carm-roofline 1.0.2.dev2__tar.gz → 1.0.3.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. {carm_roofline-1.0.2.dev2/carm_roofline.egg-info → carm_roofline-1.0.3.dev1}/PKG-INFO +1 -1
  2. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/architecture.py +6 -9
  3. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/arm.py +1 -1
  4. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/config.py +1 -2
  5. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/detect.py +2 -3
  6. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/memory.py +1 -2
  7. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/riscv.py +4 -4
  8. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/x86.py +1 -1
  9. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/__init__.py +0 -3
  10. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/benchmark.py +1 -1
  11. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/benchmarking.py +1 -4
  12. carm_roofline-1.0.3.dev1/benchmark/generation/__init__.py +10 -0
  13. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/generation/code_gen/__init__.py +0 -4
  14. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/generation/code_gen/instruction.py +2 -2
  15. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/generation/code_gen/register.py +1 -1
  16. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/generation/parameters.py +4 -6
  17. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/arithmetic.py +2 -2
  18. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/common.py +1 -1
  19. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/jsonl.py +3 -3
  20. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/memory.py +2 -2
  21. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/memory_sweep.py +2 -2
  22. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/roofline.py +176 -55
  23. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/result.py +1 -1
  24. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/arithmetic.py +1 -1
  25. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/base.py +1 -1
  26. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/memory.py +2 -2
  27. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/memory_sweep.py +2 -2
  28. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/roofline.py +1 -1
  29. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm.py +1 -1
  30. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1/carm_roofline.egg-info}/PKG-INFO +1 -1
  31. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm_roofline.egg-info/SOURCES.txt +10 -9
  32. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm_roofline.egg-info/top_level.txt +2 -3
  33. carm_roofline-1.0.3.dev1/core/__init__.py +33 -0
  34. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/assets/style.css +7 -0
  35. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/components.py +20 -11
  36. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/data.py +157 -40
  37. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/factory.py +196 -83
  38. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/ids.py +1 -0
  39. carm_roofline-1.0.3.dev1/isa/__init__.py +44 -0
  40. {carm_roofline-1.0.2.dev2/benchmark/generation → carm_roofline-1.0.3.dev1/isa}/arm.py +5 -5
  41. carm_roofline-1.0.2.dev2/benchmark/generation/isa.py → carm_roofline-1.0.3.dev1/isa/base.py +9 -6
  42. {carm_roofline-1.0.2.dev2/benchmark/generation → carm_roofline-1.0.3.dev1/isa}/riscv.py +5 -5
  43. {carm_roofline-1.0.2.dev2/benchmark/generation → carm_roofline-1.0.3.dev1/isa}/x86.py +4 -4
  44. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/output_utils.py +7 -6
  45. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/__init__.py +3 -3
  46. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/backends.py +1 -1
  47. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/config.py +14 -5
  48. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/papi_backend.py +50 -4
  49. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/papi_metrics.py +239 -6
  50. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/perf_backend.py +1 -1
  51. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/perf_metrics.py +1 -1
  52. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/shared.py +14 -13
  53. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/pyproject.toml +5 -27
  54. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/roofline_assembly.py +73 -82
  55. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_gui_data.py +25 -8
  56. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_isa_codegen_integration.py +6 -6
  57. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_memory_suite_generation.py +2 -2
  58. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_output_module.py +147 -34
  59. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_roofline_assembly.py +267 -15
  60. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test/test_typed_benchmarks.py +3 -3
  61. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test_bench/builder.py +1 -1
  62. carm_roofline-1.0.2.dev2/benchmark/generation/__init__.py +0 -53
  63. carm_roofline-1.0.2.dev2/utils.py +0 -177
  64. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/LICENSE +0 -0
  65. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/README.md +0 -0
  66. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/__init__.py +0 -0
  67. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/frequency.py +0 -0
  68. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/identity.py +0 -0
  69. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/arm/features.c +0 -0
  70. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/arm/frequency.h +0 -0
  71. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/arm/vlen.c +0 -0
  72. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/frequency.c +0 -0
  73. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/riscv/frequency.h +0 -0
  74. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/riscv/rvv_version.c +0 -0
  75. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/riscv/vlen.c +0 -0
  76. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/x86/cache.c +0 -0
  77. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/x86/features.c +0 -0
  78. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/x86/frequency.h +0 -0
  79. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/architecture/tests/x86/x86_avx512/frequency.h +0 -0
  80. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/arguments.py +0 -0
  81. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/interface.py +0 -0
  82. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/__init__.py +0 -0
  83. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/base.py +0 -0
  84. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/output/mixed.py +0 -0
  85. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/__init__.py +0 -0
  86. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/benchmark/suites/mixed.py +0 -0
  87. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm_roofline.egg-info/dependency_links.txt +0 -0
  88. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm_roofline.egg-info/entry_points.txt +0 -0
  89. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/carm_roofline.egg-info/requires.txt +0 -0
  90. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/context.py +0 -0
  91. {carm_roofline-1.0.2.dev2/benchmark/generation/code_gen → carm_roofline-1.0.3.dev1/core}/data_type.py +0 -0
  92. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1/core}/error.py +0 -0
  93. {carm_roofline-1.0.2.dev2/benchmark/generation/code_gen → carm_roofline-1.0.3.dev1/core}/operation.py +0 -0
  94. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1/core}/units.py +0 -0
  95. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/exec_interface.py +0 -0
  96. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/__init__.py +0 -0
  97. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/assets/CARM_icon.svg +0 -0
  98. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/assets/CHAMP_logo.svg +0 -0
  99. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/assets/menu_icon.png +0 -0
  100. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/gui/config.py +0 -0
  101. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/aggregation.py +0 -0
  102. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/model.py +0 -0
  103. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/output.py +0 -0
  104. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/papi_loader.py +0 -0
  105. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/profiling/perf_loader.py +0 -0
  106. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/results_paths.py +0 -0
  107. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/run_config.py +0 -0
  108. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/setup.cfg +0 -0
  109. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test_bench/__init__.py +0 -0
  110. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test_bench/test_bench.c +0 -0
  111. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test_bench/test_bench.h +0 -0
  112. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/test_bench/wrapper.inl +0 -0
  113. {carm_roofline-1.0.2.dev2 → carm_roofline-1.0.3.dev1}/workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: carm-roofline
