💻 Modül 6 · Yazılım Yığını · Bölüm 6.1 · 11 dk okuma

İşletim Sistemi ve PCIe Sürücü Temelleri

Linux'tan SIDRA donanımına ilk dokunuş — sürücü mimarisi.

Bu bölümde öğreneceklerin

  • Linux kernel modülü ve user-space ayrımını anla
  • PCIe enumeration sürecini ve BAR (Base Address Register) kavramını söyle
  • Karakter cihaz dosyaları (/dev/sidra0) ile yazılım API'si arasındaki bağı kur
  • Interrupt vs polling tasarım tercihini açıkla
  • SIDRA yazılım yığınının 5 katmanını (driver → firmware → SDK → compiler → app) tanımla

Açılış: Donanım Olmadan Yazılım Yetersiz

Modül 5’te SIDRA donanımı tamamlandı. Ama çıplak çip işe yaramaz. Yazılım yığını çipi kullanılabilir hale getirir:

[Application]      → kullanıcı kodu (PyTorch, app)
[SDK / API]        → SIDRA'ya özel kütüphane
[Compiler]         → PyTorch model → SIDRA assembly
[Driver]           → Linux kernel modül (PCIe iletişim)
[Firmware]         → SIDRA on-chip RISC-V
[Donanım]          → YILDIRIM çip

Bu modül 10 bölüm boyunca her katmanı açar. Bu bölüm en alt: driver + OS temelleri.

Sezgi: Linux + PCIe + Cihaz Dosyası

Linux donanım modeli:

User-space (uygulamalar) doğrudan donanıma erişemez. Kernel arayüzü (system call) gerekir.

PCIe cihazları için:

  1. BIOS boot’ta PCIe enumeration (vendor + device ID).
  2. Linux kernel cihaz tanımıyla driver’ı eşleştirir.
  3. Driver donanımı /dev/sidra0 cihaz dosyasıyla user-space’e açar.
  4. App read()/write()/ioctl() ile etkileşir.

SIDRA driver işlevleri:

  • Çipi initialize et (boot kalibrasyon).
  • Memori mapleri (BAR) hazırla.
  • DMA buffer ayır.
  • Interrupt handle et (inference complete).
  • IOCTL ile yazılım kontrolü.

Formalizm: PCIe Driver Detayları

L1 · Başlangıç

PCIe BAR (Base Address Register):

Çip kendi memori bölgesini bildirir. Linux fiziksel adres atar.

Y1 BAR layout:

  • BAR0: 16 MB MMIO control registers.
  • BAR1: 256 MB DMA buffer area.
  • BAR2: 16 GB L3 SRAM mapping.

User-space kod mmap() ile BAR’ları okuyabilir/yazabilir.

Kernel modül iskeleti (Linux):

static int sidra_probe(struct pci_dev *dev, const struct pci_device_id *id) {
    pci_enable_device(dev);
    pci_request_regions(dev, "sidra");
    bar0 = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0));
    request_irq(dev->irq, sidra_interrupt_handler, ...);
    cdev_add(...);  // /dev/sidra0
    return 0;
}

static struct pci_driver sidra_driver = {
    .name = "sidra",
    .id_table = sidra_ids,
    .probe = sidra_probe,
    .remove = sidra_remove,
};

Module init: module_init(sidra_driver_init);. insmod sidra.ko kurulum.

Cihaz dosyası:

/dev/sidra0 user-space erişim. Açma:

fd = open("/dev/sidra0", O_RDWR);
L2 · Tam

Inference akışı (driver perspektifi):

  1. App SDK çağrısı → driver IOCTL.
  2. Driver input verisini DMA buffer’a kopyalar.
  3. Driver çipe komut yazar (BAR0 register).
  4. Çip inference başlar (donanım).
  5. Inference biter → çip interrupt yükseltir.
  6. Driver interrupt handle eder, output DMA buffer’dan okur.
  7. App’e dönderir.

Tipik latency:

  • IOCTL overhead: ~5 µs.
  • DMA setup: ~1 µs.
  • Çip inference: ~5 µs.
  • Interrupt handle: ~10 µs.
  • Toplam: ~21 µs/inference.

Polling alternatifi:

Interrupt yerine driver register polling. Daha düşük latency (interrupt handle yok), ama CPU sürekli meşgul.

SIDRA Y1 küçük inference için polling, büyük batch için interrupt. Hibrit.

DMA mapping:

Linux dma_alloc_coherent() cihaz + CPU senkron buffer ayırır. Cache flush sorunu yok.

Y1 DMA ring buffer: 4 MB (yeterli ~1000 inference için).

L3 · Derin

Kernel ↔ User-space iletişim:

3 yöntem:

  1. read/write: klasik dosya çağrısı. Yavaş (kopya).
  2. mmap: BAR doğrudan user-space’e açılır. Sıfır kopya.
  3. ioctl: kontrol komutu (örn. “model yükle”, “inference başla”).

SIDRA SDK bu üçünü birlikte kullanır.

Çoklu süreç (multi-process):

Birden fazla app SIDRA’ya erişebilir. Driver sandık.

