From cce8a4cfa4513d57603d7eb6d5abba17e536e719 Mon Sep 17 00:00:00 2001
From: Rahix <rahix@rahix.de>
Date: Sun, 21 Jul 2019 19:45:19 +0200
Subject: [PATCH] feat(genapi): Autogenerate IRQ stubs

Signed-off-by: Rahix <rahix@rahix.de>
---
 epicardium/api/genapi.py | 86 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 2 deletions(-)

diff --git a/epicardium/api/genapi.py b/epicardium/api/genapi.py
index a528c0cf..12f26b2d 100644
--- a/epicardium/api/genapi.py
+++ b/epicardium/api/genapi.py
@@ -5,11 +5,16 @@ import subprocess
 import sys
 
 
-MATCH_EXPANSION = re.compile(
+MATCH_API_EXPANSION = re.compile(
     r"__GENERATE_API \$ __GEN_ID_(?P<id>\w+) \$ (?P<decl>.*?) \$",
     re.DOTALL | re.MULTILINE,
 )
 
+MATCH_ISR_EXPANSION = re.compile(
+    r"__GENERATE_API_ISR \$ __GEN_ID_(?P<id>\w+) \$ (?P<isr>.*?) \$",
+    re.DOTALL | re.MULTILINE,
+)
+
 MATCH_DECLARATION = re.compile(
     r"^(?P<typename>.*?)\s*\((?P<args>.*)\)$",
     re.DOTALL,
@@ -34,7 +39,7 @@ def bailout(message, *args, **kwargs):
 def parse_declarations(source):
     """Parse all declarations in the given source."""
     declarations = []
-    for exp in MATCH_EXPANSION.finditer(source):
+    for exp in MATCH_API_EXPANSION.finditer(source):
         id = exp.group("id")
         decl = MATCH_DECLARATION.match(exp.group("decl"))
 
@@ -76,6 +81,21 @@ def parse_declarations(source):
     return declarations
 
 
+def parse_interrupts(source):
+    """Parse all isr declarations in the given source."""
+    interrupts = []
+    for exp in MATCH_ISR_EXPANSION.finditer(source):
+        id = exp.group("id")
+        isr = exp.group("isr")
+
+        interrupts.append({
+            "id": id,
+            "isr": isr,
+        })
+
+    return interrupts
+
+
 def main():
     parser = argparse.ArgumentParser(
         description="Generate the API stubs from a header file."
@@ -98,6 +118,7 @@ def main():
     # a way we can find later on.
     api_src = """\
 #define API(id, def) __GENERATE_API $ __GEN_ID_##id $ def $
+#define API_ISR(id, isr) __GENERATE_API_ISR $ __GEN_ID_##id $ isr $
 #include "{header}"
 """.format(
         header=os.path.relpath(args.header)
@@ -109,6 +130,8 @@ def main():
     ).decode()
 
     declarations = parse_declarations(source)
+    interrupts = parse_interrupts(source)
+
     fmt_header = {
         "header": os.path.basename(args.header)
     }
@@ -118,6 +141,7 @@ def main():
         tmp = """\
 #include <stdio.h>
 
+#define API_ISR(id, isr)
 #include "{header}"
 #include "api/caller.h"
 """
@@ -160,6 +184,64 @@ def main():
 }}
 """
                 f_client.write(tmp.format(**decl))
+
+        tmp = """\
+
+
+/* Weakly linked stubs for ISRs */
+"""
+        f_client.write(tmp)
+
+        for isr in interrupts:
+            tmp = """\
+void {isr}(api_int_id_t id)
+        __attribute__((weak, alias("__epic_isr_default_handler")));
+"""
+            f_client.write(tmp.format(**isr))
+
+        tmp = """\
+
+/* Default handler stub */
+__attribute__((weak)) void epic_isr_default_handler(api_int_id_t id)
+{
+        ;
+}
+
+/*
+ * This function is needed because aliasing the weak default handler will
+ * lead to issues.
+ */
+void __epic_isr_default_handler(api_int_id_t id)
+{
+        epic_isr_default_handler(id);
+}
+
+/*
+ * __dispatch_isr() will be called from the actual isr which was triggered
+ * by core 0.  It will then call the appropriate isr.
+ */
+void __dispatch_isr(api_int_id_t id)
+{
+        switch (id) {
+"""
+        f_client.write(tmp)
+
+        for isr in interrupts:
+            tmp = """\
+        case {id}:
+                {isr}(id);
+                break;
+"""
+            f_client.write(tmp.format(**isr))
+
+        tmp = """\
+        default:
+                epic_isr_default_handler(id);
+                break;
+        }
+}
+"""
+        f_client.write(tmp)
     # END: Generate Client }}}
 
     # Generate Dispatcher {{{
-- 
GitLab