std1.0.0-beta-7 SafeC docs

Source hal/riscv.h

View in the repository

// SafeC Standard Library — RISC-V HAL (CLINT, PLIC, CSRs)
// Freestanding-safe. Addresses follow the SiFive FE310 / standard RISC-V MMIO map.
#pragma once

// ── CSR helpers ───────────────────────────────────────────────────────────────
// Read / write arbitrary CSRs by name (uses inline asm).

namespace std {

unsigned long rv_csr_read_mstatus();
void          rv_csr_write_mstatus(unsigned long val);
unsigned long rv_csr_read_mie();
void          rv_csr_write_mie(unsigned long val);
unsigned long rv_csr_read_mip();
unsigned long rv_csr_read_mcause();
unsigned long rv_csr_read_mepc();
void          rv_csr_write_mepc(unsigned long val);
unsigned long rv_csr_read_mtvec();
void          rv_csr_write_mtvec(unsigned long val);
unsigned long rv_csr_read_time();
unsigned long rv_csr_read_cycle();
unsigned long rv_csr_read_instret();

// Global interrupt enable / disable.
void rv_global_irq_enable();
void rv_global_irq_disable();

// ── CLINT — Core-Local Interruptor ────────────────────────────────────────────
#define CLINT_BASE  0x02000000UL

struct Clint {
    unsigned long base;

    // Software interrupt (msip) for hart `hart_id`.
    void  set_msip(unsigned int hart_id);
    void  clear_msip(unsigned int hart_id);

    // Machine timer compare for hart 0.
    void          set_mtimecmp(unsigned long long cmp);
    unsigned long long read_mtime() const;

    // Schedule a timer interrupt `delta` ticks in the future.
    void  schedule(unsigned long delta);
};

extern struct Clint clint;
void clint_init(unsigned long base_addr);

// ── PLIC — Platform-Level Interrupt Controller ───────────────────────────────
#define PLIC_BASE  0x0C000000UL
#define PLIC_MAX_IRQ  53

struct Plic {
    unsigned long base;

    // Set interrupt priority (1–7; 0 = disabled).
    void  set_priority(unsigned int irq, unsigned int priority);

    // Enable interrupt `irq` for target context 0 (M-mode hart 0).
    void  enable(unsigned int irq);
    void  disable(unsigned int irq);

    // Set priority threshold for context 0.
    void  set_threshold(unsigned int threshold);

    // Claim highest-priority pending interrupt; returns IRQ number (0 = none).
    unsigned int claim();

    // Complete interrupt handling for `irq`.
    void  complete(unsigned int irq);
};

extern struct Plic plic;
void plic_init(unsigned long base_addr);

} // namespace std