chipfoundry-cli 1.2.10__tar.gz → 1.3.0__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.
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/PKG-INFO +1 -1
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/chipfoundry_cli/main.py +22 -120
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/pyproject.toml +1 -1
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/LICENSE +0 -0
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/README.md +0 -0
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/chipfoundry_cli/__init__.py +0 -0
- {chipfoundry_cli-1.2.10 → chipfoundry_cli-1.3.0}/chipfoundry_cli/utils.py +0 -0
|
@@ -350,7 +350,8 @@ def init(project_root):
|
|
|
350
350
|
|
|
351
351
|
@main.command('gpio-config')
|
|
352
352
|
@click.option('--project-root', required=False, type=click.Path(exists=True, file_okay=False), help='Path to the project directory (defaults to current directory).')
|
|
353
|
-
|
|
353
|
+
@click.option('--view', is_flag=True, help='Display current GPIO configuration summary without editing.')
|
|
354
|
+
def gpio_config(project_root, view):
|
|
354
355
|
"""Configure GPIO settings interactively and save to project config and user_defines.v."""
|
|
355
356
|
if not project_root:
|
|
356
357
|
project_root = os.getcwd()
|
|
@@ -547,6 +548,17 @@ def gpio_config(project_root):
|
|
|
547
548
|
# Initialize gpio_configs
|
|
548
549
|
gpio_configs = existing_configs.copy() if existing_configs else {}
|
|
549
550
|
|
|
551
|
+
# If --view flag is set, just display the summary and return
|
|
552
|
+
if view:
|
|
553
|
+
if not gpio_configs:
|
|
554
|
+
console.print("[yellow]No GPIO configuration found.[/yellow]")
|
|
555
|
+
console.print("[dim]Run 'cf gpio-config' to configure GPIOs.[/dim]")
|
|
556
|
+
return
|
|
557
|
+
console.print(f"\n[bold cyan]GPIO Configuration ({gpio_label})[/bold cyan]")
|
|
558
|
+
display_summary(gpio_configs, user_to_real_map)
|
|
559
|
+
console.print()
|
|
560
|
+
return
|
|
561
|
+
|
|
550
562
|
# ========================
|
|
551
563
|
# HEADER
|
|
552
564
|
# ========================
|
|
@@ -576,7 +588,7 @@ def gpio_config(project_root):
|
|
|
576
588
|
if not mode_key:
|
|
577
589
|
return "red"
|
|
578
590
|
elif "output" in mode_key:
|
|
579
|
-
return "
|
|
591
|
+
return "ansi_bright_green"
|
|
580
592
|
elif "input" in mode_key:
|
|
581
593
|
return "cyan"
|
|
582
594
|
elif "bidirectional" in mode_key:
|
|
@@ -719,7 +731,7 @@ def gpio_config(project_root):
|
|
|
719
731
|
}
|
|
720
732
|
|
|
721
733
|
.mode-btn-output {
|
|
722
|
-
color:
|
|
734
|
+
color: ansi_bright_green;
|
|
723
735
|
}
|
|
724
736
|
|
|
725
737
|
.mode-btn-input {
|
|
@@ -1198,118 +1210,6 @@ def gpio_config(project_root):
|
|
|
1198
1210
|
console.print(f"[red]Error updating user_defines.v: {e}[/red]")
|
|
1199
1211
|
|
|
1200
1212
|
|
|
1201
|
-
@main.command('gpio-status')
|
|
1202
|
-
@click.option('--project-root', required=False, type=click.Path(exists=True, file_okay=False), help='Path to the project directory (defaults to current directory).')
|
|
1203
|
-
def gpio_status(project_root):
|
|
1204
|
-
"""Display current GPIO configuration summary."""
|
|
1205
|
-
if not project_root:
|
|
1206
|
-
project_root = os.getcwd()
|
|
1207
|
-
|
|
1208
|
-
project_root = Path(project_root)
|
|
1209
|
-
|
|
1210
|
-
# Load project config
|
|
1211
|
-
project_json_path = project_root / '.cf' / 'project.json'
|
|
1212
|
-
if not project_json_path.exists():
|
|
1213
|
-
console.print("[red]Error: No project configuration found.[/red]")
|
|
1214
|
-
console.print("[dim]Run 'cf gpio-config' first to configure GPIOs.[/dim]")
|
|
1215
|
-
return
|
|
1216
|
-
|
|
1217
|
-
with open(project_json_path, 'r') as f:
|
|
1218
|
-
project_config = json.load(f)
|
|
1219
|
-
|
|
1220
|
-
# GPIO config is stored under project.gpio_config
|
|
1221
|
-
project_data = project_config.get('project', {})
|
|
1222
|
-
gpio_configs = project_data.get('gpio_config', {})
|
|
1223
|
-
if not gpio_configs:
|
|
1224
|
-
console.print("[yellow]No GPIO configuration found in project.json[/yellow]")
|
|
1225
|
-
console.print("[dim]Run 'cf gpio-config' to configure GPIOs.[/dim]")
|
|
1226
|
-
return
|
|
1227
|
-
|
|
1228
|
-
# Detect project type
|
|
1229
|
-
project_type = project_data.get('type')
|
|
1230
|
-
if not project_type:
|
|
1231
|
-
project_type = detect_project_type(project_root)
|
|
1232
|
-
|
|
1233
|
-
# Determine GPIO range based on project type
|
|
1234
|
-
if project_type == 'caravan':
|
|
1235
|
-
user_gpio_range = list(range(0, 32))
|
|
1236
|
-
gpio_label = "Caravan"
|
|
1237
|
-
else:
|
|
1238
|
-
user_gpio_range = list(range(5, 38))
|
|
1239
|
-
gpio_label = "Caravel"
|
|
1240
|
-
|
|
1241
|
-
user_to_real_map = {g: g for g in user_gpio_range}
|
|
1242
|
-
|
|
1243
|
-
# Convert string keys back to int if needed
|
|
1244
|
-
gpio_configs_int = {}
|
|
1245
|
-
for k, v in gpio_configs.items():
|
|
1246
|
-
try:
|
|
1247
|
-
gpio_configs_int[int(k)] = v
|
|
1248
|
-
except (ValueError, TypeError):
|
|
1249
|
-
gpio_configs_int[k] = v
|
|
1250
|
-
|
|
1251
|
-
def find_mode_key(mode_value):
|
|
1252
|
-
"""Find the mode key for a given mode value (handles hex values)."""
|
|
1253
|
-
if not mode_value:
|
|
1254
|
-
return None
|
|
1255
|
-
# First, try to convert hex to mode constant name
|
|
1256
|
-
mode_name = GPIO_HEX_TO_MODE.get(mode_value, mode_value)
|
|
1257
|
-
# Then find the short key for that mode constant
|
|
1258
|
-
for key, name in GPIO_MODES.items():
|
|
1259
|
-
if name == mode_name and key != "invalid":
|
|
1260
|
-
return key
|
|
1261
|
-
return None
|
|
1262
|
-
|
|
1263
|
-
def format_gpio_ranges(gpio_list):
|
|
1264
|
-
"""Convert [5,6,7,10,11,15] to '5-7, 10-11, 15'."""
|
|
1265
|
-
if not gpio_list:
|
|
1266
|
-
return "-"
|
|
1267
|
-
gpio_list = sorted(gpio_list)
|
|
1268
|
-
ranges = []
|
|
1269
|
-
start = gpio_list[0]
|
|
1270
|
-
end = start
|
|
1271
|
-
for g in gpio_list[1:]:
|
|
1272
|
-
if g == end + 1:
|
|
1273
|
-
end = g
|
|
1274
|
-
else:
|
|
1275
|
-
ranges.append(f"{start}-{end}" if start != end else str(start))
|
|
1276
|
-
start = end = g
|
|
1277
|
-
ranges.append(f"{start}-{end}" if start != end else str(start))
|
|
1278
|
-
return ", ".join(ranges)
|
|
1279
|
-
|
|
1280
|
-
# Group by mode
|
|
1281
|
-
mode_groups = {}
|
|
1282
|
-
for user_gpio, real_gpio in user_to_real_map.items():
|
|
1283
|
-
mode_value = gpio_configs_int.get(real_gpio)
|
|
1284
|
-
mode_key = find_mode_key(mode_value) if mode_value else None
|
|
1285
|
-
if mode_key not in mode_groups:
|
|
1286
|
-
mode_groups[mode_key] = []
|
|
1287
|
-
mode_groups[mode_key].append(user_gpio)
|
|
1288
|
-
|
|
1289
|
-
console.print(f"\n[bold cyan]GPIO Configuration ({gpio_label})[/bold cyan]\n")
|
|
1290
|
-
|
|
1291
|
-
table = Table(show_header=True, header_style="bold", box=None, padding=(0, 2))
|
|
1292
|
-
table.add_column("Mode", style="cyan", width=24)
|
|
1293
|
-
table.add_column("Count", justify="right", width=6)
|
|
1294
|
-
table.add_column("GPIOs")
|
|
1295
|
-
|
|
1296
|
-
# Sort by count (most common first)
|
|
1297
|
-
for mode_key in sorted(mode_groups.keys(), key=lambda k: -len(mode_groups[k])):
|
|
1298
|
-
gpios = mode_groups[mode_key]
|
|
1299
|
-
display_name = mode_key if mode_key else "[red]unconfigured[/red]"
|
|
1300
|
-
style = ""
|
|
1301
|
-
if mode_key:
|
|
1302
|
-
if "output" in mode_key: style = "[green]"
|
|
1303
|
-
elif "input" in mode_key: style = "[cyan]"
|
|
1304
|
-
elif "bidirectional" in mode_key: style = "[yellow]"
|
|
1305
|
-
elif "analog" in mode_key: style = "[magenta]"
|
|
1306
|
-
display_name = f"{style}{mode_key}[/]"
|
|
1307
|
-
table.add_row(display_name, str(len(gpios)), format_gpio_ranges(gpios))
|
|
1308
|
-
|
|
1309
|
-
console.print(table)
|
|
1310
|
-
console.print()
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
1213
|
@main.command('push')
|
|
1314
1214
|
@click.option('--project-root', required=False, type=click.Path(exists=True, file_okay=False), help='Path to the local ChipFoundry project directory (defaults to current directory if .cf/project.json exists).')
|
|
1315
1215
|
@click.option('--sftp-host', default=DEFAULT_SFTP_HOST, show_default=True, help='SFTP server hostname.')
|
|
@@ -2608,12 +2508,10 @@ def setup(project_root, repo_owner, repo_name, branch, pdk, caravel_lite,
|
|
|
2608
2508
|
def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry_run):
|
|
2609
2509
|
"""Harden a macro using LibreLane (OpenLane 2).
|
|
2610
2510
|
|
|
2611
|
-
If no macro is specified, lists all available macros.
|
|
2612
|
-
|
|
2613
2511
|
Examples:
|
|
2614
|
-
cf harden # List available macros
|
|
2615
2512
|
cf harden user_proj_example # Harden a specific macro
|
|
2616
2513
|
cf harden user_project_wrapper
|
|
2514
|
+
cf harden --list # List available macros
|
|
2617
2515
|
"""
|
|
2618
2516
|
from datetime import datetime
|
|
2619
2517
|
|
|
@@ -2641,13 +2539,17 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
|
|
|
2641
2539
|
console.print("[yellow]Run 'cf setup' first to install OpenLane[/yellow]")
|
|
2642
2540
|
return
|
|
2643
2541
|
|
|
2644
|
-
# If no macro specified,
|
|
2542
|
+
# If no macro specified, show prompt with available macros
|
|
2543
|
+
no_macro_specified = not macro and not list_designs
|
|
2645
2544
|
if not macro:
|
|
2646
2545
|
list_designs = True
|
|
2647
2546
|
|
|
2648
2547
|
# List designs if requested (or if no macro specified)
|
|
2649
2548
|
if list_designs:
|
|
2650
|
-
|
|
2549
|
+
if no_macro_specified:
|
|
2550
|
+
console.print("[yellow]Please specify a macro from this list:[/yellow]")
|
|
2551
|
+
else:
|
|
2552
|
+
console.print("[bold cyan]Available macros:[/bold cyan]")
|
|
2651
2553
|
designs = [d.name for d in openlane_dir.iterdir() if d.is_dir() and ((d / 'config.json').exists() or (d / 'config.yaml').exists() or (d / 'config.tcl').exists())]
|
|
2652
2554
|
if designs:
|
|
2653
2555
|
for design in sorted(designs):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|