diff --git a/generator/coder/syscall_fsm.py b/generator/coder/syscall_fsm.py
index ee0cd2261337fbbfb5e9987b13db205f7a3111d3..a7f82f248de7eaa4c42564705dc49c6117bd2b56 100644
--- a/generator/coder/syscall_fsm.py
+++ b/generator/coder/syscall_fsm.py
@@ -10,11 +10,15 @@ import logging
 
 
 class FSMSystemCalls(FullSystemCalls):
-    def __init__(self):
+    def __init__(self, use_pla = False):
         super(FSMSystemCalls, self).__init__()
 
         self.alarms = FSMAlarmTemplate
-        self.fsm_template = SimpleFSMTemplate
+        if use_pla:
+            self.fsm_template = PLA_FSMTemplate
+        else:
+            self.fsm_template = SimpleFSMTemplate
+
 
     def generate_system_code(self):
         self.generator.source_file.include("syscall.h")
@@ -178,7 +182,6 @@ class SimpleFSMTemplate(CodeTemplate):
         def action_rename(action):
             task_id = action.impl.task_id
             if task_id == None:
-                print(action.subtask)
                 task_id = 255
             return task_id
         self.fsm.rename(actions = action_rename)
@@ -266,8 +269,100 @@ class SimpleFSMTemplate(CodeTemplate):
             ret.append(self.expand_snippet(body))
         return ret
 
+class PLA_FSMTemplate(CodeTemplate):
+    def __init__(self, syscall_fsm):
+        CodeTemplate.__init__(self, syscall_fsm.generator, "os/fsm/pla-fsm.h.in")
+        self.syscall_fsm = syscall_fsm
+        self.system_graph = self.generator.system_graph
+        self.logic = self.system_graph.get_pass("LogicMinimizer")
+        self.fsm = self.logic.fsm
+
+    def add_transition_table(self):
+        # Truth table is generated in pla-fsm.h
+        return
+
+
+    def fsm_event(self, syscall, userspace, kernelspace):
+        event = None
+        for ev in self.fsm.events:
+            if self.fsm.event_mapping[ev.name] == syscall:
+                event = ev
+                break
+        if not event:
+            return # No Dispatch
+        # kernelspace.add(Statement('kout << "%s" << endl' % syscall.path()))
+        task = self.syscall_fsm.call_function(kernelspace, "os::fsm::fsm_engine.event",
+                                              "unsigned", [str(int(event.name, 2))])
+        return task
+
+    def fsm_schedule(self, syscall, userspace, kernelspace):
+        task = self.fsm_event(syscall, userspace, kernelspace)
+        if not task:
+            return
+        if type(task) == int:
+            self.syscall_fsm.call_function(kernelspace, "os::fsm::fsm_engine.dispatch",
+                                           "void", [str(task)])
+        else:
+            self.syscall_fsm.call_function(kernelspace, "os::fsm::fsm_engine.dispatch",
+                                           "void", [task.name])
+
+    def fsm_iret(self, syscall, userspace, kernelspace):
+        task = self.fsm_event(syscall, userspace, kernelspace)
+        if not task:
+            return
+
+        if type(task) == int:
+            self.syscall_fsm.call_function(kernelspace, "os::fsm::fsm_engine.iret",
+                                           "void", [str(task)])
+        else:
+            self.syscall_fsm.call_function(kernelspace, "os::fsm::fsm_engine.iret",
+                                           "void", [task.name])
+
+    ################################################################
+    # Used in Template Code
+    ################################################################
+    def truth_table(self, *args):
+        # Generate the transition table
+        initializer = []
+        for (mask, pattern, output_state, output_action) in self.logic.truth_table:
+            initializer.append("{{{0}, {1}, {2}, {3}}}".format(
+                int(mask, 2),
+                int(pattern, 2),
+                int(output_state, 2),
+                int(output_action, 2)))
+
+        return "{" + (", ".join(initializer)) + "}"
+
+    def mask_pattern_len(self, *args):
+        return str(self.logic.event_len + self.logic.state_len)
+
+    def truth_table_entries(self, *args):
+        return str(len(self.logic.truth_table))
+
+    def initial_state(self, *args):
+        return str(int(self.fsm.initial_state,2))
+
+    def dispatch_table(self, *args):
+        mapping = {}
+        for k, subtask in self.fsm.action_mapping.items():
+            mapping[int(k, 2)] = subtask
+        if not 0 in mapping:
+            mapping[0] = None
+        self.NO_DISPATCH = 0
+
+        initializer = []
+        for k,subtask in sorted(mapping.items(), key = lambda x:x[0]):
+            if not subtask or subtask.conf.is_isr:
+                initializer.append("0 /* NO_DISPATCH */")
+            elif subtask == self.system_graph.idle_subtask:
+                initializer.append("0 /* IDLE */")
+                self.IDLE = k
+            else:
+                initializer.append("&" +subtask.impl.task_descriptor.name)
+        if not hasattr(self, "IDLE"):
+            self.IDLE = len(mapping) + 100
+        return ", ".join(initializer)
 
 class FSMAlarmTemplate(AlarmTemplate):
     def __init__(self, rules):
         AlarmTemplate.__init__(self, rules)
-
diff --git a/generator/main.py b/generator/main.py
index e75db2114bfcbd121347a1ce89bc50a230f76ef2..d91ec7f6f98b340015ba7799c3874c13b0adbd74 100755
--- a/generator/main.py
+++ b/generator/main.py
@@ -188,7 +188,7 @@ if __name__ == "__main__":
     else:
         os_rules = EncodedOS()
 
-    assert options.systemcalls in ("full", "specialized", "fsm")
+    assert options.systemcalls in ("full", "specialized", "fsm", "fsm:pla")
 
     if options.systemcalls == "specialized":
         # Only when we want to specialize the system calls, run the
