mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-07 04:53:47 +08:00
22a8575199
Keep official openpilot ancestry and dependency licenses. Store resources directly in Git, remove LFS setup requirements, and leave the downloadable big model outside the source tree.
54 lines
2.1 KiB
Python
54 lines
2.1 KiB
Python
from __future__ import annotations
|
|
import struct, sys, time
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT))
|
|
from tinygrad.runtime.support.usb import USB3
|
|
from tinygrad.runtime.support.system import PCIDevice, System, USBPCIDevice
|
|
|
|
USB_IDS = ((0x3801, 0x0001), (0xADD1, 0x0001))
|
|
NAVI31_DEVICES = ((0xffff, (0x744c,)),)
|
|
|
|
|
|
def open_gpu(index: int = 0, transport: str = 'auto') -> PCIDevice:
|
|
"""Open an AMD GPU through tinygrad's transport-independent PCI interface."""
|
|
if transport not in ('auto', 'usb', 'pci'): raise ValueError(f"unsupported transport {transport!r}")
|
|
candidates = []
|
|
if transport in ('auto', 'usb'):
|
|
for vendor, product in USB_IDS:
|
|
candidates += [(USBPCIDevice, dev) for dev in USB3.list_devices(vendor, product)]
|
|
if transport in ('auto', 'pci'):
|
|
candidates += System.list_devices(0x1002, NAVI31_DEVICES)
|
|
if not candidates: raise RuntimeError(f"no supported {transport} AMD GPU found")
|
|
if not 0 <= index < len(candidates): raise RuntimeError(f"device index {index} out of range (found {len(candidates)})")
|
|
cls, descriptor = candidates[index]
|
|
return cls("AM", *descriptor) if cls is USBPCIDevice else cls("AM", descriptor)
|
|
|
|
|
|
class MMIO:
|
|
"""Transport-independent byte view of BAR5."""
|
|
def __init__(self, pci_dev: PCIDevice): self.bar = pci_dev.map_bar(5, fmt='B')
|
|
|
|
def read32(self, offset: int) -> int:
|
|
return struct.unpack('<I', bytes(self.bar[offset:offset+4]))[0]
|
|
|
|
def write32(self, offset: int, value: int):
|
|
self.write(offset, struct.pack('<I', value & 0xffffffff))
|
|
|
|
def read(self, offset: int, size: int) -> bytes:
|
|
return bytes(self.bar[offset:offset+size])
|
|
|
|
def write(self, offset: int, data: bytes):
|
|
self.bar[offset:offset+len(data)] = data
|
|
|
|
|
|
def wait_until(fn, timeout: float, message: str, interval: float = 0.001):
|
|
if timeout <= 0 or timeout > 60: raise ValueError("timeout must be in (0, 60] seconds")
|
|
end = time.monotonic() + timeout
|
|
while True:
|
|
value = fn()
|
|
if value: return value
|
|
if time.monotonic() >= end: raise TimeoutError(message)
|
|
time.sleep(interval)
|