views:

710

answers:

5

I've been curious to understand if it is possible to apply the power of Haskell to embedded realtime world, and in googling have found the Atom package. I'd assume that in the complex case the code might have all the classical C bugs - crashes, memory corruptions, etc, which would then need to be traced to the original Haskell code that caused them. So, this is the first part of the question: "If you had the experience with Atom, how did you deal with the task of debugging the low-level bugs in compiled C code and fixing them in Haskell original code ?"

I searched for some more examples for Atom, this blog post mentions the resulting C code 22KLOC (and obviously no code:), the included example is a toy. This and this references have a bit more practical code, but this is where this ends. And the reason I put "sizable" in the subject is, I'm most interested if you might share your experiences of working with the generated C code in the range of 300KLOC+.

As I am a Haskell newbie, obviously there may be other ways that I did not find due to my unknown unknowns, so any other pointers for self-education in this area would be greatly appreciated - and this is the second part of the question - "what would be some other practical methods (if) of doing real-time development in Haskell?". If the multicore is also in the picture, that's an extra plus :-)

(About usage of Haskell itself for this purpose: from what I read in this blog post, the garbage collection and laziness in Haskell makes it rather nondeterministic scheduling-wise, but maybe in two years something has changed. Real world Haskell programming question on SO was the closest that I could find to this topic)

Thanks a lot for sharing the wisdom!

p.s. "real-time" above is would be closer to "hard realtime" - I'm curious if it is possible to ensure that the pause time when the main task is not executing is under 0.5ms.

EDIT: I marked the answer from dons as accepted since it did reflect very much on what I was looking for - however, any additional information from the practical experience is very much welcome. I am going to make it a community wiki if there is sufficient amount of additional info.

+2  A: 

It will be a long time before there is a Haskell system that fits in small memory and can guarantee sub-millisecond pause times. The community of Haskell implementors just doesn't seem to be interested in this kind of target.

There is healthy interest in using Haskell or something Haskell-like to compile down to something very efficient; for example, Bluespec compiles to hardware.

I don't think it will meet your needs, but if you're interested in functional programming and embedded systems you should learn about Erlang.

Norman Ramsey
+1 for the bluespec link. Will be interesting to compare it to Lava - from what I've read, it has similar function. Erlang: yes, that's another thing I started to peek my nose into, but it seems to be a bit of a "softer" real-time.
Andrew Y
You might also take a look at Ocaml. It's functional and even supports lazy evaluation if you want it for an algorithm, but doesn't force everything to be evaluated lazily. I seem to recall hearing of it being used for realtime systems, though I haven't done so myself. It should be faster and smaller than Erlang, anyway.
Chuck
OCaml, Erlang and Haskell all get used for soft realtime. None make guarantees about response times for example.In one system we use at work, we happly have ~1ms response times on a network device in Haskell, so that's the sort of ball park. Tuning the GC settings to minimize noise is also useful.
Don Stewart
Thanks for mention of OCaml. My subjective feeling from playing with Ocaml code was a bit mixed. The trivial examples of adding two numbers requires me to remember extra language features which I feel are an overhead, whereas the experiments with Haskell require me to remember the language features that can express the things in a more succint way (list comprehensions, for example) - or are very special beasts altogether (monads). This is subjective and I'd need to get more experience with either to gain more understanding - but the first impressions are hard to fight. :)
Andrew Y
+1  A: 

I don't think Haskell, or other Garbage Collected languages are very well-suited to hard-realtime systems, as GC's tend to amortize their runtimes into short pauses.

Writing in Atom is not exactly programming in Haskell, as Haskell here can be seen as purely a preprocessor for the actual program you are writing.

I think Haskell is an awesome preprocessor, and using DSEL's like Atom is probably a great way to create sizable hard-realtime systems, but I don't know if Atom fits the bill or not. If it doesn't, I'm pretty sure it is possible (and I encourage anyone who does!) to implement a DSEL that does.

