Skip to content

Commit e3fc438

Browse files
committed
Updated for 'source' updates (Atom post on probes)
1 parent 4088908 commit e3fc438

8 files changed

+466
-4
lines changed

archive.html

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ <h1>Archives</h1>
5050
Here you can find all my previous posts:
5151
<ul>
5252

53+
<li>
54+
<a href="./posts/2015-02-20-atom-part-2-probes.html">Atom, part 2: Probes</a> - February 20, 2015
55+
</li>
56+
5357
<li>
5458
<a href="./posts/2015-02-17-atom-examples.html">Examples for the Atom library</a> - February 17, 2015
5559
</li>

index.html

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ <h2>Welcome</h2>
5858
<h2>Posts</h2>
5959
<ul>
6060

61+
<li>
62+
<a href="./posts/2015-02-20-atom-part-2-probes.html">Atom, part 2: Probes</a> - February 20, 2015
63+
</li>
64+
6165
<li>
6266
<a href="./posts/2015-02-17-atom-examples.html">Examples for the Atom library</a> - February 17, 2015
6367
</li>

posts/2015-02-17-atom-examples.html

+1-2
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,8 @@ <h2 id="output">Atom Compiler Output</h2>
334334
...</code></pre>
335335
<p>Most lines begin with a number which is the global clock.</p>
336336
<h1 id="closing">Closing</h1>
337-
<p>Hopefully, this provided a meaningful introduction. In following posts I hope to cover some other aspects of Atom, such as:</p>
337+
<p>Hopefully, this provided a meaningful introduction. The <a href="./2015-02-20-atom-part-2-probes.html">next post</a> covers how to use probes in Atom. In future posts I hope to cover some other aspects of Atom, such as:</p>
338338
<ul>
339-
<li>Probes</li>
340339
<li>Assertions</li>
341340
<li>Coverage checking</li>
342341
<li>Internals of generated code</li>

posts/2015-02-17-atom-examples.lhs

+2-2
Original file line numberDiff line numberDiff line change
@@ -339,15 +339,15 @@ Most lines begin with a number which is the global clock.
339339
340340
Closing
341341
====
342-
Hopefully, this provided a meaningful introduction. In following posts I hope to cover some other aspects of Atom, such as:
342+
Hopefully, this provided a meaningful introduction. The [next post] covers how to use probes in Atom. In future posts I hope to cover some other aspects of Atom, such as:
343343
344-
- Probes
345344
- Assertions
346345
- Coverage checking
347346
- Internals of generated code
348347
349348
[source code]: ./2015-02-17-atom-examples.lhs
350349
[last post]: ./2015-02-06-how-i-got-here.html
350+
[next post]: ./2015-02-20-atom-part-2-probes.html
351351
352352
[hawkins]: http://tomahawkins.org/
353353
[hawkins-hybrids]: http://cufp.galois.com/2008/slides/HawkinsTom.pdf "Controlling Hybrid Vehicles with Haskell. Hawkins, T. (2008)."

posts/2015-02-20-atom-part-2-probes.html

