From c92be5de9c10a78a5cc3efef928b6843ece916f6 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 22 Dec 2021 14:22:16 +0000 Subject: [PATCH] Make _PySignalState CRTL-aware --- src/openpower/decoder/test/_pyrtl.py | 66 ++++++++++++++++++++-------- src/openpower/decoder/test/pysim.py | 62 +++++++++++++++++++------- 2 files changed, 95 insertions(+), 33 deletions(-) diff --git a/src/openpower/decoder/test/_pyrtl.py b/src/openpower/decoder/test/_pyrtl.py index 07d68a96..bb0a38bc 100644 --- a/src/openpower/decoder/test/_pyrtl.py +++ b/src/openpower/decoder/test/_pyrtl.py @@ -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 -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): diff --git a/src/openpower/decoder/test/pysim.py b/src/openpower/decoder/test/pysim.py index 531a7e83..9014ef8f 100644 --- a/src/openpower/decoder/test/pysim.py +++ b/src/openpower/decoder/test/pysim.py @@ -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) -- 2.30.2