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