"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

Shi - an embeddable ARMv7-M Forth Engine

Vinci 13.04.2019 - 15:53 230 1
Posts

Vinci

hatin' on summer
Registered: Jan 2003
Location: Wien
Posts: 5105
Grüß euch

Ich wollt mal kurz mein letztes 50/50 Privat-Arbeits-Projekt namens "Shi" vorstellen. Bei Shi handelt es sich um eine Teilimplementierung des aktuellen Forth Standards, einer sehr alten und für heutige Verhältnisse eher esoterischen Sprache. Zwar ist Forth selbst eigentlich rein prozedural, jedoch verfügt es über Metaprogramming Möglichkeiten die recht Lisp- bzw. Scheme-artig ausfallen. Ältere Semestern kommt Forth vielleicht durch die Polnische Notation (siehe HP-Taschenrechner) bekannt vor. Die Implementierung ist zu 100% in ARM Thumb2 Assembler geschrieben und damit auch nur auf ARMv7-M Prozessoren oder darüber lauffähig. Das klingt jetzt ad-hoc einmal ziemlich irre, ist aber tatsächlich die einzig vernünftige Variante wie man Forth implementieren sollte. Das hängt vor allem damit zusammen dass Forth explizit Stack-basiert ist und viele sogenannte "Wörter" (Funktionen) Dinge tun, die als klassische C/C++, etc. Funktion recht schwer und umständlich umzusetzen sind.

Der nette Nebeneffekt der ganzen Arbeit ist, dass Shi in weniger als 7kB Flash Memory passt. In diesen 7kB findet sich der komplette Interpreter/Compiler inklusive kleinen Optimierungen wie Konstantenfaltung oder Inlining.

Was Shi von so gut wie allen anderen Forths unterscheidet ist, dass Shi als Library und nicht als eigentständige Firmware (sprich als Komplettsystem) gedacht ist. Normalerweise arbeiteten Forth Programmierer mit einer REPL vergleichbar mit Python. Man tippt interaktiv irgendwelche Definitionen ein und kann diese sofort testen. Auf embedded Systemen (wie den ARMv7-M Prozessoren) wird dazu meist via serieller Schnittstelle ein Terminal zur Zielplatform aufgemacht und dort der Code hineingeklopft. Genau das tut Shi nicht und da seh ich ehrlich gesagt auch überhaupt keinen Bedarf... vor allem in Hinblick auf so übermächtige Konkurrenz wie MicroPython. Außerdem, let's face it, ist Forth eine ziemlich grausliche Sprache... Forth hat keine Objektorientierung, kein Scope, keine Kapselung und defakto überhaupt kein Typ-System.

Wozu also überhaupt der ganze Aufwand?

Najo, ein in Assembler geschriebenes natives Forth ist so ziemlich das schnellste was man auf so einer kleinen Platform nach optimiertem C Code bekommt. Mein Brötchengeber hatte vor allem Interesse daran Skripte in Echtzeit neben einer Motorregelung und einer Audioausgabe laufen zu lassen. Das war sowohl mit MicroPython als auch mit Lua ein absolut hoffnungsloses Unterfangen. Die 7kB die Shi braucht sind jedoch verkraftbar und der Compiler kann Skripte wahlweise ins interne Prozessor-RAM oder Flash compilieren. Damit das ganze möglichst komfortabel nutzbar wird gibts ein modernes C++ Interface mit dessen Hilfe sich Forth Definitionen wie normale C Funktionen aufrufen lassen. Das sieht dann in etwa so aus:
Code: C++
  // Running code
  shi::evaluate("13 29 +");

  // Same but using literal _s
  "1 -"_s;

  // Creating a new definition called "mean" and then call it through Word
  ": mean + 2 / ;"_s;
  shi::Word mean{"mean"};
  int32_t retval{mean(100, 200)};

  // Same but using literal _w
  retval = "mean"_w(100, 50);

  // Getting multiple return values by using std::tuple
  ": range 0 do i loop ;"_s;
  std::tuple<int32_t, int32_t, int32_t, int32_t> t{"range"_w(4)};

  // Creating a definition which refers to a C variable
  int32_t moore_birthday{1938};
  shi::variable(&moore_birthday, "moore_bday");
  "2019 moore_bday @ -"_s;

  // Same but using literal _v
  uint8_t moore_age;
  "moore_age"_v(&moore_age);
  "moore_age c!"_s;


Die Library inkl. Test-Suite, Benchmarks und ein paar Erklärungen gibts hier: https://gitlab.com/higaski/Shi

Auch wer mit Forth sonst nichts anfangen kann, dem empfehle ich sich mal ein wenig damit zu beschäftigen. Es ist ziemlich beeindruckend was Charles H. Moore da vor bald 50 Jahren erfunden hat und man bekommt einen Perspektivenwechsel in Bezug auf was "Reusibility" wirklich heißen kann und was 7kB sind...


/edit
Achja, ein reines C Interface gibts natürlich auch... für die armen Seelen da draußen die das wirklich noch brauchen. ;)

.Gh#Z7

Little Overclocker
Registered: May 2005
Location: AdW
Posts: 87
Impressive! Ich bin leider bei Forth komplett ausgestiegen, der Peak meiner stackbasierten Machenschaften war ein Brainfuck Interpreter/Debugger in Postscript.
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz