From 44f6c7bcf487159fc044e35a49ffda1d49695169 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Thu, 23 Dec 2021 00:39:04 +0000 Subject: [PATCH] Move "pending" set to C Finally something works. --- src/openpower/decoder/test/_pyrtl.py | 88 ++-------------------- src/openpower/decoder/test/pysim.py | 108 +++++++++++++++------------ 2 files changed, 69 insertions(+), 127 deletions(-) diff --git a/src/openpower/decoder/test/_pyrtl.py b/src/openpower/decoder/test/_pyrtl.py index bb0a38bc..2a241fd0 100644 --- a/src/openpower/decoder/test/_pyrtl.py +++ b/src/openpower/decoder/test/_pyrtl.py @@ -1,8 +1,4 @@ import os -import shutil -import tempfile -import importlib -from cffi import FFI from contextlib import contextmanager from nmigen.hdl.ast import SignalSet @@ -13,11 +9,10 @@ __all__ = ["PyRTLProcess"] class PyRTLProcess(BaseProcess): - __slots__ = ("is_comb", "runnable", "passive", "crtl") + __slots__ = ("is_comb", "runnable", "passive", "name", "filename", "crtl", "run") def __init__(self, *, is_comb): self.is_comb = is_comb - self.reset() def reset(self): @@ -412,60 +407,6 @@ class _StatementCompiler(StatementVisitor, _Compiler): emitter.append(f"slots[{signal_index}].set(next_{signal_index})") return emitter.flush() -code_includes = """\ -#include -""" - -code_cdef = """\ -typedef struct signal_t -{ - uint64_t curr; - uint64_t next; -} 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_footer = """\ -}; - -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) -{ - slot->next = value; -} -""" - class _FragmentCompiler: def __init__(self, state): @@ -478,8 +419,10 @@ class _FragmentCompiler: domain_stmts = LHSGroupFilter(domain_signals)(fragment.statements) domain_process = PyRTLProcess(is_comb=domain_name is None) + domain_process.name = f"{id(fragment)}_{domain_name or ''}_{index}" + emitter = _PythonEmitter() - emitter.append(f"void run(void)") + emitter.append(f"void run_{domain_process.name}(void)") with emitter.nest(): if domain_name is None: for signal in domain_signals: @@ -508,13 +451,10 @@ class _FragmentCompiler: for signal in domain_signals: signal_index = self.state.get_signal(signal) - emitter.append(f"set(&slots[{signal_index}], next_{signal_index});") + emitter.append(f"set({signal_index}, next_{signal_index});") - # create code header, slots, footer, followed by emit actual code - code = code_header % len(self.state.slots) - for slot in self.state.slots: - code += " {%s, %s},\n" % (str(slot.signal.reset), str(slot.signal.reset)) - code += code_footer + code = "#include \n" + code += "#include \"common.h\"\n" code += emitter.flush() try: @@ -522,22 +462,10 @@ class _FragmentCompiler: except FileExistsError: pass - basename = f"{id(fragment)}_{domain_name or ''}_{index}" - - file = open(f"crtl/{basename}.c", "w") + file = open(f"crtl/{domain_process.name}.c", "w") file.write(code) file.close() - ffibuilder = FFI() - ffibuilder.cdef(code_cdef) - ffibuilder.set_source(f"crtl._{basename}", - 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.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 9014ef8f..914dd8e5 100644 --- a/src/openpower/decoder/test/pysim.py +++ b/src/openpower/decoder/test/pysim.py @@ -10,6 +10,8 @@ from openpower.decoder.test._pyrtl import _FragmentCompiler from nmigen.sim._pycoro import PyCoroProcess from nmigen.sim._pyclock import PyClockProcess +import importlib +from cffi import FFI __all__ = ["PySimEngine"] @@ -200,57 +202,36 @@ class _Timeline: class _PySignalState: - __slots__ = ("signal", "waiters", "pending", "_crtl", "_id", "_curr", "_next") + __slots__ = ("signal", "waiters", "sim_state", "index") - def __init__(self, signal, pending, id, crtl): + def __init__(self, signal, index, sim_state): self.signal = signal - self.pending = pending self.waiters = dict() - self._id = id - self._crtl = crtl - - if self._crtl is None: - self._curr = self._next = signal.reset + self.index = index + self.sim_state = sim_state # Ugly. We just need it to have a reference to crtl. def set(self, 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.pending.add(self) + self.sim_state.crtl.set(self.index, value) def commit(self): - 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 + if self.sim_state.crtl.capture(self.index) == 0: + return False + # Waiters are not implemented in C yet. 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 + return self.sim_state.crtl.get_curr(self.index) @property def next(self): - if self._crtl is not None: - return self._crtl.get_next(self._id) - - return self._next + return self.sim_state.crtl.get_next(self.index) class _PySimulation: @@ -259,7 +240,7 @@ class _PySimulation: self.signals = SignalDict() self.slots = [] self.pending = set() - self.crtl = None + self.crtl = None # Initialized later. def reset(self): self.timeline.reset() @@ -271,10 +252,10 @@ class _PySimulation: try: return self.signals[signal] except KeyError: - id = len(self.slots) - self.slots.append(_PySignalState(signal, self.pending, id, self.crtl)) - self.signals[signal] = id - return id + index = len(self.slots) + self.slots.append(_PySignalState(signal, index, self)) + self.signals[signal] = index + return index def add_trigger(self, process, signal, *, trigger=None): index = self.get_signal(signal) @@ -292,14 +273,19 @@ class _PySimulation: def commit(self, changed=None): converged = True - for signal_state in self.pending: + + for pending_index in range(self.crtl.pending_count): + index = self.crtl.pending[pending_index] + signal_state = self.slots[index] + if signal_state.commit(): converged = False - if changed is not None: - changed.update(self.pending) - self.pending.clear() - return converged + if changed is not None: + changed.add(signal_state) + + self.crtl.clear_pending() + return converged class PySimEngine(BaseEngine): def __init__(self, fragment): @@ -308,6 +294,38 @@ class PySimEngine(BaseEngine): self._fragment = fragment self._processes = _FragmentCompiler(self._state)(self._fragment) + + cdef_file = open("crtl_template.h") + cdef = cdef_file.read() % (len(self._state.slots), len(self._state.slots)) + for process in self._processes: + cdef += f"void run_{process.name}(void);\n" + cdef_file.close() + + cdef_file = open("crtl/common.h", "w") + cdef_file.write(cdef) + cdef_file.close() + + src_file = open("crtl_template.c") + src = src_file.read() % (len(self._state.slots), len(self._state.slots)) + src_file.close() + + src_file = open("crtl/common.c", "w") + src_file.write(src) + src_file.close() + + ffibuilder = FFI() + ffibuilder.cdef(cdef) + ffibuilder.set_source("crtl.crtl", + cdef, + sources=["crtl/common.c"] + + [f"crtl/{process.name}.c" for process in self._processes]) + ffibuilder.compile(verbose=True) + + self._state.crtl = importlib.import_module(f"crtl.crtl").lib + for process in self._processes: + process.crtl = self._state.crtl + process.run = getattr(process.crtl, f"run_{process.name}") + self._vcd_writers = [] def add_coroutine_process(self, process, *, default_cmd): @@ -333,11 +351,7 @@ class PySimEngine(BaseEngine): for process in self._processes: if process.runnable: process.runnable = False - - if hasattr(process, "crtl"): - process.crtl.run() - else: - process.run() + process.run() # 2. commit: apply every queued signal change, waking up any waiting processes converged = self._state.commit(changed) -- 2.30.2