3
- Version: 1.0.2.dev2
3
+ Version: 1.0.3.dev1
4
4
  Summary: CARM: Cache-Aware Roofline Model benchmarking and visualization toolkit
5
5
  Author: CHaMP Team
6
6
  License: Apache License
@@ -5,13 +5,12 @@ from pathlib import Path
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
7
  from arguments import InsertsArguments, positive_int
8
- from benchmark import generation as bench_gen
9
- from error import UserError
8
+ from core import Frequency, UserError
9
+ from isa import INCOMPATIBLE_ISAS, ISA_NAME_TO_CLASS
10
10
  from output_utils import configure_verbosity, debug, detail, format_if_container, warn
11
- from units import Frequency
12
11
 
13
12
  if TYPE_CHECKING:
14
- from benchmark.generation import BaseISA
13
+ from isa import BaseISA
15
14
 
16
15
  from .config import load_memory_topology_from_toml
17
16
  from .detect import DetectedArchitecture, detect_for_isa, native_detect
@@ -32,7 +31,7 @@ def check_isa_compatibility(selected_isas: list[type[BaseISA]]) -> None:
32
31
 
33
32
  # Check for special incompatibilities within the same family
34
33
  isa_set = set(selected_isas)
35
- for incompatible_pair in bench_gen.INCOMPATIBLE_ISAS:
34
+ for incompatible_pair in INCOMPATIBLE_ISAS:
36
35
  if incompatible_pair.issubset(isa_set):
37
36
  pair_names = ", ".join(isa.name for isa in incompatible_pair)
38
37
  raise UserError(f"Incompatible ISAs selected: {pair_names}")
@@ -245,10 +244,8 @@ class Architecture(InsertsArguments):
245
244
  detected = native_detect(threads=num_threads)
246
245
  isa_strs = detected.isa or []
247
246
 
248
- self.isa: list[type[BaseISA]] = [bench_gen.ISA_NAME_TO_CLASS[isa_str] for isa_str in isa_strs]
247
+ self.isa: list[type[BaseISA]] = [ISA_NAME_TO_CLASS[isa_str] for isa_str in isa_strs]
249
248
  else:
250
- from benchmark.generation import ISA_NAME_TO_CLASS
251
-
252
249
  self.isa = [ISA_NAME_TO_CLASS[isa_name] for isa_name in args.isa]
253
250
  # Verify that the selected ISAs are compatible
254
251
  check_isa_compatibility(self.isa)
@@ -279,7 +276,7 @@ class Architecture(InsertsArguments):
279
276
 
280
277
  @staticmethod
281
278
  def insert_arguments(parser: argparse.ArgumentParser) -> None:
282
- from benchmark.generation import ISA_NAME_TO_CLASS
279
+ from isa import ISA_NAME_TO_CLASS
283
280
 
284
281
  parser.add_argument(
285
282
  "-i",
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from architecture.detect import DetectedArchitecture, TestContext, run_generic_tests
4
- from benchmark.generation import ArmNeon, ArmScalar, ArmSVE
4
+ from isa import ArmNeon, ArmScalar, ArmSVE
5
5
 
6
6
 
7
7
  def detect(threads: int = 1) -> DetectedArchitecture:
@@ -18,8 +18,7 @@ from __future__ import annotations
18
18
  from pathlib import Path
19
19
  from typing import cast
20
20
 
21
- from error import UserError
22
- from units import Bytes
21
+ from core import Bytes, UserError
23
22
 
24
23
  from .memory import SimpleMemoryTopology
25
24
 
@@ -15,12 +15,11 @@ from dataclasses import dataclass
15
15
  from pathlib import Path
16
16
  from typing import TYPE_CHECKING, Any
17
17
 
18
- from error import UserError
18
+ from core import Frequency, UserError
19
19
  from output_utils import debug, detail, warn
20
- from units import Frequency
21
20
 
22
21
  if TYPE_CHECKING:
23
- from benchmark.generation import BaseISA
22
+ from isa import BaseISA
24
23
 
25
24
  from .memory import MemoryTopology
26
25
 
@@ -9,9 +9,8 @@ from enum import Enum
9
9
  from pathlib import Path
10
10
  from typing import Protocol, runtime_checkable
11
11
 
12
- from error import UserError
12
+ from core import Bytes, UserError
13
13
  from output_utils import debug, format_if_container
14
- from units import Bytes
15
14
 
16
15
  _CPU_ROOT = Path("/sys/devices/system/cpu")
17
16
 
@@ -3,8 +3,8 @@ from __future__ import annotations
3
3
  import tempfile
4
4
  from pathlib import Path
5
5
 
6
- from benchmark import generation as bench_gen
7
6
  from exec_interface import ExecutionInterface
7
+ from isa import RISCV_RVV, RISCV_RVV_071, RISCVScalar
8
8
 
9
9
  from .detect import ROOT, DetectedArchitecture, TestContext, run_generic_tests
10
10
 
@@ -24,7 +24,7 @@ def detect(threads: int = 1) -> DetectedArchitecture:
24
24
  detected = run_generic_tests(ctx, threads=threads)
25
25
 
26
26
  # Build ISA list with scalar as base
27
- isa_list = [bench_gen.RISCVScalar.name]
27
+ isa_list = [RISCVScalar.name]
28
28
 
29
29
  # Detect RVV version using RISC-V specific test
30
30
  exec_iface = _get_execution_interface()
@@ -33,9 +33,9 @@ def detect(threads: int = 1) -> DetectedArchitecture:
33
33
  if rvv_version_probe_path.exists():
34
34
  # Try compiling with RVV 1.0 flag first (most common)
35
35
  if _can_compile_rvv(exec_iface, rvv_version_probe_path, "RISCV_RVV"):
36
- isa_list.append(bench_gen.RISCV_RVV.name)
36
+ isa_list.append(RISCV_RVV.name)
37
37
  elif _can_compile_rvv(exec_iface, rvv_version_probe_path, "RISCV_RVV_0_7_1"):
38
- isa_list.append(bench_gen.RISCV_RVV_071.name)
38
+ isa_list.append(RISCV_RVV_071.name)
39
39
 
40
40
  detected.isa = isa_list
41
41
 
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from architecture.detect import ROOT, DetectedArchitecture, TestContext, run_generic_tests, run_test
4
- from units import Frequency
4
+ from core import Frequency
5
5
 
6
6
 
7
7
  def detect(threads: int = 1) -> DetectedArchitecture:
@@ -11,7 +11,6 @@ from .benchmark import (
11
11
  MixedBenchmarkResult,
12
12
  )
13
13
  from .benchmarking import Benchmarking, TestType
14
- from .generation import ALL_ISAS, BaseISA
15
14
  from .interface import generate_microbenchmarks, run_full_benchmark
16
15
  from .result import OutputFormat
17
16
  from .suites import (
@@ -23,13 +22,11 @@ from .suites import (
23
22
  )
24
23
 
25
24
  __all__ = [
26
- "ALL_ISAS",
27
25
  "ArithmeticBenchmark",
28
26
  "ArithmeticBenchmarkResult",
29
27
  "ArithmeticBenchmarkSuite",
30
28
  "BaseBenchmark",
31
29
  "BaseBenchmarkResult",
32
- "BaseISA",
33
30
  "Benchmarking",
34
31
  "ISABenchmarkSuite",
35
32
  "MemoryBenchmark",
@@ -8,9 +8,9 @@ from __future__ import annotations
8
8
  from abc import ABC, abstractmethod
9
9
  from dataclasses import dataclass, field
10
10
 
11
+ from core import ArithmeticIntensity, Bandwidth, Bytes, Performance, Seconds
11
12
  from output_utils import debug
12
13
  from test_bench.builder import MicrobenchmarkFunctionSpec
13
- from units import ArithmeticIntensity, Bandwidth, Bytes, Performance, Seconds
14
14
 
15
15
  from .generation import ArithmeticBenchmarkParams, BenchmarkParams, MemoryBenchmarkParams
16
16
 
@@ -10,11 +10,8 @@ from enum import Enum
10
10
  from typing import TypeVar
11
11
 
12
12
  from arguments import InsertsArguments, enum_action, positive_float, positive_int
13
- from benchmark.generation.code_gen.operation import ArithmeticOperation
13
+ from core import ArithmeticOperation, Bytes, DataType, Operations
14
14
  from output_utils import warn
15
- from units import Bytes, Operations
16
-
17
- from .generation import DataType
18
15
 
19
16
 
20
17
  class TestType(Enum):
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ from .parameters import ArithmeticBenchmarkParams, BenchmarkParams, MemoryBenchmarkParams, MemoryLayoutMode
4
+
5
+ __all__ = [
6
+ "ArithmeticBenchmarkParams",
7
+ "BenchmarkParams",
8
+ "MemoryBenchmarkParams",
9
+ "MemoryLayoutMode",
10
+ ]
@@ -1,17 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from . import instruction
4
- from .data_type import DataType
5
4
  from .instruction import ControlInstructions, TypedInstructions, escape_for_inline_asm
6
- from .operation import Operation
7
5
  from .register import CyclicRegisterSet, HelperRegisterSet, TypedRegisterSets
8
6
 
9
7
  __all__ = [
10
8
  "ControlInstructions",
11
9
  "CyclicRegisterSet",
12
- "DataType",
13
10
  "HelperRegisterSet",
14
- "Operation",
15
11
  "TypedInstructions",
16
12
  "TypedRegisterSets",
17
13
  "escape_for_inline_asm",
@@ -3,8 +3,8 @@ from __future__ import annotations
3
3
  from enum import Enum, auto
4
4
  from typing import Union, overload
5
5
 
6
- from .data_type import DataType
7
- from .operation import ArithmeticOperation, MemoryOperation, Operation
6
+ from core import ArithmeticOperation, DataType, MemoryOperation, Operation
7
+
8
8
  from .register import CyclicRegisterSet
9
9
 
10
10
  # Type alias for objects that can be converted to string
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from collections.abc import Iterable, Iterator
4
4
  from typing import Union
5
5
 
6
- from .data_type import DataType
6
+ from core import DataType
7
7
 
8
8
  __all__ = [
9
9
  "CyclicRegisterSet",
@@ -4,14 +4,12 @@ from dataclasses import dataclass
4
4
  from enum import Enum
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- import units
8
- from benchmark.generation.code_gen.operation import ArithmeticOperation
9
- from units import Bytes, Operations
7
+ from core import ArithmeticOperation, Bytes, Operations
10
8
 
11
9
  if TYPE_CHECKING:
12
10
  from benchmark.benchmarking import LoadStoreRatio
13
11
 
14
- from .code_gen import DataType
12
+ from core import DataType
15
13
 
16
14
 
17
15
  class BenchParamError(Exception):
@@ -52,14 +50,14 @@ class ArithmeticBenchmarkParams(BenchmarkParams):
52
50
  params = ArithmeticBenchmarkParams(
53
51
  data_type=DataType.f32,
54
52
  operation=ArithmeticOperation.fma,
55
- num_ops=units.Operations(1000),
53
+ num_ops=Operations(1000),
56
54
  thread_affinity=[0, 1, 2, 3],
57
55
  )
58
56
  spec = isa.generate_arithmetic(params)
59
57
  """
60
58
 
61
59
  operation: ArithmeticOperation
62
- num_ops: units.Operations
60
+ num_ops: Operations
63
61
 
64
62
  def __post_init__(self) -> None:
65
63
  super().__post_init__()
@@ -8,8 +8,8 @@ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from rich.table import Table
10
10
 
11
+ from core import Cycles
11
12
  from output_utils import error, get_console, warn
12
- from units import Cycles
13
13
 
14
14
  from .base import NON_ROOFLINE_CSV_ERROR_MSG, OutputHandler
15
15
  from .common import (
@@ -47,7 +47,7 @@ def _collect_gops_by_isa(isa_suites: dict[str, ISABenchmarkSuite]) -> dict[str,
47
47
 
48
48
  def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite]) -> None:
49
49
  from benchmark.benchmark import ArithmeticBenchmarkResult
50
- from benchmark.generation.isa import BaseISA
50
+ from isa import BaseISA
51
51
 
52
52
  print_extra = context.run_config.verbose >= 3
53
53
 
@@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, Any
11
11
  from output_utils import error, info, warn
12
12
 
13
13
  if TYPE_CHECKING:
14
- from benchmark.generation.code_gen import DataType
14
+ from core import DataType
15
15
 
16
16
 
17
17
  def format_precision_label(data_type: DataType) -> str:
@@ -13,16 +13,16 @@ from datetime import datetime
13
13
  from pathlib import Path
14
14
  from typing import TYPE_CHECKING
15
15
 
16
+ from core import Cycles
16
17
  from output_utils import info, warn
17
18
  from roofline_assembly import RecordType
18
- from units import Cycles
19
19
 
20
20
  if TYPE_CHECKING:
21
21
  from benchmark.benchmark import ArithmeticBenchmark, MemoryBenchmark
22
- from benchmark.generation.isa import BaseISA
23
22
  from benchmark.suites.base import ISABenchmarkSuite
24
23
  from context import CARMContext
25
- from units import Frequency
24
+ from core import Frequency
25
+ from isa import BaseISA
26
26
 
27
27
 
28
28
  def _serialize_arithmetic(
@@ -9,9 +9,9 @@ from typing import TYPE_CHECKING, Any
9
9
  from rich.table import Table
10
10
 
11
11
  from benchmark.benchmark import MemoryBenchmarkResult
12
- from benchmark.generation.isa import BaseISA
12
+ from core import Cycles
13
+ from isa import BaseISA
13
14
  from output_utils import error, warn
14
- from units import Cycles
15
15
 
16
16
  from .base import NON_ROOFLINE_CSV_ERROR_MSG, OutputHandler
17
17
  from .common import (
@@ -9,10 +9,10 @@ from typing import TYPE_CHECKING, Any
9
9
  from rich.table import Table
10
10
 
11
11
  from benchmark.benchmark import MemoryBenchmarkResult
12
- from benchmark.generation.isa import BaseISA
13
12
  from benchmark.suites import MemorySweepBenchmarkSuite
13
+ from core import Cycles
14
+ from isa import BaseISA
14
15
  from output_utils import error, warn
15
- from units import Cycles
16
16
 
17
17
  from .base import NON_ROOFLINE_CSV_ERROR_MSG, OutputHandler
18
18
  from .common import safe_matplotlib_import, save_or_show_plot
@@ -8,83 +8,204 @@ from datetime import datetime
8
8
  from pathlib import Path
9
9
  from typing import TYPE_CHECKING, Any
10
10
 
11
- from benchmark.generation.code_gen.operation import ArithmeticOperation
12
- from output_utils import info, warn
13
- from units import Cycles
11
+ from rich.table import Table
12
+
13
+ from core import ArithmeticIntensity, ArithmeticOperation, Bandwidth, Cycles, Performance
14
+ from output_utils import error, get_console, info, warn
14
15
 
15
16
  from .base import OutputHandler
16
- from .common import format_precision_label
17
+ from .common import format_precision_label, safe_matplotlib_import, save_or_show_plot
17
18
 
18
19
  if TYPE_CHECKING:
19
20
  from benchmark.benchmark import ISABenchmarkSuite
20
- from benchmark.generation.isa import BaseISA
21
21
  from context import CARMContext
22
+ from isa import BaseISA
22
23
 
23
24
 
24
- def _gather_roofline_points(suite: ISABenchmarkSuite) -> dict[str, tuple[float, float]]:
25
- """Gather roofline points (intensity, performance) from a benchmark suite.
26
-
27
- Roofline analysis requires both arithmetic intensity and GOPS,
28
- which are only available from MixedBenchmarkResult.
25
+ def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite]) -> None:
26
+ """Print a merged roofline summary table.
29
27
 
30
- Note:
31
- Skips invalid values (NaN, inf, or non-positive) with warning.
28
+ One row per ISA x (data_type, threads, loads, stores) combo, showing peak
29
+ intensity. Values are displayed via their unit class __str__ methods
30
+ (e.g., "8.95 GOPS/s", "380.00 GB/s", "0.02 FLOP/B").
31
+ At verbose >= 3, also prints the arithmetic and memory detail tables.
32
32
  """
33
- # Basic implementation used by tests and future consumers.
34
- # Collect intensity/performance pairs from MixedBenchmarkResult-like objects.
35
- points: dict[str, tuple[float, float]] = {}
36
-
37
- for name, bench in suite.benchmarks.items():
38
- res = getattr(bench, "results", None)
39
- if res is None:
40
- continue
41
- # we expect attributes 'arithmetic_intensity' and 'performance'
42
- ai = getattr(res, "arithmetic_intensity", None)
43
- perf = getattr(res, "performance", None)
44
- if ai is None or perf is None:
45
- # nothing to record for this benchmark
46
- continue
47
- try:
48
- ai_val = float(ai)
49
- perf_val = float(perf)
50
- except Exception:
51
- warn(f"Skipping invalid roofline point for {name} (non-numeric)")
52
- continue
33
+ table = Table(title="Roofline Summary")
34
+ table.add_column("ISA", style="cyan")
35
+ table.add_column("Prec.", justify="left")
36
+ table.add_column("Thr.", style="magenta", justify="right")
37
+ table.add_column("Peak", justify="right")
38
+ for level in _CACHE_LEVELS:
39
+ table.add_column(level, justify="right")
40
+ table.add_column(f"{level} AI", justify="right")
53
41
 
54
- if ai_val <= 0 or perf_val <= 0:
55
- warn(f"Skipping invalid roofline point for {name} (non-positive values)")
56
- continue
42
+ for isa, suite in sorted(isa_suites.items(), key=lambda kv: kv[0]):
43
+ mem_benches = suite.get_memory_benchmarks()
44
+ arith_benches = suite.get_arithmetic_benchmarks()
45
+
46
+ for (dt, nt, _ld, _st), group in sorted(_group_combos(mem_benches).items()):
47
+ # Collect Bandwidth per cache level from this combo's memory benchmarks
48
+ bw_by_level: dict[str, Bandwidth | None] = dict.fromkeys(_CACHE_LEVELS)
49
+ for bench in group:
50
+ if bench.results is not None and bench.cache_level in bw_by_level:
51
+ bw_by_level[bench.cache_level] = bench.results.bandwidth
52
+
53
+ # Find peak Performance from arithmetic benchmarks matching this combo
54
+ peak_perf: Performance | None = None
55
+ for bench in arith_benches.values():
56
+ if bench.results is None:
57
+ continue
58
+ if bench.params.data_type != dt or bench.params.num_threads != nt:
59
+ continue
60
+ if peak_perf is None or bench.results.performance > peak_perf:
61
+ peak_perf = bench.results.performance
62
+
63
+ row: list[str] = [isa, format_precision_label(dt), str(nt)]
64
+ if peak_perf is not None:
65
+ row.append(str(peak_perf))
66
+ else:
67
+ row.append("-")
68
+
69
+ for level in _CACHE_LEVELS:
70
+ bw = bw_by_level[level]
71
+ if bw is not None and bw.value > 0 and peak_perf is not None:
72
+ ridge = ArithmeticIntensity(peak_perf.value / bw.value)
73
+ row.append(str(bw))
74
+ row.append(str(ridge))
75
+ else:
76
+ row.append("-")
77
+ row.append("-")
78
+ table.add_row(*row)
79
+
80
+ get_console().print(table)
81
+
82
+ if context.run_config.verbose >= 3:
83
+ from . import arithmetic, memory
84
+
85
+ arithmetic._print_table(context, isa_suites)
86
+ memory._print_table(context, isa_suites)
87
+
88
+
89
+ _ROOFLINE_COLORS = [
90
+ "#1f77b4",
91
+ "#ff7f0e",
92
+ "#2ca02c",
93
+ "#d62728",
94
+ "#9467bd",
95
+ "#8c564b",
96
+ "#e377c2",
97
+ "#7f7f7f",
98
+ "#bcbd22",
99
+ "#17becf",
100
+ ]
101
+ _LINE_STYLES = {"L1": "-", "L2": "--", "L3": "-.", "DRAM": ":"}
102
+ _CACHE_LEVELS = ("L1", "L2", "L3", "DRAM")
103
+
104
+
105
+ def _plot_roofline_to_axis(
106
+ roofline_data: dict[str, tuple[float, dict[str, float]]],
107
+ ax: Any,
108
+ np: Any,
109
+ ) -> None:
110
+ """Draw roofline curves on a matplotlib log-log axis.
111
+
112
+ For each ISA: horizontal ceiling at peak Gflop/s, and one bandwidth slope
113
+ per cache level (y = bandwidth x AI, clipped at the ceiling).
114
+ """
115
+ all_ridges: list[float] = []
116
+ for peak_gflops, bw_gbps in roofline_data.values():
117
+ for bw in bw_gbps.values():
118
+ if bw > 0:
119
+ all_ridges.append(peak_gflops / bw)
120
+
121
+ if not all_ridges:
122
+ warn("No valid roofline ridge points to plot")
123
+ return
57
124
 
58
- points[name] = (ai_val, perf_val)
59
- return points
125
+ ai_min = min(all_ridges) / 10
126
+ ai_max = max(all_ridges) * 10
127
+ ai_values = np.logspace(np.log10(ai_min), np.log10(ai_max), 200)
128
+ if not isinstance(ai_values, list):
129
+ ai_values = list(ai_values)
60
130
 
131
+ for idx, (isa, (peak_gflops, bw_gbps)) in enumerate(sorted(roofline_data.items())):
132
+ color = _ROOFLINE_COLORS[idx % len(_ROOFLINE_COLORS)]
61
133
 
62
- def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite]) -> None:
63
- info("Roofline summary per ISA:")
134
+ # Compute ridge points for this ISA to clip the ceiling
135
+ isa_ridges = [peak_gflops / bw for level in _CACHE_LEVELS if (bw := bw_gbps.get(level, 0)) > 0]
136
+ if isa_ridges:
137
+ min_ridge = min(isa_ridges)
138
+ ceiling_ai = [ai for ai in ai_values if ai >= min_ridge]
139
+ else:
140
+ ceiling_ai = []
141
+ if ceiling_ai:
142
+ ax.plot(
143
+ ceiling_ai,
144
+ [peak_gflops] * len(ceiling_ai),
145
+ color=color,
146
+ linestyle="-",
147
+ linewidth=1.5,
148
+ label=f"{isa} ceiling",
149
+ )
150
+ for level in _CACHE_LEVELS:
151
+ bw = bw_gbps.get(level, 0)
152
+ if bw <= 0:
153
+ continue
154
+ perf = [min(bw * ai, peak_gflops) for ai in ai_values]
155
+ ax.plot(
156
+ ai_values,
157
+ perf,
158
+ color=color,
159
+ linestyle=_LINE_STYLES[level],
160
+ linewidth=1,
161
+ alpha=1,
162
+ )
163
+
164
+ ax.set_xscale("log")
165
+ ax.set_yscale("log")
166
+ ax.set_xlabel("Arithmetic Intensity (FLOP/byte)")
167
+ ax.set_ylabel("Performance (Gflop/s)")
168
+ ax.set_title("Roofline Model")
169
+ ax.legend(fontsize=8)
64
170
 
65
171
 
66
172
  def _write_plot(isa_suites: dict[str, ISABenchmarkSuite], output_path: Path | None = None) -> None:
67
- """Generate roofline plots or warn when no data.
173
+ """Generate and save roofline plot.
68
174
 
69
- This minimal implementation is sufficient for unit tests and avoids
70
- raising exceptions during missing-data scenarios. Full plotting logic
71
- may be added later.
175
+ Draws log-log roofline curves (bandwidth slopes + compute ceiling) per ISA.
176
+ Gracefully handles missing data, invalid values, and I/O errors.
72
177
  """
73
- # gather all points across ISAs; warn if none found
74
- any_points = False
75
- for _isa, suite in isa_suites.items():
76
- pts = _gather_roofline_points(suite)
77
- if pts:
78
- any_points = True
79
- break
80
-
81
- if not any_points:
178
+ roofline_data: dict[str, tuple[float, dict[str, float]]] = {}
179
+ for isa, suite in sorted(isa_suites.items(), key=lambda kv: kv[0]):
180
+ try:
181
+ peak = suite.get_peak_performance()
182
+ bw_by_level = suite.get_bandwidth_by_level()
183
+ except ValueError:
184
+ warn(f"Skipping {isa} in roofline plot: missing or incomplete benchmark results")
185
+ continue
186
+ peak_gflops = float(peak) / 1e9
187
+ bw_gbps = {level: float(bw) / 1e9 for level, bw in bw_by_level.items()}
188
+ roofline_data[isa] = (peak_gflops, bw_gbps)
189
+
190
+ if not roofline_data:
82
191
  warn("No roofline data found")
83
192
  return
84
193
 
85
- # Placeholder: in a complete implementation we would import matplotlib
86
- # and numpy and draw the curves. For now just silently succeed.
87
- return
194
+ plt, np = safe_matplotlib_import()
195
+ if plt is None:
196
+ return
197
+
198
+ fig = None
199
+ try:
200
+ fig, ax = plt.subplots(figsize=(10, 7))
201
+ _plot_roofline_to_axis(roofline_data, ax, np)
202
+ plt.tight_layout()
203
+ save_or_show_plot(output_path, "roofline.png", plt=plt)
204
+ except Exception as e:
205
+ error(f"Failed to generate roofline plot: {e}")
206
+ finally:
207
+ if fig is not None:
208
+ plt.close(fig)
88
209
 
89
210
 
90
211
  def _to_isa_label(isa_name: str, context: CARMContext) -> str:
@@ -11,7 +11,7 @@ from __future__ import annotations
11
11
  from enum import Enum
12
12
  from typing import TYPE_CHECKING
13
13
 
14
- from units import Seconds
14
+ from core import Seconds
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from .benchmark import BaseBenchmark
@@ -37,7 +37,7 @@ class ArithmeticBenchmarkSuite(ISABenchmarkSuite):
37
37
  Raises:
38
38
  ValueError: Unsupported precision or unknown ISA name.
39
39
  """
40
- from benchmark.generation.isa import BaseISA
40
+ from isa import BaseISA
41
41
 
42
42
  benchmark = context.benchmarking
43
43
  architecture = context.architecture
@@ -6,7 +6,7 @@ from abc import ABC, abstractmethod
6
6
  from dataclasses import dataclass, field
7
7
  from typing import TYPE_CHECKING
8
8
 
9
- from units import Bandwidth, Performance
9
+ from core import Bandwidth, Performance
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from context import CARMContext