diff --git a/tools/hw-oracle/hw_oracle.py b/tools/hw-oracle/hw_oracle.py index 46b59c202..6573c9f54 100644 --- a/tools/hw-oracle/hw_oracle.py +++ b/tools/hw-oracle/hw_oracle.py @@ -63,8 +63,12 @@ def oracle(): @cache +def detected_target(binary): + return subprocess.run([binary, "--target"], capture_output=True, text=True, check=True).stdout.strip() + + def target(): - return os.environ.get("HW_ORACLE_TARGET") or subprocess.run([oracle(), "--target"], capture_output=True, text=True, check=True).stdout.strip() + return os.environ.get("HW_ORACLE_TARGET") or detected_target(oracle()) def assemble(body, work, wave64, *, ieee, denorm32, denorm16, dx10_clamp, round32, round16, fp16_overflow, lds=DEFAULT_LDS): diff --git a/tools/hw-oracle/test_hw_oracle.py b/tools/hw-oracle/test_hw_oracle.py index 7de671b40..26c05c624 100644 --- a/tools/hw-oracle/test_hw_oracle.py +++ b/tools/hw-oracle/test_hw_oracle.py @@ -127,6 +127,41 @@ class FloatModeTests(unittest.TestCase): self.assertEqual(assemble.call_args.kwargs, MODES | {"lds": 4096}) +class TargetOverrideTests(unittest.TestCase): + def setUp(self): + detector = getattr(hw_oracle, "detected_target", hw_oracle.target) + detector.cache_clear() + + def tearDown(self): + detector = getattr(hw_oracle, "detected_target", hw_oracle.target) + detector.cache_clear() + + def test_override_is_read_for_each_call_without_a_gpu_probe(self): + with patch.object(hw_oracle, "oracle", side_effect=AssertionError("GPU probe")): + with patch.dict(os.environ, {"HW_ORACLE_TARGET": "gfx1030"}): + self.assertEqual(hw_oracle.target(), "gfx1030") + with patch.dict(os.environ, {"HW_ORACLE_TARGET": "gfx1100"}): + self.assertEqual(hw_oracle.target(), "gfx1100") + + def test_removing_override_restores_cached_detection_for_that_binary(self): + reply = subprocess.CompletedProcess([], 0, "gfx1030\n", "") + with patch.object(hw_oracle, "oracle", return_value=Path("oracle-a")), \ + patch.object(hw_oracle.subprocess, "run", return_value=reply) as probe: + with patch.dict(os.environ, {"HW_ORACLE_TARGET": ""}): + self.assertEqual(hw_oracle.target(), "gfx1030") + self.assertEqual(hw_oracle.target(), "gfx1030") + with patch.dict(os.environ, {"HW_ORACLE_TARGET": "gfx1100"}): + self.assertEqual(hw_oracle.target(), "gfx1100") + with patch.dict(os.environ, {"HW_ORACLE_TARGET": ""}): + self.assertEqual(hw_oracle.target(), "gfx1030") + self.assertEqual(probe.call_count, 1) + with patch.object(hw_oracle, "oracle", return_value=Path("oracle-b")), \ + patch.dict(os.environ, {"HW_ORACLE_TARGET": ""}): + probe.return_value = subprocess.CompletedProcess([], 0, "gfx1200\n", "") + self.assertEqual(hw_oracle.target(), "gfx1200") + self.assertEqual(probe.call_count, 2) + + class OracleConfigurationTests(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "Linux compiler and shared-library fixture") def test_cache_and_compiler_command_with_host_toolchain(self):