Make _PySignalState CRTL-aware
authorMikolaj Wielgus <wielgusmikolaj@gmail.com>
Wed, 22 Dec 2021 14:22:16 +0000 (14:22 +0000)
committerMikolaj Wielgus <wielgusmikolaj@gmail.com>
Wed, 22 Dec 2021 14:24:09 +0000 (14:24 +0000)
src/openpower/decoder/test/_pyrtl.py
src/openpower/decoder/test/pysim.py

index 07d68a965f11a6ebc2cdc076b250d7960f57dac3..bb0a38bc9af75c3c8b654f3733fb0325024e8def 100644 (file)
@@ -13,7 +13,7 @@ __all__ = ["PyRTLProcess"]
 
 
 class PyRTLProcess(BaseProcess):
-    __slots__ = ("is_comb", "runnable", "passive", "run")
+    __slots__ = ("is_comb", "runnable", "passive", "crtl")
 
     def __init__(self, *, is_comb):
         self.is_comb  = is_comb
@@ -412,25 +412,56 @@ class _StatementCompiler(StatementVisitor, _Compiler):
             emitter.append(f"slots[{signal_index}].set(next_{signal_index})")
         return emitter.flush()
 
-# TODO: for use in the linux kernel stdint.h will not be available. ok for now
-code_hdr = """\
+code_includes = """\
 #include <stdint.h>
-typedef struct slot_t
+"""
+
+code_cdef = """\
+typedef struct signal_t
 {
     uint64_t curr;
     uint64_t next;
-} slot_t;
-slot_t slots[%d] =
+} signal_t;
+
+uint64_t capture(uint64_t id);
+uint64_t get_curr(uint64_t id);
+uint64_t get_next(uint64_t id);
+void run(void);
+"""
+
+code_header = code_includes
+code_header += "\n"
+code_header += code_cdef
+code_header += """
+signal_t slots[%d] =
 {
 """
 
-code_ftr = """\
+code_footer = """\
 };
 
-static void set(slot_t *slot, uint64_t value)
+uint64_t capture(uint64_t id)
+{
+    if (slots[id].curr == slots[id].next)
+        return 0;
+
+    slots[id].curr = slots[id].next;
+
+    return 1;
+}
+
+uint64_t get_curr(uint64_t id)
+{
+    return slots[id].curr;
+}
+
+uint64_t get_next(uint64_t id)
+{
+    return slots[id].next;
+}
+
+static void set(signal_t *slot, uint64_t value)
 {
-    if (slot->next == value)
-        return;
     slot->next = value;
 }
 """
@@ -480,10 +511,10 @@ class _FragmentCompiler:
                     emitter.append(f"set(&slots[{signal_index}], next_{signal_index});")
 
             # create code header, slots, footer, followed by emit actual code
-            code = code_hdr % len(self.state.slots)
+            code = code_header % len(self.state.slots)
             for slot in self.state.slots:
-                code += "    {%s, %s},\n" % (str(slot.curr), str(slot.next))
-            code += code_ftr
+                code += "    {%s, %s},\n" % (str(slot.signal.reset), str(slot.signal.reset))
+            code += code_footer
             code += emitter.flush()
 
             try:
@@ -497,17 +528,16 @@ class _FragmentCompiler:
             file.write(code)
             file.close()
 
-            cdef = "void run(void);"
-
             ffibuilder = FFI()
-            ffibuilder.cdef(cdef)
+            ffibuilder.cdef(code_cdef)
             ffibuilder.set_source(f"crtl._{basename}",
-                                  cdef,
+                                  code_cdef,
                                   sources=[f"crtl/{basename}.c"],
                                   include_dirs=["/usr/include/python3.7m"])
             ffibuilder.compile(verbose=True)
 
-            domain_process.run = importlib.import_module(f"crtl._{basename}").lib.run
+            #domain_process.run = importlib.import_module(f"crtl._{basename}").lib.run
+            domain_process.crtl = importlib.import_module(f"crtl._{basename}").lib
             processes.add(domain_process)
 
         for subfragment_index, (subfragment, subfragment_name) in enumerate(fragment.subfragments):
index 531a7e836f1759e0b9737ab6f133c73a75c47154..9014ef8fa71cb4d65ae17706331f7e30dea4c038 100644 (file)
@@ -199,39 +199,67 @@ class _Timeline:
         return True
 
 
-class _PySignalState(BaseSignalState):
-    __slots__ = ("signal", "curr", "next", "waiters", "pending")
+class _PySignalState:
+    __slots__ = ("signal", "waiters", "pending", "_crtl", "_id", "_curr", "_next")
 
-    def __init__(self, signal, pending):
+    def __init__(self, signal, pending, id, crtl):
         self.signal = signal
         self.pending = pending
         self.waiters = dict()
-        self.curr = self.next = signal.reset
+        self._id = id
+        self._crtl = crtl 
+
+        if self._crtl is None:
+            self._curr = self._next = signal.reset
 
     def set(self, value):
-        if self.next == value:
+        if self._crtl is not None:
+            # Shouldn't be called from Python if the signal is implemented through CRTL.
+            raise NotImplementedError
+
+        if self._next == value:
             return
-        self.next = value
+
+        self._next = value
         self.pending.add(self)
 
     def commit(self):
-        if self.curr == self.next:
-            return False
-        self.curr = self.next
+        if self._crtl is not None:
+            if self._crtl.capture(self._id) == 0:
+                return False
+        else:
+            if self._curr == self._next:
+                return False
+            self._curr = self._next
 
         awoken_any = False
         for process, trigger in self.waiters.items():
             if trigger is None or trigger == self.curr:
                 process.runnable = awoken_any = True
         return awoken_any
+    
+    @property
+    def curr(self):
+        if self._crtl is not None:
+            return self._crtl.get_curr(self._id)
+        
+        return self._curr
+
+    @property
+    def next(self):
+        if self._crtl is not None:
+            return self._crtl.get_next(self._id)
 
+        return self._next
 
-class _PySimulation(BaseSimulation):
+
+class _PySimulation:
     def __init__(self):
         self.timeline = _Timeline()
         self.signals  = SignalDict()
         self.slots    = []
         self.pending  = set()
+        self.crtl = None
 
     def reset(self):
         self.timeline.reset()
@@ -243,10 +271,10 @@ class _PySimulation(BaseSimulation):
         try:
             return self.signals[signal]
         except KeyError:
-            index = len(self.slots)
-            self.slots.append(_PySignalState(signal, self.pending))
-            self.signals[signal] = index
-            return index
+            id = len(self.slots)
+            self.slots.append(_PySignalState(signal, self.pending, id, self.crtl))
+            self.signals[signal] = id
+            return id
 
     def add_trigger(self, process, signal, *, trigger=None):
         index = self.get_signal(signal)
@@ -305,7 +333,11 @@ class PySimEngine(BaseEngine):
             for process in self._processes:
                 if process.runnable:
                     process.runnable = False
-                    process.run()
+
+                    if hasattr(process, "crtl"):
+                        process.crtl.run()
+                    else:
+                        process.run()
 
             # 2. commit: apply every queued signal change, waking up any waiting processes
             converged = self._state.commit(changed)