| import unittest |
|
|
| import numpy as np |
|
|
| from quread.def_translator import DEFGridConfig, build_def_blockages_from_severity_rows, to_def_blockages_fragment |
| from quread.eda_translator import build_eda_mapping_from_severity_rows, to_cadence_skill_reliability, to_synopsys_tcl |
| from quread.package_exporter import build_companion_lef, build_companion_lib |
| from quread.severity_mapper import SeverityConfig, SeverityThresholds, compute_severity_rows, severity_rows_to_csv |
| from quread.metrics import to_metrics_csv |
| from quread.validation_workbench import ( |
| build_validation_report_html, |
| validate_design_exports, |
| validation_artifact_summary_rows, |
| validation_focus_rows, |
| ) |
|
|
|
|
| def _sample_metrics(): |
| return { |
| "activity_count": np.array([10.0, 2.0], dtype=float), |
| "activity_norm": np.array([1.0, 0.2], dtype=float), |
| "gate_error": np.array([0.12, 0.01], dtype=float), |
| "readout_error": np.array([0.08, 0.02], dtype=float), |
| "fidelity": np.array([0.82, 0.99], dtype=float), |
| "state_fidelity": np.array([0.80, 0.99], dtype=float), |
| "process_fidelity": np.array([0.78, 0.98], dtype=float), |
| "coherence_health": np.array([0.30, 0.90], dtype=float), |
| "decoherence_risk": np.array([0.70, 0.10], dtype=float), |
| "composite_risk": np.array([0.82, 0.22], dtype=float), |
| "hotspot_level": np.array([2.0, 0.0], dtype=float), |
| } |
|
|
|
|
| class ValidationWorkbenchTest(unittest.TestCase): |
| def _build_case(self): |
| metrics = _sample_metrics() |
| severity_cfg = SeverityConfig( |
| mode="linear", |
| source_metric="composite_risk", |
| thresholds=SeverityThresholds(warning=0.45, critical=0.70), |
| ) |
| severity_rows = compute_severity_rows(metrics, cfg=severity_cfg, qubit_coords={0: (0, 0), 1: (0, 1)}) |
| mapping_rows = build_eda_mapping_from_severity_rows(metrics, severity_rows) |
| grid_cfg = DEFGridConfig( |
| origin_x_dbu=0, |
| origin_y_dbu=0, |
| site_width_dbu=100, |
| row_height_dbu=100, |
| sites_per_cell_x=10, |
| rows_per_cell_y=10, |
| ) |
| blockage_rows = build_def_blockages_from_severity_rows(severity_rows, grid_cfg=grid_cfg, partial_density=70.0) |
| return { |
| "metrics": metrics, |
| "severity_cfg": severity_cfg, |
| "severity_rows": severity_rows, |
| "mapping_rows": mapping_rows, |
| "grid_cfg": grid_cfg, |
| "blockage_rows": blockage_rows, |
| "metrics_csv_text": to_metrics_csv(metrics), |
| "severity_csv_text": severity_rows_to_csv(severity_rows), |
| "synopsys_tcl_text": to_synopsys_tcl(mapping_rows), |
| "cadence_skill_text": to_cadence_skill_reliability(mapping_rows), |
| "def_fragment_text": to_def_blockages_fragment(blockage_rows), |
| "companion_lef_text": build_companion_lef( |
| severity_rows, |
| dbu_per_micron=1000, |
| site_name="QUREAD_SITE", |
| site_width_dbu=100, |
| row_height_dbu=100, |
| sites_per_cell_x=10, |
| rows_per_cell_y=10, |
| ), |
| "companion_lib_text": build_companion_lib( |
| severity_rows, |
| dbu_per_micron=1000, |
| site_width_dbu=100, |
| row_height_dbu=100, |
| sites_per_cell_x=10, |
| rows_per_cell_y=10, |
| ), |
| "design_def_text": "UNITS DISTANCE MICRONS 1000 ;\nDIEAREA ( 0 0 ) ( 2000 2000 ) ;\n", |
| } |
|
|
| def test_validate_design_exports_passes_for_consistent_artifacts(self): |
| case = self._build_case() |
| report = validate_design_exports( |
| metrics_csv_text=case["metrics_csv_text"], |
| severity_csv_text=case["severity_csv_text"], |
| synopsys_tcl_text=case["synopsys_tcl_text"], |
| cadence_skill_text=case["cadence_skill_text"], |
| def_fragment_text=case["def_fragment_text"], |
| companion_lef_text=case["companion_lef_text"], |
| companion_lib_text=case["companion_lib_text"], |
| expected_metrics=case["metrics"], |
| expected_severity_rows=case["severity_rows"], |
| expected_mapping_rows=case["mapping_rows"], |
| expected_blockage_rows=case["blockage_rows"], |
| severity_cfg=case["severity_cfg"], |
| grid_cfg=case["grid_cfg"], |
| chip_rows=2, |
| chip_cols=2, |
| dbu_per_micron=1000, |
| site_name="QUREAD_SITE", |
| imported_design_def_text=case["design_def_text"], |
| ) |
| self.assertEqual(report["summary"]["overall_status"], "PASS") |
| self.assertGreater(report["summary"]["pass_count"], 0) |
|
|
| def test_validate_design_exports_fails_for_misaligned_def(self): |
| case = self._build_case() |
| broken_def = case["def_fragment_text"].replace("RECT ( 0 0 ) ( 1000 1000 ) ;", "RECT ( 5 0 ) ( 1000 1000 ) ;") |
| report = validate_design_exports( |
| metrics_csv_text=case["metrics_csv_text"], |
| severity_csv_text=case["severity_csv_text"], |
| synopsys_tcl_text=case["synopsys_tcl_text"], |
| cadence_skill_text=case["cadence_skill_text"], |
| def_fragment_text=broken_def, |
| companion_lef_text=case["companion_lef_text"], |
| companion_lib_text=case["companion_lib_text"], |
| expected_metrics=case["metrics"], |
| expected_severity_rows=case["severity_rows"], |
| expected_mapping_rows=case["mapping_rows"], |
| expected_blockage_rows=case["blockage_rows"], |
| severity_cfg=case["severity_cfg"], |
| grid_cfg=case["grid_cfg"], |
| chip_rows=2, |
| chip_cols=2, |
| dbu_per_micron=1000, |
| site_name="QUREAD_SITE", |
| imported_design_def_text=case["design_def_text"], |
| ) |
| self.assertEqual(report["summary"]["overall_status"], "FAIL") |
| self.assertTrue(any(check["code"] == "def_alignment" and check["status"] == "FAIL" for check in report["checks"])) |
| focus_rows = validation_focus_rows(report) |
| self.assertGreaterEqual(len(focus_rows), 1) |
| self.assertIn("q0", focus_rows[0][3]) |
| artifact_rows = validation_artifact_summary_rows(report) |
| self.assertTrue(any(row[0] == "def" and row[4] == "FAIL" for row in artifact_rows)) |
| html = build_validation_report_html(report) |
| self.assertIn("Artifact Summary", html) |
| self.assertIn("Mismatch Focus", html) |
|
|