Files
tinygrad/test/external/external_test_am.py
nimlgen c18307e749 AM driver (#6923)
* connect to gpu

* rlc init?

* gfx comp start init

* early init is hardoded, some progress with fw

* gart

* progress, next mqd

* ring setup, still does not execute anything

* ugh write correct reg

* pci2: vm

* pci2: start psp

* vm seems to work

* pci2: gfx start

* pci2: fix psp ring resp

* pci2: try ring

* pci2: mes and some fixes

* pci2: some progress

* pci2: progress

* pci2: mm

* pci2: discovery

* pci2: correct apertures

* pci2: b

* pci2: i

* pci2: l

* pci2: o

* pci2: cmu

* pci2: mes_kiq works

* pci2: mes

* pci2: kcq does not work(

* pci2: unhalt gfx

* ops_am

* minor

* check if amdgpu is there, or we will crash

* bring back graph, it just works

* less prints

* do not init mes (not used)

* remove unused files

* ops_am: start move into core

* ops_am: works

* clcks, but still slower

* faster + no mes_kiq

* vm frags + remove mes

* cleanup fw

* gmc tiny cleanup

* move to ops_amd

* comment out what we dont really need

* driverless

* close in speed

* am clean most of ips

* gmc to ips

* cleaner

* new vm walker

* comment old one

* remove unsued autogens

* last write ups

* remove psp hardcoded values

* more

* add logs

* ih

* p2p and sdma

* vfio hal and interrupts

* smth

* amd dev iface

* minor after rebase

* bind for sdma

* Revert "bind for sdma"

This reverts commit a90766514d.

* tmp

* debug new mm

* ugh, allreduce hangs fixed

* p1

* works

* no pci.py

* cleaner a bit

* smth

* tiny cleanups

* cleaner a bit

* pciiface

* linter

* linter 2

* linter 3

* linter

* pylint

* reverted unrelated changes

* unrelated

* cmp tool

* ugh wrong fw

* clockgating

* unrelated

* alloc smaller chunks

* this

* opt sigs

* collect stat

* ops

* upd

* proclogs

* proclogs2

* vfio

* ruff

* linter pylint

* oops

* mypy p1

* mem fix

* mypy p2

* mypy p3

* mypy p4

* correct

* minor

* more tests

* linter in tests

* pci_regs header

* minor write up

* setup

* do not require libs

---------

Co-authored-by: George Hotz <72895+geohot@users.noreply.github.com>
2024-12-31 23:06:17 +03:00

163 lines
6.2 KiB
Python

import unittest
from tinygrad.runtime.support.am.amdev import AMMemoryManager
class FakeGMC:
def flush_tlb(self, *args, **kwargs): pass
class FakePCIRegion:
def __init__(self): self.base_addr = 0xc12300000000
class FakePCIDev:
def __init__(self): self.regions = [FakePCIRegion()]
class FakeAM:
def __init__(self):
self.pcidev = FakePCIDev()
self.vram = memoryview(bytearray(4 << 30))
self.gmc = FakeGMC()
self.mm = AMMemoryManager(self, vram_size=4 << 30)
# * PTE format:
# * 63:59 reserved
# * 58:57 reserved
# * 56 F
# * 55 L
# * 54 reserved
# * 53:52 SW
# * 51 T
# * 50:48 mtype
# * 47:12 4k physical page base address
# * 11:7 fragment
# * 6 write
# * 5 read
# * 4 exe
# * 3 Z
# * 2 snooped
# * 1 system
# * 0 valid
def helper_read_entry_components(entry_val):
return {"paddr": entry_val & 0x0000FFFFFFFFF000, "fragment":(entry_val >> 7) & 0x1f, "valid": entry_val & 0x1,
"read": (entry_val >> 5) & 0x1, "write": (entry_val >> 6) & 0x1, "exec": (entry_val >> 4) & 0x1,
"mtype": (entry_val >> 48) & 0x7, "T": (entry_val >> 51) & 0x1, "L": (entry_val >> 55) & 0x1, "F": (entry_val >> 56) & 0x1}
class TestAMPageTable(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.d = [FakeAM() for _ in range(2)]
def test_page_table_walkers(self):
mm = self.d[0].mm
for va,sz in [(0x10000, 0x3000), (0x11000, 0x300000), (0x10000, 0x2000), (0x11000, 0x5000),
(0x2000000, 0x2000), (0x4000000, 0x4000000), (0x38000, 0x303000), (0x8000, 0x1000)]:
exteranl_va = va + AMMemoryManager.va_allocator.base
mm.map_range(vaddr=exteranl_va, size=sz, paddr=va)
results = list(mm.page_table_walker(mm.root_page_table, vaddr=va, size=sz))
total_covered = 0
for tup in results:
_vaddr, _offset, _pte_idx, _n_ptes, _pte_covers, _pt = tup
total_covered += _n_ptes * _pte_covers
assert total_covered == sz, f"Expected total coverage {total_covered} to be {sz}"
for tup in results:
_vaddr, _offset, pte_idx, n_ptes, pte_covers, pt = tup
for i in range(n_ptes):
pte = helper_read_entry_components(pt.get_entry(pte_idx + i))
assert pte['paddr'] == va + _offset + i * pte_covers, f"Expected paddr {pte['paddr']:#x} to be {va + _offset + i * pte_covers:#x}"
assert pte['valid'] == 1
mm.unmap_range(va, sz, free_paddrs=False)
for tup in results:
_vaddr, _offset, pte_idx, n_ptes, pte_covers, pt = tup
for i in range(n_ptes):
pte = helper_read_entry_components(pt.get_entry(pte_idx + i))
assert pte['paddr'] == 0
assert pte['valid'] == 0
def test_double_map(self):
mm0 = self.d[0].mm
for va,sz in [(0x10000, 0x3000), (0x1000000, 0x1000000), (0x12000, 0x4000)]:
exteranl_va = va + AMMemoryManager.va_allocator.base
mm0.map_range(vaddr=exteranl_va, size=sz, paddr=va)
with self.assertRaises(AssertionError):
mm0.map_range(vaddr=exteranl_va, size=0x1000, paddr=va)
with self.assertRaises(AssertionError):
mm0.map_range(vaddr=exteranl_va, size=0x100000, paddr=va)
with self.assertRaises(AssertionError):
mm0.map_range(vaddr=exteranl_va + 0x1000, size=0x1000, paddr=va)
with self.assertRaises(AssertionError):
mm0.map_range(vaddr=exteranl_va + 0x2000, size=0x100000, paddr=va)
mm0.unmap_range(vaddr=exteranl_va, size=sz, free_paddrs=False)
# Finally can map and check paddrs
mm0.map_range(vaddr=exteranl_va + 0x2000, size=0x100000, paddr=0xdead0000)
for tup in mm0.page_table_walker(mm0.root_page_table, vaddr=va + 0x2000, size=0x100000):
_vaddr, _offset, pte_idx, n_ptes, pte_covers, pt = tup
for i in range(n_ptes):
pte = helper_read_entry_components(pt.get_entry(pte_idx + i))
assert pte['paddr'] == 0xdead0000 + _offset + i * pte_covers, f"paddr {pte['paddr']:#x} not {0xdead0000 + _offset + i * pte_covers:#x}"
assert pte['valid'] == 1
mm0.unmap_range(vaddr=exteranl_va + 0x2000, size=0x100000, free_paddrs=False)
def test_map_from(self):
mm0 = self.d[0].mm
mm1 = self.d[1].mm
for va,sz in [(0x10000, 0x3000), (0x11000, 0x300000), (0x10000, 0x2000), (0x11000, 0x5000),
(0x2000000, 0x2000), (0x4000000, 0x4000000), (0x38000, 0x303000), (0x8000, 0x1000)]:
exteranl_va = va + AMMemoryManager.va_allocator.base
mm0.map_range(vaddr=exteranl_va, size=sz, paddr=va)
mm1.map_range(vaddr=exteranl_va, size=sz, paddr=va)
with self.assertRaises(AssertionError):
mm0.map_from(vaddr=exteranl_va, size=sz, from_adev=mm0.adev) # self mapping -- bad
with self.assertRaises(AssertionError):
mm0.map_from(vaddr=exteranl_va, size=sz, from_adev=mm1.adev) # mapping from mm1 to same addrs -- bad
mm0.unmap_range(vaddr=exteranl_va, size=sz, free_paddrs=False) # unmap from mm0
mm0.map_from(vaddr=exteranl_va, size=sz, from_adev=mm1.adev) # mapping from mm1 to same addrs -- ok
d1_pci_base = self.d[1].pcidev.regions[0].base_addr
for tup in mm0.page_table_walker(mm0.root_page_table, vaddr=va, size=sz):
_vaddr, _offset, pte_idx, n_ptes, pte_covers, pt = tup
for i in range(n_ptes):
pte = helper_read_entry_components(pt.get_entry(pte_idx + i))
assert pte['paddr'] == d1_pci_base + va + _offset + i * pte_covers, f"paddr {pte['paddr']:#x} not {d1_pci_base+va+_offset+i*pte_covers:#x}"
assert pte['valid'] == 1
mm0.unmap_range(vaddr=exteranl_va, size=sz, free_paddrs=False)
mm1.unmap_range(vaddr=exteranl_va, size=sz, free_paddrs=False)
def test_try_bad_unmap(self):
mm0 = self.d[0].mm
with self.assertRaises(AssertionError):
mm0.unmap_range(0x10000, 0x3000, free_paddrs=False)
mm0.map_range(0x10000, 0x3000, 0x10000)
mm0.unmap_range(0x10000, 0x3000, free_paddrs=False)
with self.assertRaises(AssertionError):
mm0.unmap_range(0x10000, 0x3000, free_paddrs=False)
mm0.map_range(0x10000, 0x3000, 0x10000)
mm0.unmap_range(0x10000, 0x3000, free_paddrs=False)
with self.assertRaises(AssertionError):
mm0.unmap_range(0x10000, 0x3000, free_paddrs=False)
if __name__ == "__main__":
unittest.main()