From de07d43dd31e5b05c361c0cb6825431e92992d8f Mon Sep 17 00:00:00 2001 From: Marek Materzok Date: Tue, 11 Jul 2023 21:53:54 +0200 Subject: [PATCH] Method run debugging (#432) --- coreblocks/transactions/core.py | 54 ++++++++++++++++++++++++--------- test/common.py | 10 +++--- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/coreblocks/transactions/core.py b/coreblocks/transactions/core.py index 7d4ea233f..8449a50a3 100644 --- a/coreblocks/transactions/core.py +++ b/coreblocks/transactions/core.py @@ -189,9 +189,7 @@ def add_transaction(self, transaction: "Transaction"): self.transactions.append(transaction) @staticmethod - def _conflict_graph( - method_map: MethodMap, relations: list[Relation] - ) -> Tuple[TransactionGraph, TransactionGraph, PriorityOrder]: + def _conflict_graph(method_map: MethodMap) -> Tuple[TransactionGraph, TransactionGraph, PriorityOrder]: """_conflict_graph This function generates the graph of transaction conflicts. Conflicts @@ -252,6 +250,12 @@ def add_edge(begin: Transaction, end: Transaction, priority: Priority, conflict: if transaction1 is not transaction2: add_edge(transaction1, transaction2, Priority.UNDEFINED, True) + relations = [ + Relation(**relation, start=elem) + for elem in method_map.methods_and_transactions + for relation in elem.relations + ] + for relation in relations: start = relation["start"] end = relation["end"] @@ -408,12 +412,7 @@ def elaborate(self, platform): merge_manager = self._simultaneous() method_map = MethodMap(self.transactions) - relations = [ - Relation(**relation, start=elem) - for elem in method_map.methods_and_transactions - for relation in elem.relations - ] - cgr, rgr, porder = TransactionManager._conflict_graph(method_map, relations) + cgr, rgr, porder = TransactionManager._conflict_graph(method_map) m = Module() m.submodules.merge_manager = merge_manager @@ -460,6 +459,25 @@ def visual_graph(self, fragment): return graph + def debug_signals(self) -> SignalBundle: + method_map = MethodMap(self.transactions) + cgr, _, _ = TransactionManager._conflict_graph(method_map) + + def transaction_debug(t: Transaction): + return ( + [t.request, t.grant] + + [m.ready for m in method_map.methods_by_transaction[t]] + + [t2.grant for t2 in cgr[t]] + ) + + def method_debug(m: Method): + return [m.ready, m.run, {t.name: transaction_debug(t) for t in method_map.transactions_by_method[m]}] + + return { + "transactions": {t.name: transaction_debug(t) for t in method_map.transactions}, + "methods": {m.owned_name: method_debug(m) for m in method_map.methods}, + } + class TransactionContext: stack: list[TransactionManager] = [] @@ -657,6 +675,7 @@ class TransactionBase(Owned): def_counter: ClassVar[count] = count() def_order: int defined: bool = False + name: str def __init__(self): self.method_uses: dict[Method, Tuple[ValueLike, ValueLike]] = dict() @@ -779,6 +798,13 @@ def peek(cls) -> Optional[Self]: raise RuntimeError(f"Current body not a {cls.__name__}") return TransactionBase.stack[-1] + @property + def owned_name(self): + if self.owner is not None and self.owner.__class__.__name__ != self.name: + return f"{self.owner.__class__.__name__}_{self.name}" + else: + return self.name + class Transaction(TransactionBase): """Transaction. @@ -835,8 +861,8 @@ def __init__(self, *, name: Optional[str] = None, manager: Optional[TransactionM if manager is None: manager = TransactionContext.get() manager.add_transaction(self) - self.request = Signal(name=self.name + "_request") - self.grant = Signal(name=self.name + "_grant") + self.request = Signal(name=self.owned_name + "_request") + self.grant = Signal(name=self.owned_name + "_grant") @contextmanager def body(self, m: TModule, *, request: ValueLike = C(1)) -> Iterator["Transaction"]: @@ -947,8 +973,8 @@ def __init__( super().__init__() self.owner, owner_name = get_caller_class_name(default="$method") self.name = name or tracer.get_var_name(depth=2, default=owner_name) - self.ready = Signal(name=self.name + "_ready") - self.run = Signal(name=self.name + "_run") + self.ready = Signal(name=self.owned_name + "_ready") + self.run = Signal(name=self.owned_name + "_run") self.data_in = Record(i) self.data_out = Record(o) self.nonexclusive = nonexclusive @@ -1107,7 +1133,7 @@ def __call__( if arg is None: arg = kwargs - enable_sig = Signal(name=self.name + "_enable") + enable_sig = Signal(name=self.owned_name + "_enable") m.d.av_comb += enable_sig.eq(enable) m.d.top_comb += assign(arg_rec, arg, fields=AssignType.ALL) TransactionBase.get().use_method(self, arg_rec, enable_sig) diff --git a/test/common.py b/test/common.py index 95f4b3c61..4cbd1c2be 100644 --- a/test/common.py +++ b/test/common.py @@ -188,15 +188,17 @@ def elaborate(self, platform) -> HasElaborate: class PysimSimulator(Simulator): def __init__(self, module: HasElaborate, max_cycles: float = 10e4, add_transaction_module=True, traces_file=None): - super().__init__(TestModule(module, add_transaction_module)) + test_module = TestModule(module, add_transaction_module) + tested_module = test_module.tested_module + super().__init__(test_module) clk_period = 1e-6 self.add_clock(clk_period) - if isinstance(module, HasDebugSignals): - extra_signals = module.debug_signals + if isinstance(tested_module, HasDebugSignals): + extra_signals = tested_module.debug_signals else: - extra_signals = functools.partial(auto_debug_signals, module) + extra_signals = functools.partial(auto_debug_signals, tested_module) if traces_file: traces_dir = "test/__traces__"