@@ -201,7 +201,13 @@ if __name__ == "__main__":
         logging.info("Global control flow information is provided by %s",
                      global_abb_information.name())
         syscall_rules = SpecializedSystemCalls(global_abb_information)
+    elif options.systemcalls == "fsm:pla":
+        assert options.arch == "posix", "FSM Encoding is only supported for arch=posix"
+        pass_manager.enqueue_analysis("LogicMinimizer")
+        pass_manager.enqueue_analysis("fsm")
+        syscall_rules = FSMSystemCalls(use_pla = True)
     elif options.systemcalls == "fsm":
+        assert options.arch == "posix", "FSM Encoding is only supported for arch=posix"
         pass_manager.enqueue_analysis("fsm")
         syscall_rules = FSMSystemCalls()
     else:
diff --git a/generator/transform/FiniteStateMachineBuilder.py b/generator/transform/FiniteStateMachineBuilder.py
index d06e0d4e47206e498b0dd72449cbaea55a1d662f..01d155fcd3e089b5ed140fa602ba2d5f9ea54748 100644
--- a/generator/transform/FiniteStateMachineBuilder.py
+++ b/generator/transform/FiniteStateMachineBuilder.py
@@ -20,7 +20,7 @@ class Transition:
             return self._event.name
 
     def __repr__(self):
-        return "<Transition(%s) %d -> %d: %s>" %(self.event, self.source, self.target, self.action)
+        return "<Transition(%s) %s -> %s: %s>" %(self.event, self.source, self.target, self.action)
 
 
 class Event:
diff --git a/generator/transform/LogicMinimizer.py b/generator/transform/LogicMinimizer.py
index df5d807ed60a880c68f16c4e40e9587318d459f2..e346b66bd78ebb4f173ad09af38ebe06416a2316 100644
--- a/generator/transform/LogicMinimizer.py
+++ b/generator/transform/LogicMinimizer.py
@@ -15,7 +15,6 @@ class LogicMinimizer(Analysis):
 
     def do(self):
         fsm = self.system_graph.get_pass("fsm").fsm.copy()
-
         self.fsm = self.call_nova(fsm)
 
     def call_nova(self, fsm):
@@ -74,6 +73,8 @@ class LogicMinimizer(Analysis):
             fd.write(".e\n")
 
         stdout = subprocess.check_output(["nova", nova_input]).decode('ascii', 'ignore')
+        with open("%s.nova.stdout" % nova_input, "w+") as fd:
+            fd.write(stdout)
         event_mapping = {}
         state_mapping = {}
         for line in stdout.split("\n"):
@@ -134,5 +135,9 @@ class LogicMinimizer(Analysis):
                     got_output_word |= output_word
                     matches[i] += 1
             assert got_output_word == desired_output_word
+
+        #for transition in fsm.transitions:
+        #    print(transition, fsm.event_mapping[transition.event], fsm.action_mapping[transition.action])
+
         logging.info("%d lines in minimzed truth table", len(self.truth_table))
         return fsm
diff --git a/os/fsm/pla-fsm.h.in b/os/fsm/pla-fsm.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..e416a64265553e89db3d5c397d2f08d1f8f75f60
--- /dev/null
+++ b/os/fsm/pla-fsm.h.in
@@ -0,0 +1,68 @@
+#include "dispatch.h"
+
+namespace os {
+namespace fsm {
+
+constexpr const os::scheduler::Task  * dispatch_table[] = {
+	{{{!dispatch_table}}}
+};
+
+
+class SchedulerFSM {
+ public:
+	struct Row {
+		unsigned mask : {{{!mask_pattern_len}}};
+		unsigned pattern : {{{!mask_pattern_len}}};
+		unsigned output_state : {{{!get:logic.state_len}}};
+		unsigned output_action : {{{!get:logic.action_len}}};
+	} __attribute__((packed));
+
+    enum {
+		IDLE = {{{!get:IDLE}}},
+		NO_DISPATCH = {{{!get:NO_DISPATCH}}},
+	};
+
+	SchedulerFSM(unsigned state) : internal_state(state) {}
+
+	unsigned event(unsigned event) {
+		unsigned input_word = event << {{{!get:logic.state_len}}} | internal_state;
+		unsigned output_state = 0, output_action = 0;
+		for (unsigned i = 0; i < {{{!truth_table_entries}}}; i++) {
+			if ((truth_table[i].mask & input_word) == truth_table[i].pattern) {
+				output_state |= truth_table[i].output_state;
+				output_action |= truth_table[i].output_action;
+			}
+		}
+		internal_state = output_state;
+		return output_action;
+	}
+
+	void dispatch(unsigned task_id) {
+		if (task_id == IDLE) {
+			arch::Dispatcher::idle();
+		} else if (task_id == NO_DISPATCH) {
+			return;
+		} else if (task_id >= sizeof(dispatch_table)/sizeof(*dispatch_table)) {
+			CALL_HOOK(FaultDetectedHook, LOGIC_ERRORdetected, 0, 0);
+		} else {
+			arch::Dispatcher::Dispatch(*dispatch_table[task_id]);
+		}
+	}
+
+	void iret(unsigned task_id) {
+		if (task_id != NO_DISPATCH && task_id != IDLE) {
+           dispatch(task_id);
+	    }
+	}
+
+ private:
+	unsigned internal_state : {{{!get:logic.state_len}}};
+	static Row truth_table[{{{!truth_table_entries}}}];
+};
+
+SchedulerFSM fsm_engine({{{!initial_state}}});
+SchedulerFSM::Row SchedulerFSM::truth_table[] = {{{!truth_table}}};
+
+
+}
+}