+241
Large diffs are not rendered by default.
+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
Probes
2+
====
3+
4+
The [last post][] introduced [Atom][atom-hackage] with a simple example that I used to cover the basics. I'm going to extend this to cover [probes][hackage-probe]. Probes are a bit vague. The only explicit information I can find is:
5+
6+
- A [StackOverflow][stackoverflow-haskell] reply from [Tom Hawkins][hawkins] - Atom's author, incidentally.
7+
- The Atom source code, [here](http://hackage.haskell.org/package/atom-1.0.12/docs/src/Language-Atom-Language.html#probe) and [here](http://hackage.haskell.org/package/atom-1.0.12/docs/src/Language-Atom-Elaboration.html#elaborate).
8+
9+
Here is my own working definition after some examples: *A probe allows inspecting any expression in Atom, remotely to its context, and at any desired rate.*
10+
11+
The type signature suggests that inserting a probe is a matter of inserting [probe][hackage-probe] anywhere inside of an Atom specification, along with a probe name and an expression, and that accessing probes is a matter of examining [probes][hackage-probes].
12+
13+
The preamble is identical to the prior example:
14+
15+
> module Main where
16+
>
17+
> import Language.Atom
18+
> import Language.Atom.Unit
19+
> import GHC.Word
20+
> import GHC.Int
21+
>
22+
> main :: IO ()
23+
> main = do
24+
> (sched, _, _, _, _) <- compile "atom_example2" atomCfg example
25+
> putStrLn $ reportSchedule sched
26+
>
27+
> atomCfg :: Config
28+
> atomCfg = defaults { cFuncName = "atom_tick"
29+
> , cStateName = "state_example"
30+
> , cCode = prePostCode
31+
> , hCode = prePostHeader
32+
> , cRuleCoverage = False
33+
> }
34+
35+
In the last post I ignored the arguments to the functions set in `cCode` and `hCode` in [Config](http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Code.html#t:Config). The third argument is a list of probes along with their types.
36+
37+
The below code is identical, save for three changes:
38+
39+
- The definition of `probeStr` which turns a probe name & type into a String.
40+
- Assigning a name `probeList` to the `[(Name,Type)]` argument in `prePostCode`.
41+
- Appending `map probeStr probeList` to the list. This serves no functional purpose, it just adds comments into the code to illustrate what probes are present.
42+
43+
> probeStr :: (Name, Type) -> String
44+
> probeStr (n, t) = "// Probe: " ++ n ++ ", type: " ++ show t
45+
>
46+
> prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
47+
> prePostCode _ _ probeList =
48+
> ( unlines $ [ "// ---- This source is automatically generated by Atom ----"
49+
> , "#include <stdlib.h>"
50+
> , "#include <stdio.h>"
51+
> , "#include <unistd.h>"
52+
> , ""
53+
> , "bool g_sensor_ready;"
54+
> , "uint16_t g_sensor_value;"
55+
> , "void sensor_on(void);"
56+
> , "void sensor_off(void);"
57+
> , "void sensor_trigger(void);"
58+
> , ""
59+
> ] ++ map probeStr probeList
60+
> , unlines [ "int main(void) {"
61+
> , " while (true) {"
62+
> , " atom_tick();"
63+
> , " usleep(1000);"
64+
> , " }"
65+
> , " return 0;"
66+
> , "}"
67+
> , "void sensor_on(void) {"
68+
> , " printf(\"%lu: sensor_on()\\n\", __global_clock);"
69+
> , "}"
70+
> , ""
71+
> , "void sensor_off(void) {"
72+
> , " printf(\"%lu: sensor_off()\\n\", __global_clock);"
73+
> , "}"
74+
> , ""
75+
> , "void sensor_trigger(void) {"
76+
> , " if (rand() % 4) {"
77+
> , " g_sensor_value = rand();"
78+
> , " g_sensor_ready = true;"
79+
> , " printf(\"%lu: Triggered sensor, value=%u\\n\","
80+
> , " __global_clock, g_sensor_value);"
81+
> , " }"
82+
> , "}"
83+
> , ""
84+
> , "// ---- End automatically-generated source ----"
85+
> ])
86+
>
87+
> prePostHeader :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
88+
> prePostHeader _ _ _ =
89+
> ( unlines [ "// ---- This header is automatically generated by Atom ----"
90+
> ]
91+
> , unlines [ "// ---- End automatically-generated header ----"
92+
> ])
93+
94+
95+
I reordered things from the last example to give some simpler definitions first. First I add a probe into `tickSecond` for the value of `clock` (which thus far I have not done anything with):
96+
97+
> tickSecond :: Atom (V Word64)
98+
> tickSecond = do
99+
> clock <- word64 "clock_sec" 0
100+
> probe "Clock" $ value clock
101+
> period 1000 $ exactPhase 0 $ atom "second" $ incr clock
102+
> return clock
103+
104+
And a probe into `checkSensor` for the value of `sensorValue`:
105+
106+
> checkSensor :: Word16 -> Atom () -> Atom ()
107+
> checkSensor threshold overThresholdAction = atom "check_sensor" $ do
108+
> ready <- return $ bool' "g_sensor_ready"
109+
> sensorValue <- return $ word16' "g_sensor_value"
110+
> warmup <- timer "warmup"
111+
> triggered <- bool "triggered" False
112+
> sensorOn <- bool "sensor_on" False
113+
>
114+
> probe "Sensor Value" $ value sensorValue
115+
>
116+
> period 2000 $ phase 500 $ atom "powerOn" $ do
117+
> call "sensor_on"
118+
> triggered <== false
119+
> ready <== false
120+
> sensorOn <== true
121+
> startTimer warmup $ Const 10
122+
>
123+
> atom "trigger" $ do
124+
> cond $ timerDone warmup &&. not_ (value triggered) &&. value sensorOn
125+
> triggered <== true
126+
> call "sensor_trigger"
127+
>
128+
> atom "checkSensorValue" $ do
129+
> cond $ value ready
130+
> ready <== false
131+
> sensorOn <== false
132+
> call "sensor_off"
133+
> atom "checkThreshold" $ do
134+
> cond $ value sensorValue >. Const threshold
135+
> overThresholdAction
136+
>
137+
> period 2000 $ phase 550 $ atom "powerOff" $ do
138+
> cond $ value sensorOn
139+
> ready <== false
140+
> printStrLn "Sensor timeout."
141+
> call "sensor_off"
142+
143+
I can access all probes via [probes][hackage-probes], but given its type signature, some conversion is necessary:
144+
```haskell
145+
probes :: Atom [(String, UE)]
146+
```
147+
148+
Primarily, that `UE` ('untyped expression') needs to be turned to something else to be useful. Luckily, [typeOf](http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Expressions.html#v:typeOf) gives its type as a [Language.Atom.Expressions.Type](http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Expressions.html#t:Type), and then the [Retype](http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Expressions.html#v:Retype) constructor can convert it accordingly.
149+
150+
I'm not sure what else I can easily tell Atom to do with an expression, so I just pass it to [printIntegralE](http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Unit.html#v:printIntegralE). I'm sure a suitably motivated individual could make more interesting functionality. I come up with this slightly hackish Haskell function for printing a probe's value:
151+
152+
*(Do you have a cleaner version? Show me.)*
153+
154+
> printProbe :: (String, UE) -> Atom ()
155+
> printProbe (str, ue) = case typeOf ue of
156+
> Int8 -> ps (ru :: E Int8)
157+
> Int16 -> ps (ru :: E Int16)
158+
> Int32 -> ps (ru :: E Int32)
159+
> Int64 -> ps (ru :: E Int64)
160+
> Word8 -> ps (ru :: E Word8)
161+
> Word16 -> ps (ru :: E Word16)
162+
> Word32 -> ps (ru :: E Word32)
163+
> Word64 -> ps (ru :: E Word64)
164+
> where ps :: IntegralE a => E a -> Atom ()
165+
> ps = printIntegralE str
166+
> ru :: IntegralE a => E a
167+
> ru = Retype ue
168+
169+
Finally, in `example` I add in a rule `monitor` to print all the probe values. For sanity's sake, the period is 100 for a rate of every 1/10 second rather than at the base rate.
170+
171+
> example :: Atom ()
172+
> example = do
173+
>
174+
> clock <- tickSecond
175+
>
176+
> checkSensor 40000 $ do
177+
> printStrLn "Sensor value over threshold!"
178+
>
179+
> period 100 $ atom "monitor" $ do
180+
> mapM_ printProbe =<< probes
181+
>
182+
183+
In the end the monitor C code looks like this:
184+
```c
185+
/* atom_example2.monitor */
186+
static void __r6() {
187+
bool __0 = true;
188+
uint16_t __1 = g_sensor_value;
189+
uint64_t __2 = state_example.atom_example2.clock_sec;
190+
if (__0) {
191+
printf("Sensor Value: %i\n", __1);
192+
printf("Clock: %i\n", __2);
193+
}
194+
}
195+
```
196+
197+
Fairly simple, but I can see how it would be useful.
198+
199+
[source code]: ./2015-02-20-atom-part-2.lhs
200+
[last post]: ./2015-02-17-atom-examples.html
201+
[atom-hackage]: http://hackage.haskell.org/package/atom "atom: A DSL for embedded hard realtime applications. (hackage)"
202+
[atom-github]: https://github.com/tomahawkins/atom "atom: A DSL for embedded hard realtime applications. (github)"
203+
[hawkins]: http://tomahawkins.org/
204+
[stackoverflow-haskell]: https://stackoverflow.com/questions/1263711/using-haskell-for-sizable-real-time-systems-how-if#answer-1582191 "Using Haskell for sizable real-time systems: how (if?)?"
205+
[hackage-probe]: http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Language.html#v:probe
206+
[hackage-probes]: http://hackage.haskell.org/package/atom-1.0.12/docs/Language-Atom-Language.html#v:probes

tags/atom.html

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ <h1>Posts tagged "atom"</h1>
4949

5050
<ul>
5151

52+
<li>
53+
<a href="../posts/2015-02-20-atom-part-2-probes.html">Atom, part 2: Probes</a> - February 20, 2015
54+
</li>
55+
5256
<li>
5357
<a href="../posts/2015-02-17-atom-examples.html">Examples for the Atom library</a> - February 17, 2015
5458
</li>

tags/haskell.html

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ <h1>Posts tagged "haskell"</h1>
4949

5050
<ul>
5151

52+
<li>
53+
<a href="../posts/2015-02-20-atom-part-2-probes.html">Atom, part 2: Probes</a> - February 20, 2015
54+
</li>
55+
5256
<li>
5357
<a href="../posts/2015-02-17-atom-examples.html">Examples for the Atom library</a> - February 17, 2015
5458
</li>

0 commit comments

Comments
 (0)