hchevva commited on
Commit
cc0edce
·
verified ·
1 Parent(s): e427457

Upload 2 files

Browse files
Files changed (2) hide show
  1. quread/eda_translator.py +26 -7
  2. quread/layout_mapper.py +102 -0
quread/eda_translator.py CHANGED
@@ -1,7 +1,7 @@
1
  from __future__ import annotations
2
 
3
  from dataclasses import dataclass
4
- from typing import Dict, List, Any
5
 
6
  import numpy as np
7
 
@@ -31,6 +31,7 @@ def build_eda_mapping(
31
  metrics: Dict[str, np.ndarray],
32
  *,
33
  cfg: EDATranslatorConfig | None = None,
 
34
  ) -> List[Dict[str, Any]]:
35
  cfg = cfg or EDATranslatorConfig()
36
  required = [
@@ -59,6 +60,12 @@ def build_eda_mapping(
59
  float(cfg.max_guardband_mv) - float(cfg.base_guardband_mv)
60
  )
61
  route_priority = "HIGH" if tier == "CRITICAL" else ("MEDIUM" if tier == "WARNING" else "LOW")
 
 
 
 
 
 
62
 
63
  rows.append(
64
  {
@@ -72,6 +79,8 @@ def build_eda_mapping(
72
  "timing_derate": float(timing_derate),
73
  "guardband_mv": float(guardband_mv),
74
  "route_priority": route_priority,
 
 
75
  }
76
  )
77
 
@@ -96,19 +105,25 @@ def to_synopsys_tcl(mapping_rows: List[Dict[str, Any]]) -> str:
96
  derate = float(row["timing_derate"])
97
  gb = float(row["guardband_mv"])
98
  route = row["route_priority"]
99
- out.append(f"# q{q}: tier={tier} risk={risk:.4f} route={route}")
 
 
 
 
100
  out.append(f"set quread_q{q}_risk {risk:.6f}")
101
  out.append(f"set quread_q{q}_tier {tier}")
102
  out.append(f"set quread_q{q}_timing_derate {derate:.6f}")
103
  out.append(f"set quread_q{q}_guardband_mv {gb:.3f}")
 
 
104
  out.append(
105
- f"lappend quread_risk_rows [list q{q} $quread_q{q}_risk $quread_q{q}_tier $quread_q{q}_timing_derate $quread_q{q}_guardband_mv {route}]"
106
  )
107
  out.append("")
108
 
109
  out.append("# Example integration hook:")
110
  out.append("# foreach row $quread_risk_rows {")
111
- out.append("# lassign $row q risk tier derate guardband route")
112
  out.append("# # apply derate/guardband to path groups or physical regions")
113
  out.append("# }")
114
  out.append("")
@@ -132,8 +147,12 @@ def to_cadence_skill_reliability(mapping_rows: List[Dict[str, Any]]) -> str:
132
  derate = float(row["timing_derate"])
133
  gb = float(row["guardband_mv"])
134
  route = row["route_priority"]
 
 
 
 
135
  out.append(
136
- f'qureadRiskRows = cons(list("q{q}" {risk:.6f} "{tier}" {derate:.6f} {gb:.3f} "{route}") qureadRiskRows)'
137
  )
138
 
139
  out.append("")
@@ -141,8 +160,8 @@ def to_cadence_skill_reliability(mapping_rows: List[Dict[str, Any]]) -> str:
141
  out.append("")
142
  out.append("; Example integration hook:")
143
  out.append("; foreach(row qureadRiskRows")
144
- out.append('; printf("Qubit=%s risk=%L tier=%s derate=%L guardband(mV)=%L route=%s\\n"')
145
- out.append("; car(row) cadr(row) caddr(row) cadddr(row) car(cddddr(row)) cadr(cddddr(row)))")
146
  out.append("; )")
147
  out.append("")
148
  return "\n".join(out) + "\n"
 
1
  from __future__ import annotations
2
 
3
  from dataclasses import dataclass
4
+ from typing import Dict, List, Any, Tuple
5
 
6
  import numpy as np
7
 
 
31
  metrics: Dict[str, np.ndarray],
32
  *,
33
  cfg: EDATranslatorConfig | None = None,
34
+ qubit_coords: Dict[int, Tuple[int, int]] | None = None,
35
  ) -> List[Dict[str, Any]]:
36
  cfg = cfg or EDATranslatorConfig()
37
  required = [
 
60
  float(cfg.max_guardband_mv) - float(cfg.base_guardband_mv)
61
  )
62
  route_priority = "HIGH" if tier == "CRITICAL" else ("MEDIUM" if tier == "WARNING" else "LOW")
63
+ layout_row = None
64
+ layout_col = None
65
+ if qubit_coords and q in qubit_coords:
66
+ rr, cc = qubit_coords[q]
67
+ layout_row = int(rr)
68
+ layout_col = int(cc)
69
 
70
  rows.append(
71
  {
 
79
  "timing_derate": float(timing_derate),
80
  "guardband_mv": float(guardband_mv),
81
  "route_priority": route_priority,
82
+ "layout_row": layout_row,
83
+ "layout_col": layout_col,
84
  }
85
  )
86
 
 
105
  derate = float(row["timing_derate"])
106
  gb = float(row["guardband_mv"])
107
  route = row["route_priority"]
108
+ layout_row = row.get("layout_row")
109
+ layout_col = row.get("layout_col")
110
+ rr = -1 if layout_row is None else int(layout_row)
111
+ cc = -1 if layout_col is None else int(layout_col)
112
+ out.append(f"# q{q}: tier={tier} risk={risk:.4f} route={route} row={rr} col={cc}")
113
  out.append(f"set quread_q{q}_risk {risk:.6f}")
114
  out.append(f"set quread_q{q}_tier {tier}")
115
  out.append(f"set quread_q{q}_timing_derate {derate:.6f}")
116
  out.append(f"set quread_q{q}_guardband_mv {gb:.3f}")
117
+ out.append(f"set quread_q{q}_row {rr}")
118
+ out.append(f"set quread_q{q}_col {cc}")
119
  out.append(
120
+ f"lappend quread_risk_rows [list q{q} $quread_q{q}_risk $quread_q{q}_tier $quread_q{q}_timing_derate $quread_q{q}_guardband_mv $quread_q{q}_row $quread_q{q}_col {route}]"
121
  )
122
  out.append("")
123
 
124
  out.append("# Example integration hook:")
125
  out.append("# foreach row $quread_risk_rows {")
126
+ out.append("# lassign $row q risk tier derate guardband row col route")
127
  out.append("# # apply derate/guardband to path groups or physical regions")
128
  out.append("# }")
129
  out.append("")
 
147
  derate = float(row["timing_derate"])
148
  gb = float(row["guardband_mv"])
149
  route = row["route_priority"]
150
+ layout_row = row.get("layout_row")
151
+ layout_col = row.get("layout_col")
152
+ rr = -1 if layout_row is None else int(layout_row)
153
+ cc = -1 if layout_col is None else int(layout_col)
154
  out.append(
155
+ f'qureadRiskRows = cons(list("q{q}" {risk:.6f} "{tier}" {derate:.6f} {gb:.3f} {rr} {cc} "{route}") qureadRiskRows)'
156
  )
157
 
158
  out.append("")
 
160
  out.append("")
161
  out.append("; Example integration hook:")
162
  out.append("; foreach(row qureadRiskRows")
163
+ out.append('; printf("Qubit=%s risk=%L tier=%s derate=%L guardband(mV)=%L row=%L col=%L route=%s\\n"')
164
+ out.append('; nth(0 row) nth(1 row) nth(2 row) nth(3 row) nth(4 row) nth(5 row) nth(6 row) nth(7 row))')
165
  out.append("; )")
166
  out.append("")
167
  return "\n".join(out) + "\n"
quread/layout_mapper.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import csv
4
+ import io
5
+ from typing import Any, Dict, Optional, Tuple
6
+
7
+
8
+ def default_qubit_coords(n_qubits: int, rows: int, cols: int) -> Dict[int, Tuple[int, int]]:
9
+ n = int(n_qubits)
10
+ rmax = int(rows)
11
+ cmax = int(cols)
12
+ m: Dict[int, Tuple[int, int]] = {}
13
+ for q in range(n):
14
+ rr = q // max(1, cmax)
15
+ cc = q % max(1, cmax)
16
+ if rr >= rmax:
17
+ break
18
+ m[q] = (rr, cc)
19
+ return m
20
+
21
+
22
+ def _to_int(v: Any) -> Optional[int]:
23
+ try:
24
+ s = str(v).strip()
25
+ if s == "":
26
+ return None
27
+ return int(s)
28
+ except Exception:
29
+ return None
30
+
31
+
32
+ def parse_layout_csv_text(
33
+ csv_text: str,
34
+ n_qubits: int,
35
+ *,
36
+ rows: int,
37
+ cols: int,
38
+ ) -> Tuple[Dict[int, Tuple[int, int]], Dict[str, Any]]:
39
+ """
40
+ Parse qubit-to-layout CSV.
41
+ Expected headers (case-insensitive):
42
+ qubit,row,col
43
+ Also accepts aliases:
44
+ qubit_id/q/id, r/y for row, c/x/column for col.
45
+ """
46
+ n = int(n_qubits)
47
+ rmax = int(rows)
48
+ cmax = int(cols)
49
+ fallback = default_qubit_coords(n, rmax, cmax)
50
+
51
+ text = (csv_text or "").strip()
52
+ if not text:
53
+ return fallback, {
54
+ "source": "default",
55
+ "parsed_rows": 0,
56
+ "mapped": len(fallback),
57
+ "fallback": len(fallback),
58
+ "skipped": 0,
59
+ "duplicates": 0,
60
+ }
61
+
62
+ reader = csv.DictReader(io.StringIO(text))
63
+ coords: Dict[int, Tuple[int, int]] = {}
64
+ skipped = 0
65
+ duplicates = 0
66
+ parsed_rows = 0
67
+
68
+ def _pick(row: Dict[str, Any], *keys: str) -> Any:
69
+ row_lc = {str(k).strip().lower(): v for k, v in row.items()}
70
+ for k in keys:
71
+ if k in row_lc:
72
+ return row_lc[k]
73
+ return None
74
+
75
+ for raw in reader:
76
+ parsed_rows += 1
77
+ q = _to_int(_pick(raw, "qubit", "qubit_id", "q", "id"))
78
+ rr = _to_int(_pick(raw, "row", "r", "y"))
79
+ cc = _to_int(_pick(raw, "col", "column", "c", "x"))
80
+ if q is None or rr is None or cc is None:
81
+ skipped += 1
82
+ continue
83
+ if not (0 <= q < n):
84
+ skipped += 1
85
+ continue
86
+ if not (0 <= rr < rmax and 0 <= cc < cmax):
87
+ skipped += 1
88
+ continue
89
+ if q in coords:
90
+ duplicates += 1
91
+ coords[q] = (rr, cc)
92
+
93
+ merged = dict(fallback)
94
+ merged.update(coords)
95
+ return merged, {
96
+ "source": "uploaded",
97
+ "parsed_rows": parsed_rows,
98
+ "mapped": len(coords),
99
+ "fallback": len(merged) - len(coords),
100
+ "skipped": skipped,
101
+ "duplicates": duplicates,
102
+ }