/ coreblocks / func_blocks / instruction_metrics.py
instruction_metrics.py
 1  from collections import defaultdict
 2  from enum import Enum
 3  from amaranth import Elaboratable
 4  from transactron import Method, TModule
 5  from transactron.utils import DependencyContext
 6  from transactron.lib.metrics import TaggedCounter
 7  from coreblocks.interface.keys import InstructionTaggedCounterKey
 8  
 9  
10  __all__ = ["InstructionMetrics"]
11  
12  
13  class InstructionMetrics(Elaboratable):
14      def elaborate(self, platform):
15          m = TModule()
16  
17          dm = DependencyContext.get()
18          incr_methods = dm.get_dependency(InstructionTaggedCounterKey())
19  
20          incr_methods_by_tag_type: defaultdict[tuple[str, type[Enum]], list[Method]] = defaultdict(list)
21          for fu_name, method in incr_methods:
22              tag_type = method.layout_in.members["tag"]
23              assert isinstance(tag_type, type) and issubclass(tag_type, Enum)
24              incr_methods_by_tag_type[(fu_name, tag_type)].append(method)
25  
26          for (fu_name, tag_type), methods in incr_methods_by_tag_type.items():
27              m.submodules[f"counter_{fu_name}_{tag_type.__qualname__}"] = counter = TaggedCounter(
28                  f"backend.fu.{fu_name}.{tag_type.__qualname__}",
29                  f"Counts of instructions executed by {fu_name} for tag {tag_type.__qualname__}",
30                  tags=tag_type,
31                  ways=len(methods),
32              )
33  
34              for incr_method, method in zip(counter.incr, methods):
35                  method.provide(incr_method)
36  
37          return m