Having a very strong pre-processor like Haskell for a low-level language opens up a huge window of opportunity to implement abstractions through code-generation that are much more clumsy when implemented as C code text generators.

Peaker
I was curious if you had a working experience with working with such a combo. Like I said - metaprogramming aspect does look seductive, but I'm concerned of the meta-bugs and their relationship with lower-level "ordinary" bugs. Since in the field you would only have the symbols of the C code, at first sight it would seem tricky to unwind them back to the higher-level code.
Andrew Y
> Atom is probably a great way to create sizable hard-realtime systems,it's not really a "preprocessor" ifit offers a grammar, variables, functions and a type system. At that point it really becomes a language with a custom code generator, as Atom is.As for creating sizeable systems: Atom is used in buses and garbage trucks running on the streets of US cities. See Eaton's talk at CUFP about this. If putting Haskell EDSLs onto the streets isn't ready for prodution, I don't know what is.
Don Stewart
@dons: ok, this gets +1 in my book as well at a minimum thanks to your comment. Muchas gracias for sharing the practical experience. Time to for me to take a break and do more practicing.
Andrew Y
+1  A: 

At Galois we use Haskell for two things:

  • Soft real time (OS device layers, networking), where 1-5 ms response times are plausible. GHC generates fast code, and has plenty of support for tuning the GC and scheduler to get the right timings.
  • for true real time systems EDSLs are used to generate code for other languages that provide stronger timing guarantees. We've started exploring Atom, and use Cryptol in house for similar things.

So be careful to distinguish the EDSL (Atom) from the host language (Haskell).

Don Stewart
awesome, thank you very much! Yes, I understand the difference between the EDSL used as a code generator and the host language itself - sorry if I was unclear in the text of the question. My reason for putting it into "in haskell" category was that using a stricter language like Haskell one might (?) avoid the more "mechanical" bugs like boundary checks, double frees, etc., assuming enough of the semantics is expressed within the EDSL - that's one of my speculations that I am trying to understand whether it is true or false.
Andrew Y
+1  A: 

Andrew,

Yes, it can be tricky to debug problems through the generated code back to the original source. One thing Atom provides is a means to probe internal expressions, then leaves if up to the user how to handle these probes. For vehicle testing, we build a transmitter (in Atom) and stream the probes out over a CAN bus. We can then capture this data, formated it, then view it with tools like GTKWave, either in post-processing or realtime. For software simulation, probes are handled differently. Instead of getting probe data from a CAN protocol, hooks are made to the C code to lift the probe values directly. The probe values are then used in the unit testing framework (distributed with Atom) to determine if a test passes or fails and to calculate simulation coverage.

Tom
Thanks a lot for the info!
Andrew Y
+1  A: 

I've been fooling around with Atom. It is pretty cool, but I think it is best for small systems. Yes it runs in trucks and buses and implements real-world, critical applications, but that doesn't mean those applications are necessarily large or complex. It really is for hard-real-time apps and goes to great lengths to make every operation take the exact same amount of time. For example, instead of an if/else statement that conditionally executes one of two code branches that might differ in running time, it has a "mux" statement that always executes both branches before conditionally selecting one of the two computed values (so the total execution time is the same whichever value is selected). It doesn't have any significant type system other than built-in types (comparable to C's) that are enforced through GADT values passed through the Atom monad. The author is working on a static verification tool that analyzes the output C code, which is pretty cool (it uses an SMT solver), but I think Atom would benefit from more source-level features and checks. Even in my toy-sized app (LED flashlight controller), I've made a number of newbie errors that someone more experienced with the package might avoid, but that resulted in buggy output code that I'd rather have been caught by the compiler instead of through testing. On the other hand, it's still at version 0.1.something so improvements are undoubtedly coming.

solrize
+1, Thanks a lot for sharing. Let's look forward for the next versions! :-)
Andrew Y