Yöntemler:

  • Time-sharing (her app sırayla).
  • Hardware partitioning (cluster’lar farklı app’lere ayrılır).
  • Virtual SIDRA (her app kendi ‘cüce’ SIDRA görür, gerçekte paylaşılan donanım).

Y1 time-sharing standart. Y10 virtualization eklenecek.

ABI stabilite:

Driver API stabil olmalı (eski uygulamalar yeni driver’la çalışsın). SIDRA driver versionlama: SIDRA_API_V1.0, gelişme V2.0 ekler ama V1 desteklemeye devam.

Güvenlik:

User-space çipe doğrudan komut göndermesin (kötü amaç). Driver yetki kontrolü:

  • Linux capabilities (CAP_SYS_RAWIO).
  • /dev/sidra0 izinleri (root veya sidra grubu).

Inference için yetki yeter; programlama (model yükleme) için sudo.

Hata yönetimi:

Çip aşırı ısınırsa, ECC failure, vb. → driver event oluşturur. App callback alır.

sysfs üzerinden status: /sys/class/sidra/sidra0/temperature, /error_count.

Modül 6 yol haritası:

  • 6.1 (bu): PCIe driver temelleri.
  • 6.2: Linux kernel ve aether-driver.
  • 6.3: SIDRA on-chip RISC-V firmware.
  • 6.4: ISPP algoritması.
  • 6.5: SDK katmanları.
  • 6.6: PyTorch backend.
  • 6.7: Compiler.
  • 6.8: Digital twin / simulator.
  • 6.9: Test, kalibrasyon, doğrulama.
  • 6.10: Üretim yığını lab.

Deney: SIDRA Driver Hello World

Senaryo: “/dev/sidra0” aç, donanım versiyonu oku.

#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>

#define SIDRA_IOCTL_VERSION _IOR('s', 1, int)

int main() {
    int fd = open("/dev/sidra0", O_RDWR);
    if (fd < 0) {
        perror("open");
        return 1;
    }
    
    int version;
    if (ioctl(fd, SIDRA_IOCTL_VERSION, &version) < 0) {
        perror("ioctl");
        return 1;
    }
    
    printf("SIDRA donanım versiyonu: 0x%08x\n", version);
    close(fd);
    return 0;
}

Compile: gcc -o sidra_hello sidra_hello.c.

Çalıştır: ./sidra_hello.

Çıktı: SIDRA donanım versiyonu: 0x00010000 (Y1 v1.0).

Driver bu IOCTL’ı yakalar, BAR0 register’dan version okur, user-space’e döndürür. Latency ~10 µs.

SDK alternatifi (daha yüksek seviye):

import sidra
chip = sidra.Chip(0)
print(f"Version: {chip.version}, Memristors: {chip.memristor_count}")

Aynı şey, daha temiz API.

Kısa Sınav

1/6Linux'ta SIDRA driver'ı hangi katmandadır?

Laboratuvar Görevi

SIDRA Y1 inference benchmark planlama.

Senaryo:

  • Y1 PCIe 5.0 × 4 = 16 GB/s.
  • Inference süresi (donanım): 5 µs/MNIST.
  • Driver overhead: 20 µs.
  • Toplam: 25 µs/inference.

Sorular:

(a) Saniyede kaç inference? (b) Batch 32 için süre + bandwidth? (c) PCIe darboğaz olur mu? (d) Optimum batch boyutu?

Çözümler

(a) 1/25 µs = 40K inference/saniye.

(b) Batch 32 input: 32 × 28×28 = 25 KB. Transfer: 25 KB / 16 GB/s = 1.6 µs. Inference paralel batch 32 → ~100 µs. Toplam: 100 + 20 = 120 µs/batch = 267K inference/s (batch ile 6.7× hızlanır).

(c) PCIe 16 GB/s × 1 ms = 16 MB. Inference 25 KB × 40K = 1 MB/s. PCIe çok rahat. Darboğaz driver/inference.

(d) Optimum batch = donanım ile bandwith dengesi. Y1 için 16-32 ideal. 64+‘da driver overhead amortize edilse de inference yavaşlar (paralel kapasite sınırı).

Özet Kart

  • Yazılım yığını 5 katman: firmware, driver, SDK, compiler, app.
  • Linux driver: kernel modülü, PCIe enumerate, BAR map, /dev/sidra0.
  • User-space erişim: open/read/write/ioctl, mmap.
  • Inference latency: donanım 5 µs + driver 20 µs = 25 µs.
  • DMA buffer: 4 MB ring, donanım otonom transfer.
  • Polling vs interrupt: Y1 hibrit.

Vizyon: Linux'tan Bağımsız SIDRA?

  • Y1: Linux + Windows driver.
  • Y3: Android + iOS desteği (mobil).
  • Y10: RTOS desteği (embedded, otomotiv).
  • Y100: SIDRA-native OS (Modül 5.1 vizyonundan).
  • Y1000: Bio-uyumlu OS (beyin implant arayüzü).

Türkiye için: Linux kernel’a SIDRA upstream → uluslararası katkı. Türk yazılımcılar mainline kernel’a katkı yaparak SIDRA görünür olur.

Daha İleri