chipfoundry-cli 2.7.0__py3-none-any.whl → 2.7.2__py3-none-any.whl
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.
- chipfoundry_cli/__init__.py +1 -1
- chipfoundry_cli/main.py +23 -5
- chipfoundry_cli/preview.py +47 -11
- {chipfoundry_cli-2.7.0.dist-info → chipfoundry_cli-2.7.2.dist-info}/METADATA +1 -1
- chipfoundry_cli-2.7.2.dist-info/RECORD +13 -0
- chipfoundry_cli-2.7.0.dist-info/RECORD +0 -13
- {chipfoundry_cli-2.7.0.dist-info → chipfoundry_cli-2.7.2.dist-info}/WHEEL +0 -0
- {chipfoundry_cli-2.7.0.dist-info → chipfoundry_cli-2.7.2.dist-info}/entry_points.txt +0 -0
- {chipfoundry_cli-2.7.0.dist-info → chipfoundry_cli-2.7.2.dist-info}/licenses/LICENSE +0 -0
chipfoundry_cli/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""ChipFoundry CLI package: Automate project submission to SFTP."""
|
|
2
|
-
__version__ = "2.7.
|
|
2
|
+
__version__ = "2.7.2"
|
chipfoundry_cli/main.py
CHANGED
|
@@ -3661,8 +3661,13 @@ def setup(project_root, repo_owner, repo_name, branch, pdk, caravel_lite,
|
|
|
3661
3661
|
)
|
|
3662
3662
|
# Install from GitHub source (workaround: PyPI package is under efabless, we use chipfoundry repo)
|
|
3663
3663
|
env = os.environ.copy()
|
|
3664
|
-
|
|
3665
|
-
|
|
3664
|
+
# cocotb 1.9.2 rewrites -bundle to -dynamiclib on the stdlib distutils
|
|
3665
|
+
# config, but an isolated pip build links with setuptools' vendored
|
|
3666
|
+
# distutils and never sees that change. Python 3.12+ has no stdlib
|
|
3667
|
+
# distutils, so this only applies to older interpreters. The venv is
|
|
3668
|
+
# created with sys.executable, so sys.version_info matches it.
|
|
3669
|
+
if sys.platform == 'darwin' and sys.version_info < (3, 12):
|
|
3670
|
+
env['SETUPTOOLS_USE_DISTUTILS'] = 'stdlib'
|
|
3666
3671
|
subprocess.run(
|
|
3667
3672
|
[
|
|
3668
3673
|
venv_python, '-m', 'pip', 'install', '--upgrade', '--no-cache-dir',
|
|
@@ -3710,9 +3715,22 @@ def setup(project_root, repo_owner, repo_name, branch, pdk, caravel_lite,
|
|
|
3710
3715
|
except subprocess.CalledProcessError as e:
|
|
3711
3716
|
maybe_abort_no_space(e, "Cocotb setup")
|
|
3712
3717
|
had_errors = True
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3718
|
+
cmd_parts = e.cmd if isinstance(e.cmd, (list, tuple)) else [str(e.cmd)]
|
|
3719
|
+
is_cocotb_install = any(
|
|
3720
|
+
"caravel-sim-infrastructure" in str(part) for part in cmd_parts
|
|
3721
|
+
)
|
|
3722
|
+
if is_cocotb_install:
|
|
3723
|
+
console.print("[red]✗[/red] Failed to set up Cocotb")
|
|
3724
|
+
stderr = e.stderr or b""
|
|
3725
|
+
if isinstance(stderr, bytes):
|
|
3726
|
+
stderr = stderr.decode(errors="replace")
|
|
3727
|
+
tail = "\n".join(stderr.splitlines()[-25:])
|
|
3728
|
+
if tail:
|
|
3729
|
+
console.print(f"[dim]{tail}[/dim]")
|
|
3730
|
+
else:
|
|
3731
|
+
console.print(f"[red]✗[/red] Failed to set up Cocotb: {e}")
|
|
3732
|
+
if e.stderr:
|
|
3733
|
+
console.print(f"[dim]{e.stderr}[/dim]")
|
|
3716
3734
|
except Exception as e:
|
|
3717
3735
|
maybe_abort_no_space(e, "Cocotb setup")
|
|
3718
3736
|
had_errors = True
|
chipfoundry_cli/preview.py
CHANGED
|
@@ -41,6 +41,9 @@ LINT_PASSED = "passed"
|
|
|
41
41
|
LINT_FAILED = "failed"
|
|
42
42
|
LINT_SKIPPED = "skipped"
|
|
43
43
|
|
|
44
|
+
AREA_SOURCE_DIE = "die_area"
|
|
45
|
+
AREA_SOURCE_SYNTHESIS = "synthesis"
|
|
46
|
+
|
|
44
47
|
_ELABORATE_ONLY_STRATEGIES = {
|
|
45
48
|
STRATEGY_HIER_MACRO_FIRST,
|
|
46
49
|
STRATEGY_HIER_MACRO_FIRST_LEGACY,
|
|
@@ -105,6 +108,30 @@ def die_area_mm2(config: Dict[str, Any]) -> Optional[Decimal]:
|
|
|
105
108
|
return (Decimal(str(um2)) / Decimal("1000000")).quantize(Decimal("0.0001"))
|
|
106
109
|
|
|
107
110
|
|
|
111
|
+
def floorplan_area_is_fixed(config: Dict[str, Any]) -> bool:
|
|
112
|
+
"""True when DIE_AREA is the macro footprint LibreLane will use.
|
|
113
|
+
|
|
114
|
+
``FP_SIZING=relative`` sizes the die from synthesized cells. Absolute
|
|
115
|
+
sizing, and a DIE_AREA with no FP_SIZING, is a fixed footprint.
|
|
116
|
+
"""
|
|
117
|
+
sizing = config.get("FP_SIZING")
|
|
118
|
+
if isinstance(sizing, str) and sizing.strip().lower() == "relative":
|
|
119
|
+
return False
|
|
120
|
+
return die_area_mm2(config) is not None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _apply_die_area(row: Dict[str, Any], config: Dict[str, Any]) -> None:
|
|
124
|
+
"""Record DIE_AREA. A fixed footprint is not replaced by synthesis later."""
|
|
125
|
+
area = die_area_mm2(config)
|
|
126
|
+
if area is None:
|
|
127
|
+
return
|
|
128
|
+
if floorplan_area_is_fixed(config):
|
|
129
|
+
row["estimated_area_mm2"] = str(area)
|
|
130
|
+
row["area_source"] = AREA_SOURCE_DIE
|
|
131
|
+
elif row.get("estimated_area_mm2") is None:
|
|
132
|
+
row["estimated_area_mm2"] = str(area)
|
|
133
|
+
|
|
134
|
+
|
|
108
135
|
def _stem_from_view_path(value: Any) -> Optional[str]:
|
|
109
136
|
if not isinstance(value, str) or not value.strip():
|
|
110
137
|
return None
|
|
@@ -262,6 +289,7 @@ def scan_project(project_root: Path) -> Dict[str, Any]:
|
|
|
262
289
|
"source": "cli_preview",
|
|
263
290
|
"config_path": row["config_path"],
|
|
264
291
|
"estimated_area_mm2": None,
|
|
292
|
+
"area_source": None,
|
|
265
293
|
"gate_count": None,
|
|
266
294
|
"instances": [],
|
|
267
295
|
"integration_strategy": None,
|
|
@@ -283,7 +311,7 @@ def scan_project(project_root: Path) -> Dict[str, Any]:
|
|
|
283
311
|
else:
|
|
284
312
|
parent = design_name.strip()
|
|
285
313
|
|
|
286
|
-
|
|
314
|
+
is_new = parent not in macros_by_name
|
|
287
315
|
parent_row = macros_by_name.setdefault(
|
|
288
316
|
parent,
|
|
289
317
|
{
|
|
@@ -292,19 +320,23 @@ def scan_project(project_root: Path) -> Dict[str, Any]:
|
|
|
292
320
|
"is_top_level": False,
|
|
293
321
|
"source": "cli_preview",
|
|
294
322
|
"config_path": row["config_path"],
|
|
295
|
-
"estimated_area_mm2":
|
|
323
|
+
"estimated_area_mm2": None,
|
|
324
|
+
"area_source": None,
|
|
296
325
|
"gate_count": None,
|
|
297
326
|
"instances": [],
|
|
298
327
|
"integration_strategy": None,
|
|
299
328
|
"lint_status": None,
|
|
300
329
|
},
|
|
301
330
|
)
|
|
302
|
-
if parent_row["config_path"]
|
|
331
|
+
if is_new or not parent_row.get("config_path") or parent_row["config_path"] == row["config_path"]:
|
|
332
|
+
if not is_new and not parent_row.get("config_path"):
|
|
333
|
+
parent_row["config_path"] = row["config_path"]
|
|
334
|
+
parent_row["notes"] = f"from {row['config_path']}"
|
|
335
|
+
_apply_die_area(parent_row, config)
|
|
336
|
+
else:
|
|
303
337
|
notes.append(
|
|
304
338
|
f"Multiple configs declare DESIGN_NAME {parent!r}; using {parent_row['config_path']}"
|
|
305
339
|
)
|
|
306
|
-
elif area is not None and parent_row["estimated_area_mm2"] is None:
|
|
307
|
-
parent_row["estimated_area_mm2"] = str(area)
|
|
308
340
|
|
|
309
341
|
macro_section = config.get("MACROS")
|
|
310
342
|
if isinstance(macro_section, dict):
|
|
@@ -330,6 +362,7 @@ def scan_project(project_root: Path) -> Dict[str, Any]:
|
|
|
330
362
|
"source": "cli_preview",
|
|
331
363
|
"config_path": None,
|
|
332
364
|
"estimated_area_mm2": None,
|
|
365
|
+
"area_source": None,
|
|
333
366
|
"gate_count": None,
|
|
334
367
|
"instances": [],
|
|
335
368
|
"integration_strategy": STRATEGY_HARD_IP,
|
|
@@ -362,6 +395,7 @@ def scan_project(project_root: Path) -> Dict[str, Any]:
|
|
|
362
395
|
"source": "cli_preview",
|
|
363
396
|
"config_path": None,
|
|
364
397
|
"estimated_area_mm2": None,
|
|
398
|
+
"area_source": None,
|
|
365
399
|
"gate_count": None,
|
|
366
400
|
"instances": [],
|
|
367
401
|
"integration_strategy": STRATEGY_HARD_IP,
|
|
@@ -471,12 +505,13 @@ def apply_synth_metrics(
|
|
|
471
505
|
macro["lint_status"] = LINT_FAILED
|
|
472
506
|
if strategy_uses_gate_count(strategy):
|
|
473
507
|
macro["gate_count"] = metrics["gate_count"]
|
|
474
|
-
area
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
508
|
+
# Cell area is the sum of synthesized gates. A fixed DIE_AREA is the
|
|
509
|
+
# footprint OpenLane will actually build.
|
|
510
|
+
if macro.get("area_source") != AREA_SOURCE_DIE:
|
|
511
|
+
area = metrics.get("estimated_area_mm2")
|
|
512
|
+
if area is not None:
|
|
513
|
+
macro["estimated_area_mm2"] = str(area)
|
|
514
|
+
macro["area_source"] = AREA_SOURCE_SYNTHESIS
|
|
480
515
|
|
|
481
516
|
|
|
482
517
|
def leaf_summary(macros: Sequence[Dict[str, Any]]) -> Dict[str, Any]:
|
|
@@ -675,6 +710,7 @@ def build_preview_payload(
|
|
|
675
710
|
"source": "cli_preview",
|
|
676
711
|
"config_path": row.get("config_path"),
|
|
677
712
|
"estimated_area_mm2": row.get("estimated_area_mm2"),
|
|
713
|
+
"area_source": row.get("area_source"),
|
|
678
714
|
"gate_count": row.get("gate_count"),
|
|
679
715
|
"instances": row.get("instances") or [],
|
|
680
716
|
"integration_strategy": row.get("integration_strategy"),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
chipfoundry_cli/__init__.py,sha256=hk8Lld7f5U8fnkyqT4PgWp34qe2KCg8Y2fF-E2DRdys,89
|
|
2
|
+
chipfoundry_cli/check_refs.py,sha256=YHbtH4GSbX5xuWG02DeO4ErjXWDJDPOqUNiiMmzdZoc,1538
|
|
3
|
+
chipfoundry_cli/librelane_run.py,sha256=Er8_oIW43rI9izJRBOD08aQwF12veQZd1cWyguIgzcA,14089
|
|
4
|
+
chipfoundry_cli/main.py,sha256=2l4Q3AVFDzvsqe2rAa6hukwYnS8HMtgQsm88k1q8CE0,263872
|
|
5
|
+
chipfoundry_cli/preview.py,sha256=FTJyso_iuh_4On5isz-nFQMcPGYiFyCRYNZdEj5u75g,36104
|
|
6
|
+
chipfoundry_cli/remote_precheck_git.py,sha256=djJIAUCqJAhg6hIHRTtW7O6UnEGAbNjtW9B1rSQSiSg,13965
|
|
7
|
+
chipfoundry_cli/utils.py,sha256=yh3doTLSxauFDQKTmibgc5TgpCd0emZ1QJBwkETqoDc,33688
|
|
8
|
+
chipfoundry_cli/version_check.py,sha256=V_YkRpMvH3rF8roJlwx8PZh4KaD84_qy3gURYPC2W7o,6473
|
|
9
|
+
chipfoundry_cli-2.7.2.dist-info/METADATA,sha256=HMTi4DEeCCfLo1bgcbwCcspWEuaO-1r_qKBisl_q0sw,37551
|
|
10
|
+
chipfoundry_cli-2.7.2.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
|
|
11
|
+
chipfoundry_cli-2.7.2.dist-info/entry_points.txt,sha256=Kz6Q2a6HSqWHsBUH3CbAOTI5esD9KGul2THYPYUZDwI,86
|
|
12
|
+
chipfoundry_cli-2.7.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
13
|
+
chipfoundry_cli-2.7.2.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
chipfoundry_cli/__init__.py,sha256=izwHokbQs1-p1yLYeJx1BD0XZF0aOVadeay2ZPOULsQ,89
|
|
2
|
-
chipfoundry_cli/check_refs.py,sha256=YHbtH4GSbX5xuWG02DeO4ErjXWDJDPOqUNiiMmzdZoc,1538
|
|
3
|
-
chipfoundry_cli/librelane_run.py,sha256=Er8_oIW43rI9izJRBOD08aQwF12veQZd1cWyguIgzcA,14089
|
|
4
|
-
chipfoundry_cli/main.py,sha256=XjealYq4oTalyjphCGAKKQEWEgopKVtVbDmQ5z8-U9E,262734
|
|
5
|
-
chipfoundry_cli/preview.py,sha256=IcTx8bx9ncLap1mCR8lHGfxymWYgYakmoWtO34RmEkY,34701
|
|
6
|
-
chipfoundry_cli/remote_precheck_git.py,sha256=djJIAUCqJAhg6hIHRTtW7O6UnEGAbNjtW9B1rSQSiSg,13965
|
|
7
|
-
chipfoundry_cli/utils.py,sha256=yh3doTLSxauFDQKTmibgc5TgpCd0emZ1QJBwkETqoDc,33688
|
|
8
|
-
chipfoundry_cli/version_check.py,sha256=V_YkRpMvH3rF8roJlwx8PZh4KaD84_qy3gURYPC2W7o,6473
|
|
9
|
-
chipfoundry_cli-2.7.0.dist-info/METADATA,sha256=bvnqz32Jn5AtbkXUo92tAHixcUmomy2FQ6E-5FPy4Ks,37551
|
|
10
|
-
chipfoundry_cli-2.7.0.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
|
|
11
|
-
chipfoundry_cli-2.7.0.dist-info/entry_points.txt,sha256=Kz6Q2a6HSqWHsBUH3CbAOTI5esD9KGul2THYPYUZDwI,86
|
|
12
|
-
chipfoundry_cli-2.7.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
13
|
-
chipfoundry_cli-2.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|