130 lines
4.5 KiB
Python
130 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Export the authoritative Ti375 C529 package map from Efinity.
|
|
|
|
Run with Efinity's bundled Python because the resource pickle contains Efinity
|
|
classes. No pin name or ball assignment is embedded in this script.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import csv
|
|
import gzip
|
|
import hashlib
|
|
import json
|
|
import pickle
|
|
import re
|
|
from pathlib import Path
|
|
|
|
|
|
HSIO_BANKS = {"2A", "2B", "2C", "2D", "2E", "4A_4B", "4C", "4D"}
|
|
HVIO_BANKS = {"BL2_BL3", "BR0", "BR3_BR4", "TL1_TL5", "TR0", "TR1", "TR2"}
|
|
|
|
|
|
def natural_ball(ball: str) -> tuple[str, int]:
|
|
match = re.fullmatch(r"([A-Z]+)([0-9]+)", ball)
|
|
if not match:
|
|
return ball, 0
|
|
return match.group(1), int(match.group(2))
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"--db",
|
|
type=Path,
|
|
default=Path("/tools/efinix/efinity/2025.2/pt/db/resource/Ti375C529.db"),
|
|
)
|
|
parser.add_argument("--csv", type=Path, default=Path("docs/ti375_c529_package.csv"))
|
|
parser.add_argument("--meta", type=Path, default=Path("docs/ti375_c529_package.meta.json"))
|
|
args = parser.parse_args()
|
|
|
|
with gzip.open(args.db, "rb") as stream:
|
|
device = pickle.load(stream)
|
|
|
|
package = device.get_package()
|
|
io_db = device._PeripheryDevice__io_pad
|
|
io_by_pad = {
|
|
vars(item)["_IOPadInfo__pad_name"]: vars(item)
|
|
for item in io_db.get_all_io_pads()
|
|
}
|
|
|
|
rows: list[dict[str, str]] = []
|
|
for ball, mapping in sorted(package.get_package_pad_map().items(), key=lambda pair: natural_ball(pair[0])):
|
|
pad = mapping.get_pad_name()
|
|
info = io_by_pad.get(pad, {})
|
|
die_bank = info.get("_IOPadInfo__bank_name", "")
|
|
package_bank = info.get("_IOPadInfo__pkg_bank_name", "")
|
|
direction_obj = info.get("_IOPadInfo__direction")
|
|
direction = getattr(direction_obj, "name", "")
|
|
instances = info.get("_IOPadInfo__instances", [])
|
|
|
|
if package_bank in HSIO_BANKS:
|
|
bank_class = "HSIO"
|
|
allowed_vccio = "1.2;1.35;1.5;1.8"
|
|
elif package_bank in HVIO_BANKS:
|
|
bank_class = "HVIO"
|
|
allowed_vccio = "1.8;2.5;3.0;3.3"
|
|
else:
|
|
bank_class = "HARD/POWER"
|
|
allowed_vccio = ""
|
|
|
|
special: list[str] = []
|
|
upper_pad = pad.upper()
|
|
if "CLK" in upper_pad:
|
|
special.append("CLOCK_CAPABLE")
|
|
if "PLLIN" in upper_pad:
|
|
special.append("PLL_INPUT")
|
|
if "EXTFB" in upper_pad:
|
|
special.append("PLL_EXTFB")
|
|
if "CDI" in upper_pad:
|
|
special.append("CORE_DATA_INPUT")
|
|
if "EXTSPI" in upper_pad:
|
|
special.append("EXT_SPI")
|
|
if "CBSEL" in upper_pad:
|
|
special.append("CONFIG_BOOT_SELECT")
|
|
if re.search(r"_(P|N)(?:_|$)", upper_pad):
|
|
special.append("DIFFERENTIAL_MEMBER")
|
|
|
|
is_fabric_gpio = pad.startswith(("GPIOB_", "GPIOT_", "GPIOL_", "GPIOR_"))
|
|
rows.append(
|
|
{
|
|
"ball": ball,
|
|
"official_pad_name": pad,
|
|
"die_bank": die_bank,
|
|
"package_bank": package_bank,
|
|
"bank_class": bank_class,
|
|
"allowed_vccio_v": allowed_vccio,
|
|
"direction": direction,
|
|
"function": info.get("_IOPadInfo__function", ""),
|
|
"periphery_instances": ";".join(instances),
|
|
"instance_pin": info.get("_IOPadInfo__pin", "") or "",
|
|
"special_capability": ";".join(special),
|
|
"fabric_gpio": "yes" if is_fabric_gpio else "no",
|
|
}
|
|
)
|
|
|
|
args.csv.parent.mkdir(parents=True, exist_ok=True)
|
|
with args.csv.open("w", newline="", encoding="utf-8") as stream:
|
|
writer = csv.DictWriter(stream, fieldnames=list(rows[0]))
|
|
writer.writeheader()
|
|
writer.writerows(rows)
|
|
|
|
digest = hashlib.sha256(args.db.read_bytes()).hexdigest()
|
|
metadata = {
|
|
"device": device.get_device_name(),
|
|
"mapped_device": device.get_device_mapped_name(),
|
|
"package": package.get_package_name(),
|
|
"package_status": package.get_status_str(),
|
|
"source_database": str(args.db),
|
|
"source_sha256": digest,
|
|
"row_count": len(rows),
|
|
"fabric_gpio_count": sum(row["fabric_gpio"] == "yes" for row in rows),
|
|
"package_banks": package.get_package_bank_names(),
|
|
}
|
|
args.meta.write_text(json.dumps(metadata, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|