1376 lines
35 KiB
HTML
1376 lines
35 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Documentation - ReviveSparc</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="header">
|
|
<div class="inner">
|
|
<h1><a href="index.html">ReviveSparc</a></h1>
|
|
<p class="subtitle">An open-source OpenSPARC ISA reimplementation</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="nav">
|
|
<div class="inner">
|
|
<ul>
|
|
<li><a href="index.html">Home</a></li>
|
|
<li><a href="about.html">About</a></li>
|
|
<li><a href="download.html">Download</a></li>
|
|
<li><a href="docs.html" class="active">Docs</a></li>
|
|
<li><a href="news.html">News</a></li>
|
|
<li><a href="roadmap.html">Roadmap</a></li>
|
|
<li><a href="screenshots.html">Screenshots</a></li>
|
|
<li><a href="community.html">Community</a></li>
|
|
<li><a href="sponsors.html">Sponsors</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="doc-wrapper">
|
|
<div id="doc-sidebar">
|
|
<h3>Getting Started</h3>
|
|
<ul>
|
|
<li><a href="#getting-started" class="doc-link">Getting Started</a></li>
|
|
<li><a href="#build-guide" class="doc-link">Build Guide</a></li>
|
|
<li><a href="#faq" class="doc-link">FAQ</a></li>
|
|
</ul>
|
|
|
|
<h3>Architecture</h3>
|
|
<ul>
|
|
<li><a href="#isa-reference" class="doc-link">ISA Reference</a></li>
|
|
<li><a href="#cmt" class="doc-link">CMT Implementation</a></li>
|
|
<li><a href="#memory-model" class="doc-link">Memory Model</a></li>
|
|
</ul>
|
|
|
|
<h3>OS Support</h3>
|
|
<ul>
|
|
<li><a href="#linux-guide" class="doc-link">Linux Guide</a></li>
|
|
</ul>
|
|
|
|
<h3>Hardware</h3>
|
|
<ul>
|
|
<li><a href="#rtl-synthesis" class="doc-link">RTL Synthesis</a></li>
|
|
</ul>
|
|
|
|
<h3>API</h3>
|
|
<ul>
|
|
<li><a href="#api-reference" class="doc-link">API Reference</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="doc-content">
|
|
<div id="doc-loading">Select a document from the sidebar to view its contents.</div>
|
|
<div id="doc-body"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="footer">
|
|
<p>ReviveSparc is released under the BSD 2-Clause License.</p>
|
|
</div>
|
|
|
|
<script type="text/plain" id="doc-getting-started">
|
|
# Getting Started with ReviveSparc
|
|
|
|
This guide will walk you through building ReviveSparc from source and running your first SPARC program.
|
|
|
|
## Prerequisites
|
|
|
|
- **Linux** (x86_64 or aarch64) or **macOS** (Intel or Apple Silicon)
|
|
- **GCC** or **Clang** (C11 support required)
|
|
- **Make** (3.81 or later)
|
|
- **CMake** (3.20 or later)
|
|
- **Git**
|
|
|
|
Optional but recommended:
|
|
- `gcc-sparc-linux-gnu` for cross-compiling SPARC Linux programs
|
|
- `qemu-system-sparc64` for comparison testing
|
|
|
|
## Building from Source
|
|
|
|
Clone the repository:
|
|
|
|
```bash
|
|
git clone https://github.com/revivesparc/revivesparc.git
|
|
cd revivesparc
|
|
```
|
|
|
|
Build the emulator:
|
|
|
|
```bash
|
|
make
|
|
```
|
|
|
|
The resulting binary is `sparc-emu` in the project root directory.
|
|
|
|
### Build Options
|
|
|
|
| Option | Description | Default |
|
|
|--------|-------------|---------|
|
|
| `DEBUG=1` | Enable debug symbols and verbose logging | off |
|
|
| `OPT=0` | Disable optimizations | off |
|
|
| `TRACE=1` | Enable instruction tracing | off |
|
|
| `CC=clang` | Use Clang instead of GCC | gcc |
|
|
|
|
Example with debug enabled:
|
|
|
|
```bash
|
|
make DEBUG=1
|
|
```
|
|
|
|
## Running the Test Suite
|
|
|
|
```bash
|
|
make test
|
|
```
|
|
|
|
This runs the ISA verification suite, which tests every implemented instruction against known-good results.
|
|
|
|
## Your First SPARC Program
|
|
|
|
Create a file `hello.S` with the following SPARC assembly:
|
|
|
|
```asm
|
|
.section ".text"
|
|
.global _start
|
|
|
|
_start:
|
|
save %sp, -96, %sp
|
|
mov 1, %g1 ! SYS_write
|
|
mov 1, %o0 ! fd = stdout
|
|
sethi %hi(msg), %o1
|
|
or %o1, %lo(msg), %o1
|
|
mov 13, %o2 ! length
|
|
ta 0x6d ! trap to kernel
|
|
clr %o0 ! status = 0
|
|
mov 1, %g1 ! SYS_exit
|
|
ta 0x6d
|
|
|
|
.section ".data"
|
|
msg:
|
|
.asciz "Hello, SPARC!\n"
|
|
```
|
|
|
|
Assemble and link using the SPARC cross-toolchain:
|
|
|
|
```bash
|
|
sparc-linux-as hello.S -o hello.o
|
|
sparc-linux-ld hello.o -o hello
|
|
```
|
|
|
|
Run it under ReviveSparc:
|
|
|
|
```bash
|
|
./sparc-emu hello
|
|
```
|
|
|
|
You should see:
|
|
|
|
```
|
|
Hello, SPARC!
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
- Read the [Build Guide](build-guide.md) for advanced build configurations
|
|
- Explore the [ISA Reference](isa-reference.md) for instruction set details
|
|
- Check the [FAQ](faq.md) for common questions
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-build-guide">
|
|
# Build Guide
|
|
|
|
Detailed build instructions for ReviveSparc across different platforms and configurations.
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
revivesparc/
|
|
emu/ -- Functional instruction-set simulator (C)
|
|
rtl/ -- Verilog RTL for synthesis
|
|
soft/ -- Firmware and boot ROM code
|
|
tests/ -- ISA verification test suite
|
|
tools/ -- Helper scripts and utilities
|
|
docs/ -- Additional documentation
|
|
Makefile -- Top-level build file
|
|
CMakeLists.txt -- CMake build configuration
|
|
```
|
|
|
|
## Build System
|
|
|
|
ReviveSparc supports two build systems: **Make** (simple) and **CMake** (advanced).
|
|
|
|
### Make (Default)
|
|
|
|
```bash
|
|
make
|
|
```
|
|
|
|
### CMake
|
|
|
|
```bash
|
|
mkdir build && cd build
|
|
cmake ..
|
|
make -j$(nproc)
|
|
```
|
|
|
|
CMake offers more granular control:
|
|
|
|
```bash
|
|
cmake .. -DCMAKE_BUILD_TYPE=Debug -DENABLE_TRACE=ON
|
|
```
|
|
|
|
## Platform-Specific Notes
|
|
|
|
### Linux (x86_64)
|
|
|
|
Standard build with GCC:
|
|
|
|
```bash
|
|
sudo apt install build-essential cmake git
|
|
git clone https://github.com/revivesparc/revivesparc.git
|
|
cd revivesparc
|
|
make
|
|
```
|
|
|
|
### Linux (aarch64)
|
|
|
|
```bash
|
|
sudo apt install build-essential cmake git
|
|
make
|
|
```
|
|
|
|
No additional steps required.
|
|
|
|
### macOS (Apple Silicon)
|
|
|
|
Install dependencies via Homebrew:
|
|
|
|
```bash
|
|
brew install cmake make gcc
|
|
make CC=gcc-14
|
|
```
|
|
|
|
### macOS (Intel)
|
|
|
|
```bash
|
|
brew install cmake make
|
|
make
|
|
```
|
|
|
|
## Cross-Compilation
|
|
|
|
To build for a different target architecture:
|
|
|
|
```bash
|
|
make CROSS=aarch64-linux-gnu-
|
|
```
|
|
|
|
This is useful for embedded ReviveSparc deployments.
|
|
|
|
## Building the RTL
|
|
|
|
The Verilog RTL requires Verilator or Icarus Verilog for simulation:
|
|
|
|
```bash
|
|
make rtl
|
|
```
|
|
|
|
For synthesis, see the [RTL Synthesis Guide](rtl-synthesis.md).
|
|
|
|
## Building the Toolchain
|
|
|
|
ReviveSparc includes scripts to build a complete SPARC cross-toolchain:
|
|
|
|
```bash
|
|
cd tools
|
|
./build-toolchain.sh
|
|
```
|
|
|
|
This builds `sparc-elf-gcc`, `sparc-linux-gcc`, and associated binutils. The toolchain is installed to `tools/toolchain/`.
|
|
|
|
## Common Build Issues
|
|
|
|
### "No such file or directory" for standard headers
|
|
|
|
Install libc development headers:
|
|
|
|
```bash
|
|
# Debian/Ubuntu
|
|
sudo apt install libc6-dev
|
|
|
|
# Fedora
|
|
sudo dnf install glibc-devel
|
|
|
|
# macOS
|
|
# Headers are included with Xcode Command Line Tools
|
|
```
|
|
|
|
### "cc1: error: unrecognized command-line option"
|
|
|
|
You may be using an older GCC. ReviveSparc requires GCC 8+ or Clang 10+.
|
|
|
|
### "undefined reference to `clock_gettime'"
|
|
|
|
Link with librt on older glibc versions:
|
|
|
|
```bash
|
|
make LDFLAGS=-lrt
|
|
```
|
|
|
|
## Cleaning the Build
|
|
|
|
```bash
|
|
make clean # Remove build artifacts
|
|
make distclean # Also remove generated files
|
|
```
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-faq">
|
|
# Frequently Asked Questions
|
|
|
|
## General
|
|
|
|
### What is ReviveSparc?
|
|
|
|
ReviveSparc is a clean-room reimplementation of the OpenSPARC ISA (instruction set architecture). It aims to provide a fully open-source, legally unencumbered implementation of the SPARC V9 architecture that can run operating systems and software.
|
|
|
|
### Is this affiliated with Oracle?
|
|
|
|
No. ReviveSparc is an independent open-source project. OpenSPARC and SPARC are trademarks of Oracle Corporation. We are not affiliated with or endorsed by Oracle.
|
|
|
|
### Why SPARC? Isn't it dead?
|
|
|
|
SPARC is still used in mission-critical systems, particularly in aerospace, defense, and high-reliability computing. The Fujitsu SPARC64 processors power Japan's Fugaku supercomputer. The architecture is elegant and well-documented, making it ideal for educational use. ReviveSparc aims to preserve the architecture for future generations.
|
|
|
|
## Technical
|
|
|
|
### What is the "clean room" process?
|
|
|
|
Developers implementing ReviveSparc have **no access** to the original OpenSPARC source code. We work exclusively from publicly available specification documents:
|
|
- SPARC Architecture Manual Version 9
|
|
- UltraSPARC T1/T2 Supplements
|
|
- VIS Instruction Set Manual
|
|
|
|
This ensures the code is entirely original and free from any AT&T licensing concerns that affected the original OpenSPARC codebase.
|
|
|
|
### What operating systems can run?
|
|
|
|
- **Linux** (6.x series, full support)
|
|
- **NetBSD** (10.x, full support)
|
|
- **OpenBSD** (7.x, in progress)
|
|
- **Bare-metal programs** (any ELF binary for SPARC V9)
|
|
|
|
### How fast is the emulator?
|
|
|
|
On a modern x86_64 system:
|
|
- Single-core, JIT disabled: ~50 MIPS
|
|
- Single-core, JIT enabled: ~200 MIPS
|
|
- 8-core, JIT enabled: ~800 MIPS aggregate
|
|
|
|
Performance is sufficient to boot Linux in a few seconds.
|
|
|
|
### Can I synthesize the RTL on an FPGA?
|
|
|
|
Yes. The Verilog RTL has been tested on:
|
|
- Xilinx Virtex-7 (XC7VX485T) — 4 cores at 50 MHz
|
|
- Xilinx Kintex-7 (XC7K325T) — 2 cores at 75 MHz
|
|
- Intel Arria 10 — 4 cores at 100 MHz
|
|
|
|
See the [RTL Synthesis Guide](rtl-synthesis.md) for details.
|
|
|
|
## Project
|
|
|
|
### How can I contribute?
|
|
|
|
See the [Community page](../community.html) for details. We welcome code contributions, documentation, testing, and hardware verification.
|
|
|
|
### What license is used?
|
|
|
|
BSD 2-Clause License. This permits both open-source and proprietary use, with minimal restrictions.
|
|
|
|
### Does ReviveSparc include any AT&T code?
|
|
|
|
No. ReviveSparc is a complete from-scratch reimplementation. Every line of code is original and written solely from the architecture specification.
|
|
|
|
### Are there plans for SPARC V8 (32-bit) support?
|
|
|
|
The emulator includes a SPARC V8 compatibility mode that handles 32-bit code. Pure 32-bit SPARC V8 is not a primary target, but the majority of V8 instructions are supported through the V9 backward compatibility features.
|
|
|
|
### Can I run Solaris?
|
|
|
|
Solaris 10 and Solaris 11 for SPARC are not currently supported. The primary targets are open-source operating systems. If you'd like to contribute Solaris support, please reach out on the mailing list.
|
|
|
|
### Why not just use QEMU's SPARC target?
|
|
|
|
QEMU's SPARC target is excellent for running SPARC binaries, but it is a functional emulator with less emphasis on:
|
|
- Cycle-accurate pipeline modeling
|
|
- Hardware synthesis targets
|
|
- Educational clarity
|
|
|
|
ReviveSparc complements QEMU by providing a reference implementation suitable for hardware design and teaching.
|
|
|
|
## Build Issues
|
|
|
|
### `make` fails with "undefined reference"
|
|
|
|
Ensure you have all dependencies installed. See the [Build Guide](build-guide.md) for your platform.
|
|
|
|
### The emulator crashes on startup
|
|
|
|
Run with debug output enabled:
|
|
|
|
```bash
|
|
./sparc-emu -d -v kernel.bin
|
|
```
|
|
|
|
This will show detailed trace information. File a bug report with the output.
|
|
|
|
### Linux kernel hangs during boot
|
|
|
|
Common causes:
|
|
- Missing or incorrect device tree blob (use the DTB from `revivesparc.dtb`)
|
|
- Incorrect kernel command-line parameters
|
|
- Kernel built without ReviveSparc platform support
|
|
|
|
Try booting with `-append "earlyprintk debug"` to see kernel messages.
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-isa-reference">
|
|
# SPARC V9 ISA Reference
|
|
|
|
Reference documentation for the SPARC V9 instruction set as implemented in ReviveSparc.
|
|
|
|
## Overview
|
|
|
|
The SPARC V9 architecture is a 64-bit RISC ISA developed by Sun Microsystems and standardized by SPARC International. ReviveSparc implements the full SPARC V9 specification, including the VIS (Visual Instruction Set) extensions.
|
|
|
|
### Key Features
|
|
|
|
- 64-bit integer and floating-point registers
|
|
- 32 general-purpose registers (register windowed)
|
|
- 32 floating-point registers (quad-precision capable)
|
|
- Delayed branching with annulment
|
|
- Register windowing with 8 global + up to 32 windowed registers
|
|
- Precise exceptions and multiple trap levels
|
|
|
|
## Instruction Set Categories
|
|
|
|
### Integer Instructions
|
|
|
|
```
|
|
ADD Add ADDcc Add and modify CC
|
|
AND And ANDcc And and modify CC
|
|
OR Or ORcc Or and modify CC
|
|
XOR Exclusive Or XORcc Exclusive Or and modify CC
|
|
SUB Subtract SUBcc Subtract and modify CC
|
|
MULX Multiply Extended UDIVX Unsigned Divide Extended
|
|
SDIVX Signed Divide Extended
|
|
SLL Shift Left Logical SRL Shift Right Logical
|
|
SRA Shift Right Arithmetic
|
|
```
|
|
|
|
### Load/Store Instructions
|
|
|
|
```
|
|
LDUB Load Unsigned Byte
|
|
LDSB Load Signed Byte
|
|
LDUH Load Unsigned Halfword
|
|
LDSH Load Signed Halfword
|
|
LDW Load Word
|
|
LDX Load Doubleword
|
|
STB Store Byte
|
|
STH Store Halfword
|
|
STW Store Word
|
|
STX Store Doubleword
|
|
LDF Load Floating-point
|
|
LDDF Load Double Floating-point
|
|
STF Store Floating-point
|
|
STDF Store Double Floating-point
|
|
```
|
|
|
|
### Branch Instructions
|
|
|
|
```
|
|
Bcc Branch on Condition
|
|
BPcc Branch on Condition (Predicted)
|
|
BPr Branch on Register
|
|
CALL Call and Link
|
|
RETT Return from Trap
|
|
JMPL Jump and Link
|
|
RETURN Return from Subroutine
|
|
```
|
|
|
|
### Floating-Point Instructions
|
|
|
|
```
|
|
FADDs FP Add (single)
|
|
FADDd FP Add (double)
|
|
FSUBs FP Subtract (single)
|
|
FSUBd FP Subtract (double)
|
|
FMULs FP Multiply (single)
|
|
FMULd FP Multiply (double)
|
|
FDIVs FP Divide (single)
|
|
FDIVd FP Divide (double)
|
|
FSQRTs FP Square Root (single)
|
|
FSQRTd FP Square Root (double)
|
|
F CMPs FP Compare (single)
|
|
F CMPd FP Compare (double)
|
|
```
|
|
|
|
### VIS Instructions
|
|
|
|
```
|
|
FPACK16 Pack 16-bit
|
|
FPACK32 Pack 32-bit
|
|
FALIGNDATA Align Data
|
|
FEXPAND Expand
|
|
FMUL8x16 Multiply 8-bit by 16-bit
|
|
FMUL8x16AU Multiply 8-bit by 16-bit (unsigned)
|
|
FMUL8x16AL Multiply 8-bit by 16-bit (unsigned)
|
|
FMUL8SUx16 Multiply 8-bit Signed by 16-bit Unsigned
|
|
FMUL8ULx16 Multiply 8-bit Unsigned by 16-bit Unsigned
|
|
FMULD8SUx16 Multiply Double 8-bit Signed by 16-bit Unsigned
|
|
FMULD8ULx16 Multiply Double 8-bit Unsigned by 16-bit Unsigned
|
|
```
|
|
|
|
## Register Windows
|
|
|
|
SPARC V9 uses register windows to optimize function call performance:
|
|
|
|
- **8 global registers** (%g0 through %g7, where %g0 is always zero)
|
|
- **Up to 32 register windows**, each containing 16 registers
|
|
- Each window provides: 8 incoming (%i0-%i7), 8 local (%l0-%l7), 8 outgoing (%o0-%o7) — with overlap between adjacent windows
|
|
- The number of windows is implementation-dependent
|
|
|
|
## Privileged Registers
|
|
|
|
| Register | Description |
|
|
|----------|-------------|
|
|
| TPC | Trap PC (1-4) |
|
|
| TNPC | Trap Next PC (1-4) |
|
|
| TSTATE | Trap State (1-4) |
|
|
| TT | Trap Type (1-4) |
|
|
| TBA | Trap Base Address |
|
|
| PSTATE | Processor State |
|
|
| TL | Trap Level |
|
|
| PIL | Processor Interrupt Level |
|
|
| CWP | Current Window Pointer |
|
|
| CANSAVE | Cleanable Windows |
|
|
| CANRESTORE | Restorable Windows |
|
|
|
|
## Trap Types
|
|
|
|
| TT Value | Trap Name | Description |
|
|
|----------|-----------|-------------|
|
|
| 0x01 | instruction_access_exception | Memory access fault |
|
|
| 0x03 | instruction_access_error | Hardware error |
|
|
| 0x04 | illegal_instruction | Unimplemented instruction |
|
|
| 0x05 | privileged_operation | Trap in user mode |
|
|
| 0x06 | fp_disabled | FPU not enabled |
|
|
| 0x08 | clean_window | Register window spill needed |
|
|
| 0x09 | division_by_zero | Integer divide by zero |
|
|
| 0x20-0x2f | interrupt_vector | External interrupts |
|
|
| 0x60-0x7f | software_trap | `ta` instruction traps |
|
|
| 0x80 | data_access_exception | Data memory access fault |
|
|
| 0x82 | data_access_error | Data memory hardware error |
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-cmt">
|
|
# Chip Multi-Threading (CMT)
|
|
|
|
ReviveSparc implements the UltraSPARC T1/T2 chip multi-threading architecture, allowing multiple threads to execute concurrently on each core.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Core 0 Core 1 Core 2 Core 3
|
|
+--------+ +--------+ +--------+ +--------+
|
|
| T0 T1 | | T0 T1 | | T0 T1 | | T0 T1 |
|
|
| T2 T3 | | T2 T3 | | T2 T3 | | T2 T3 |
|
|
+--------+ +--------+ +--------+ +--------+
|
|
| | | |
|
|
+--------------+--------------+--------------+
|
|
|
|
|
+-----------+
|
|
| L2 Cache |
|
|
+-----------+
|
|
```
|
|
|
|
Each core supports up to **4 hardware threads** with fine-grained interleaving. The pipeline switches between threads every cycle, hiding memory latency and maximizing throughput.
|
|
|
|
## Thread Scheduling
|
|
|
|
Threads are scheduled using a round-robin policy with two modes:
|
|
|
|
### Fine-Grained (Default)
|
|
|
|
The pipeline switches to a different thread each cycle. If the selected thread is stalled (cache miss, long latency operation), the pipeline switches to the next ready thread.
|
|
|
|
```c
|
|
// Pseudocode for thread selection
|
|
while (true) {
|
|
for (int i = 0; i < NUM_THREADS; i++) {
|
|
thread = (current_thread + i) % NUM_THREADS;
|
|
if (thread_is_ready(thread)) {
|
|
execute(thread);
|
|
break;
|
|
}
|
|
}
|
|
current_thread = (current_thread + 1) % NUM_THREADS;
|
|
}
|
|
```
|
|
|
|
### Coarse-Grained
|
|
|
|
Each thread runs for a fixed quantum (configurable, default 64 cycles) before yielding the pipeline. Useful for workloads with good instruction-level parallelism.
|
|
|
|
## Thread State
|
|
|
|
Each thread has its own fully replicated architectural state:
|
|
|
|
- **Register window** (16 registers, with window pointer)
|
|
- **PC and NPC** (program counters)
|
|
- **PSTATE** (processor state register)
|
|
- **TL** (trap level, up to 4)
|
|
- **Interrupt state** (pending interrupts, PIL)
|
|
|
|
## Memory Model
|
|
|
|
The T1/T2 memory model is **Total Store Order (TSO)** with per-thread write buffers. ReviveSparc implements:
|
|
|
|
- **TSO** by default (SPARC V9 default)
|
|
- **Partial Store Order (PSO)** as an alternative
|
|
- **Relaxed Memory Order (RMO)** for maximum performance
|
|
|
|
### Memory Barrier Instructions
|
|
|
|
| Instruction | Description |
|
|
|-------------|-------------|
|
|
| `MEMBAR #Sync` | Full memory barrier |
|
|
| `MEMBAR #StoreLoad` | Store before Load ordering |
|
|
| `MEMBAR #StoreStore` | Store before Store ordering |
|
|
| `MEMBAR #LoadLoad` | Load before Load ordering |
|
|
| `MEMBAR #LoadStore` | Load before Store ordering |
|
|
| `MEMBAR #Lookaside` | Invalidate lookaside buffers |
|
|
|
|
## Configuration
|
|
|
|
CMT parameters are configured at core initialization:
|
|
|
|
```c
|
|
sparc_core_config_t config = {
|
|
.num_threads = 4,
|
|
.sched_mode = SCHED_FINE_GRAINED,
|
|
.pipeline_mode = TSO,
|
|
.quantum = 64 // coarse-grained quantum
|
|
};
|
|
sparc_core_t *core = sparc_core_new(&config);
|
|
```
|
|
|
|
Or via command line:
|
|
|
|
```bash
|
|
./sparc-emu -cores 4 -threads 4 -sched fine kernel.bin
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
- Fine-grained threading works best with high cache-miss rates (database, web serving)
|
|
- Coarse-grained threading works best with compute-intensive workloads
|
|
- The optimal thread count depends on the L2 cache size and memory latency
|
|
- Monitor thread utilization with the `-stats` flag:
|
|
```bash
|
|
./sparc-emu -stats kernel.bin
|
|
```
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-memory-model">
|
|
# Memory Model
|
|
|
|
ReviveSparc implements the SPARC V9 memory architecture, including the cache hierarchy, MMU, and memory ordering models.
|
|
|
|
## Cache Hierarchy
|
|
|
|
```
|
|
CLIENT (Core)
|
|
|
|
|
+-- L1 I-Cache (16 KB, 4-way, 32-byte line)
|
|
+-- L1 D-Cache (16 KB, 4-way, 32-byte line)
|
|
|
|
|
+-- L2 Cache (shared, 512 KB - 4 MB, 8-way)
|
|
|
|
|
+-- Main Memory (DDR4, configurable)
|
|
```
|
|
|
|
### L1 Caches
|
|
|
|
- **Capacity**: 16 KB each for instructions and data
|
|
- **Associativity**: 4-way set associative
|
|
- **Line size**: 32 bytes
|
|
- **Latency**: 2 cycles (hit), 1 cycle (tag check)
|
|
- **Policy**: Write-back (D-cache), read-only (I-cache)
|
|
- **Coherency**: MOESI protocol between cores
|
|
|
|
### L2 Cache
|
|
|
|
- **Capacity**: Configurable (512 KB to 4 MB)
|
|
- **Associativity**: 8-way set associative
|
|
- **Line size**: 64 bytes
|
|
- **Latency**: 12 cycles (hit)
|
|
- **Policy**: Write-back, write-allocate
|
|
- **Coherency**: Inclusive of L1 (snoop filter)
|
|
|
|
## MMU (Memory Management Unit)
|
|
|
|
The SPARC Reference MMU provides virtual-to-physical address translation.
|
|
|
|
### Address Spaces
|
|
|
|
| Mode | Virtual Address Width | Physical Address Width |
|
|
|------|----------------------|----------------------|
|
|
| 32-bit (V8 compat) | 32 bits | 40 bits |
|
|
| 64-bit (V9) | 44 bits | 44 bits |
|
|
|
|
### TLB Structure
|
|
|
|
```
|
|
ITLB (64 entries)
|
|
Fully associative
|
|
Supports 8 KB, 64 KB, 256 KB, 4 MB pages
|
|
|
|
DTLB (64 entries)
|
|
Fully associative
|
|
Supports same page sizes as ITLB
|
|
```
|
|
|
|
### Translation Process
|
|
|
|
```
|
|
Virtual Address (44 bits)
|
|
|
|
|
+-- VPN[0:2] --> TLB Lookup (parallel)
|
|
| |
|
|
| +-- Hit? --> PPN + Offset --> Physical Address
|
|
| +-- Miss --> TLB Miss Trap (TLB miss handler)
|
|
|
|
|
+-- Offset --> Direct to physical address
|
|
```
|
|
|
|
### TSB (Translation Storage Buffer)
|
|
|
|
The TSB is a software-managed cache of page table entries. On a TLB miss, the trap handler searches the TSB before walking the full page table.
|
|
|
|
## Memory Ordering
|
|
|
|
ReviveSparc supports three memory models:
|
|
|
|
### Total Store Order (TSO)
|
|
|
|
The default SPARC V9 model:
|
|
|
|
- Stores appear in program order to all observers
|
|
- Loads may pass stores (store buffer forwarding)
|
|
- Atomic operations provide full ordering
|
|
|
|
### Partial Store Order (PSO)
|
|
|
|
Relaxed store ordering:
|
|
|
|
- Stores to different locations may be reordered
|
|
- Stores to the same location appear in order
|
|
- MEMBAR is required for ordering constraints
|
|
|
|
### Relaxed Memory Order (RMO)
|
|
|
|
Maximum relaxation:
|
|
|
|
- Loads and stores may be reordered freely
|
|
- All ordering is explicit via MEMBAR instructions
|
|
- Highest performance on multi-core configurations
|
|
|
|
## Atomic Operations
|
|
|
|
| Instruction | Description |
|
|
|-------------|-------------|
|
|
| `CAS` | Compare and Swap (32-bit) |
|
|
| `CASX` | Compare and Swap (64-bit) |
|
|
| `SWAP` | Atomic swap |
|
|
| `LDSTUB` | Atomic load-and-store-byte |
|
|
| `CASA` | Compare and Swap (alternate space) |
|
|
| `CASXA` | Compare and Swap (alternate space, 64-bit) |
|
|
|
|
## Configuration
|
|
|
|
Memory parameters can be configured at startup:
|
|
|
|
```bash
|
|
./sparc-emu -l1i 16k -l1d 16k -l2 1m -mem tso kernel.bin
|
|
```
|
|
|
|
Or via the C API:
|
|
|
|
```c
|
|
sparc_mem_config_t mem = {
|
|
.l1i_size = 16 * 1024,
|
|
.l1d_size = 16 * 1024,
|
|
.l2_size = 1 * 1024 * 1024,
|
|
.memory_model = MEM_TSO,
|
|
.num_cores = 4
|
|
};
|
|
sparc_t *cpu = sparc_new_with_config(&mem);
|
|
```
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-linux-guide">
|
|
# Building Linux for ReviveSparc
|
|
|
|
This guide covers building and booting a Linux kernel on the ReviveSparc emulator.
|
|
|
|
## Supported Kernels
|
|
|
|
| Kernel Version | Status | Notes |
|
|
|----------------|--------|-------|
|
|
| 6.12+ | Full | All features working |
|
|
| 6.6 LTS | Full | Recommended for production |
|
|
| 6.1 LTS | Full | Older but stable |
|
|
| 5.15 LTS | Partial | No SMP support |
|
|
|
|
## Cross-Compilation Setup
|
|
|
|
Install a SPARC64 cross-compiler:
|
|
|
|
```bash
|
|
# Debian/Ubuntu
|
|
sudo apt install gcc-sparc64-linux-gnu
|
|
|
|
# Fedora
|
|
sudo dnf install cross-gcc-sparc64-linux-gnu
|
|
|
|
# Build from source (see toolchain guide)
|
|
./tools/build-toolchain.sh --target=sparc64-linux-gnu
|
|
```
|
|
|
|
## Building the Kernel
|
|
|
|
### Get the Source
|
|
|
|
```bash
|
|
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
|
cd linux
|
|
git checkout v6.12
|
|
```
|
|
|
|
### Apply ReviveSparc Patches
|
|
|
|
```bash
|
|
# From the ReviveSparc repository
|
|
./tools/apply-kernel-patches.sh /path/to/linux
|
|
```
|
|
|
|
### Configure
|
|
|
|
```bash
|
|
make ARCH=sparc64 CROSS_COMPILE=sparc64-linux-gnu- revivesparc_defconfig
|
|
```
|
|
|
|
Or customize:
|
|
|
|
```bash
|
|
make ARCH=sparc64 CROSS_COMPILE=sparc64-linux-gnu- menuconfig
|
|
```
|
|
|
|
### Build
|
|
|
|
```bash
|
|
make ARCH=sparc64 CROSS_COMPILE=sparc64-linux-gnu- -j$(nproc)
|
|
```
|
|
|
|
The kernel image is at `arch/sparc64/boot/image` and `vmlinux` (ELF).
|
|
|
|
## Building an Initramfs
|
|
|
|
Create a minimal root filesystem:
|
|
|
|
```bash
|
|
# Create a simple init script
|
|
cat > init << 'EOF'
|
|
#!/bin/busybox
|
|
/bin/busybox --install -s
|
|
mount -t proc proc /proc
|
|
mount -t sysfs sysfs /sys
|
|
echo "Welcome to ReviveSparc Linux!"
|
|
exec /bin/sh
|
|
EOF
|
|
|
|
# Create the initramfs
|
|
mkdir -p rootfs/{bin,proc,sys,dev,etc}
|
|
cp init rootfs/
|
|
cp /path/to/busybox rootfs/bin/
|
|
|
|
# Package it
|
|
cd rootfs
|
|
find . | cpio -H newc -o | gzip > ../initramfs.gz
|
|
```
|
|
|
|
## Booting
|
|
|
|
```bash
|
|
./sparc-emu \
|
|
-kernel vmlinux \
|
|
-initrd initramfs.gz \
|
|
-append "console=ttyS0,115200 root=/dev/ram rdinit=/init" \
|
|
-nographic
|
|
```
|
|
|
|
### Command-Line Options
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `-kernel` | Path to the kernel vmlinux |
|
|
| `-initrd` | Path to the initramfs image |
|
|
| `-append` | Kernel command line |
|
|
| `-nographic` | No graphical output (serial console) |
|
|
| `-m` | Memory size (e.g., `-m 512M`) |
|
|
| `-smp` | Number of cores (e.g., `-smp 4`) |
|
|
| `-net` | Network backend (e.g., `-net user`) |
|
|
|
|
### Booting with Device Tree
|
|
|
|
ReviveSparc provides a device tree blob (DTB) for the emulated platform:
|
|
|
|
```bash
|
|
./sparc-emu \
|
|
-kernel vmlinux \
|
|
-dtb revivesparc.dtb \
|
|
-initrd initramfs.gz \
|
|
-append "console=ttyS0,115200" \
|
|
-nographic
|
|
```
|
|
|
|
## Building for NetBSD
|
|
|
|
```bash
|
|
# Build a SPARC64 NetBSD kernel
|
|
cd /usr/src
|
|
./build.sh -m sparc64 -U kernel=GENERIC
|
|
|
|
# Run under ReviveSparc
|
|
./sparc-emu \
|
|
-kernel netbsd-sparc64 \
|
|
-append "console=com0" \
|
|
-nographic
|
|
```
|
|
|
|
## Building for OpenBSD
|
|
|
|
```bash
|
|
# Build a SPARC64 OpenBSD kernel
|
|
cd /usr/src
|
|
make -C sys/arch/sparc64/conf GENERIC
|
|
config GENERIC
|
|
cd ../compile/GENERIC
|
|
make
|
|
|
|
# Run under ReviveSparc
|
|
./sparc-emu \
|
|
-kernel bsd.sparc64 \
|
|
-nographic
|
|
```
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-rtl-synthesis">
|
|
# RTL Synthesis Guide
|
|
|
|
This guide covers synthesizing the ReviveSparc Verilog RTL for FPGA deployment.
|
|
|
|
## Overview
|
|
|
|
The ReviveSparc RTL implements a 6-stage, in-order, dual-issue SPARC V9 pipeline with chip multi-threading. It is written in synthesizable Verilog and targets Xilinx and Intel FPGAs.
|
|
|
|
## Pipeline Stages
|
|
|
|
```
|
|
Fetch --> Decode --> Execute --> Memory --> Writeback --> Commit
|
|
| | | | | |
|
|
v v v v v v
|
|
ICache Decode ALU/MUL D-Cache RegFile TLB/MMU
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
- **Verilator** 5.x (for simulation)
|
|
- **Vivado** 2024.x or **Quartus** 23.x (for synthesis)
|
|
- **Python** 3.10+ (for build scripts)
|
|
- **FuseSoC** (optional, for IP management)
|
|
|
|
## Building the RTL Simulation
|
|
|
|
```bash
|
|
make rtl
|
|
```
|
|
|
|
This compiles the RTL with Verilator and produces a simulation binary.
|
|
|
|
### Running RTL Tests
|
|
|
|
```bash
|
|
make rtl-test
|
|
```
|
|
|
|
This runs the complete RTL test suite, including unit tests for each pipeline stage and integration tests for the full core.
|
|
|
|
## FPGA Synthesis
|
|
|
|
### Xilinx Vivado
|
|
|
|
```bash
|
|
cd rtl/syn/vivado
|
|
vivado -mode batch -source synth.tcl
|
|
```
|
|
|
|
This generates a bitstream for the default target board.
|
|
|
|
### Target Boards
|
|
|
|
| Board | Speed | Resources Used | Status |
|
|
|-------|-------|----------------|--------|
|
|
| Xilinx VC707 (Virtex-7) | 50 MHz, 4 cores | 65% LUT, 48% BRAM | Verified |
|
|
| Xilinx KC705 (Kintex-7) | 75 MHz, 2 cores | 55% LUT, 35% BRAM | Verified |
|
|
| Xilinx Arty A7 (Artix-7) | 40 MHz, 1 core | 70% LUT, 60% BRAM | Verified |
|
|
| Intel Arria 10 GX | 100 MHz, 4 cores | 60% ALM, 40% M20K | Verified |
|
|
| Intel Cyclone V | 50 MHz, 2 cores | 72% ALM, 55% M20K | Beta |
|
|
|
|
### Configuration
|
|
|
|
RTL parameters are set in `rtl/config.vh`:
|
|
|
|
```verilog
|
|
`define NUM_CORES 4
|
|
`define THREADS_PER_CORE 4
|
|
`define L1I_SIZE 16384
|
|
`define L1D_SIZE 16384
|
|
`define L2_SIZE 1048576
|
|
`define PIPELINE_STAGES 6
|
|
```
|
|
|
|
## Running on FPGA
|
|
|
|
1. Program the FPGA with the generated bitstream
|
|
2. Connect a USB-UART cable (default: 115200 baud, 8N1)
|
|
3. Load a program via the boot ROM interface:
|
|
|
|
```bash
|
|
./tools/fpga-load.py /dev/ttyUSB0 kernel.bin
|
|
```
|
|
|
|
4. The core resets and begins execution. Output appears on the serial console.
|
|
|
|
## Boot ROM
|
|
|
|
The boot ROM loads a program from the UART interface into memory and starts execution at the entry point. The boot ROM firmware is in `soft/bootrom/` and is pre-synthesized into the bitstream.
|
|
|
|
## Debug Interface
|
|
|
|
The RTL includes a JTAG-like debug interface accessible via the emulator:
|
|
|
|
```bash
|
|
./sparc-emu --connect-fpga /dev/ttyUSB1
|
|
```
|
|
|
|
This connects the emulator's debugger to the FPGA-resident cores, allowing register inspection and breakpoint management.
|
|
|
|
## Performance Results
|
|
|
|
| Configuration | FPGA | Frequency | DMIPS |
|
|
|---------------|------|-----------|-------|
|
|
| 1 core, 4 threads | Artix-7 | 40 MHz | 45 |
|
|
| 2 cores, 4 threads | Kintex-7 | 75 MHz | 168 |
|
|
| 4 cores, 4 threads | Virtex-7 | 50 MHz | 320 |
|
|
| 4 cores, 4 threads | Arria 10 | 100 MHz | 720 |
|
|
|
|
## Contributing RTL Changes
|
|
|
|
1. Write a Verilog testbench in `rtl/tb/`
|
|
2. Verify with Verilator: `make rtl-test`
|
|
3. Ensure lint passes: `make rtl-lint`
|
|
4. Submit a pull request with simulation results
|
|
</script>
|
|
|
|
<script type="text/plain" id="doc-api-reference">
|
|
# API Reference
|
|
|
|
ReviveSparc provides a C API for embedding the SPARC emulator in other projects.
|
|
|
|
## Core API
|
|
|
|
### Initialization
|
|
|
|
```c
|
|
#include <revivesparc.h>
|
|
|
|
// Create a new SPARC CPU instance
|
|
sparc_t *sparc_new(sparc_isa_t isa);
|
|
```
|
|
|
|
Parameters:
|
|
- `isa`: `SPARC_V9` for 64-bit mode, `SPARC_V8` for 32-bit compatibility mode
|
|
|
|
Returns: Pointer to a new SPARC instance, or NULL on failure.
|
|
|
|
```c
|
|
// Create with custom configuration
|
|
sparc_t *sparc_new_with_config(const sparc_config_t *config);
|
|
```
|
|
|
|
```c
|
|
// Free a SPARC instance
|
|
void sparc_free(sparc_t *cpu);
|
|
```
|
|
|
|
### Loading Programs
|
|
|
|
```c
|
|
// Load an ELF file into memory
|
|
int sparc_load_elf(sparc_t *cpu, const char *path);
|
|
|
|
// Load a flat binary into memory at a specific address
|
|
int sparc_load_binary(sparc_t *cpu, const char *path, uint64_t addr);
|
|
|
|
// Load a file into memory at a specific offset
|
|
int sparc_load_file(sparc_t *cpu, const char *path, uint64_t addr);
|
|
```
|
|
|
|
All load functions return 0 on success, -1 on error.
|
|
|
|
### Execution Control
|
|
|
|
```c
|
|
// Reset the CPU to initial state
|
|
void sparc_reset(sparc_t *cpu);
|
|
|
|
// Run for a specified number of instructions
|
|
uint64_t sparc_run(sparc_t *cpu, uint64_t num_insts);
|
|
|
|
// Run until a breakpoint is hit
|
|
uint64_t sparc_run_until_break(sparc_t *cpu);
|
|
|
|
// Step a single instruction
|
|
int sparc_step(sparc_t *cpu);
|
|
|
|
// Stop execution (called from interrupt handler)
|
|
void sparc_stop(sparc_t *cpu);
|
|
```
|
|
|
|
Returns the actual number of instructions executed.
|
|
|
|
### Register Access
|
|
|
|
```c
|
|
// Read/write general-purpose registers
|
|
uint64_t sparc_get_gpr(sparc_t *cpu, int reg);
|
|
void sparc_set_gpr(sparc_t *cpu, int reg, uint64_t val);
|
|
|
|
// Read/write special registers
|
|
uint64_t sparc_get_pc(sparc_t *cpu);
|
|
void sparc_set_pc(sparc_t *cpu, uint64_t val);
|
|
|
|
uint64_t sparc_get_npc(sparc_t *cpu);
|
|
void sparc_set_npc(sparc_t *cpu, uint64_t val);
|
|
|
|
// Floating-point registers
|
|
double sparc_get_fpr(sparc_t *cpu, int reg);
|
|
void sparc_set_fpr(sparc_t *cpu, int reg, double val);
|
|
|
|
// Privileged registers
|
|
uint64_t sparc_get_priv(sparc_t *cpu, sparc_priv_reg_t reg);
|
|
void sparc_set_priv(sparc_t *cpu, sparc_priv_reg_t reg, uint64_t val);
|
|
```
|
|
|
|
### Memory Access
|
|
|
|
```c
|
|
// Direct memory access (bypasses MMU)
|
|
int sparc_mem_write(sparc_t *cpu, uint64_t addr, const void *buf, size_t len);
|
|
int sparc_mem_read(sparc_t *cpu, uint64_t addr, void *buf, size_t len);
|
|
|
|
// Virtual memory access (through MMU)
|
|
int sparc_virt_write(sparc_t *cpu, uint64_t addr, const void *buf, size_t len);
|
|
int sparc_virt_read(sparc_t *cpu, uint64_t addr, void *buf, size_t len);
|
|
```
|
|
|
|
Returns the number of bytes read/written, or -1 on error.
|
|
|
|
### Debugging
|
|
|
|
```c
|
|
// Set a breakpoint at a virtual address
|
|
int sparc_breakpoint_set(sparc_t *cpu, uint64_t addr);
|
|
|
|
// Clear a breakpoint
|
|
int sparc_breakpoint_clear(sparc_t *cpu, uint64_t addr);
|
|
|
|
// Get disassembly of an instruction
|
|
const char *sparc_disassemble(sparc_t *cpu, uint64_t addr);
|
|
|
|
// Set tracing level
|
|
void sparc_set_trace(sparc_t *cpu, int level);
|
|
```
|
|
|
|
## Configuration Structures
|
|
|
|
```c
|
|
typedef struct {
|
|
int num_cores; // Number of cores (1-8)
|
|
int threads_per_core; // Threads per core (1-4)
|
|
sparc_mem_t memory_model; // TSO, PSO, or RMO
|
|
sparc_sched_t sched_mode; // Fine or coarse-grained
|
|
uint64_t mem_size; // Main memory size in bytes
|
|
int l1i_size; // L1 I-cache size in bytes
|
|
int l1d_size; // L1 D-cache size in bytes
|
|
int l2_size; // L2 cache size in bytes
|
|
int num_windows; // Number of register windows (8-32)
|
|
} sparc_config_t;
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
Most functions return 0 on success and -1 on error. Detailed error information can be retrieved:
|
|
|
|
```c
|
|
// Get the last error message
|
|
const char *sparc_error(sparc_t *cpu);
|
|
|
|
// Get the last error code
|
|
int sparc_errno(sparc_t *cpu);
|
|
```
|
|
|
|
## Example: Embedded Emulator
|
|
|
|
```c
|
|
#include <stdio.h>
|
|
#include <revivesparc.h>
|
|
|
|
int main(int argc, char **argv) {
|
|
sparc_t *cpu = sparc_new(SPARC_V9);
|
|
if (!cpu) {
|
|
fprintf(stderr, "Failed to create CPU\n");
|
|
return 1;
|
|
}
|
|
|
|
sparc_config_t config = {
|
|
.num_cores = 1,
|
|
.mem_size = 256 * 1024 * 1024,
|
|
.memory_model = MEM_TSO
|
|
};
|
|
sparc_configure(cpu, &config);
|
|
|
|
if (sparc_load_elf(cpu, argv[1]) != 0) {
|
|
fprintf(stderr, "Failed to load ELF: %s\n", sparc_error(cpu));
|
|
return 1;
|
|
}
|
|
|
|
sparc_reset(cpu);
|
|
uint64_t insts = sparc_run(cpu, 1000000);
|
|
printf("Executed %lu instructions\n", insts);
|
|
printf("Final PC: 0x%lx\n", sparc_get_pc(cpu));
|
|
|
|
sparc_free(cpu);
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
Compile with:
|
|
|
|
```bash
|
|
cc -o myemu myemu.c -lrevivesparc
|
|
```
|
|
</script>
|
|
|
|
<script>
|
|
var docNames = [
|
|
"getting-started",
|
|
"build-guide",
|
|
"faq",
|
|
"isa-reference",
|
|
"cmt",
|
|
"memory-model",
|
|
"linux-guide",
|
|
"rtl-synthesis",
|
|
"api-reference"
|
|
];
|
|
|
|
function loadDoc(name) {
|
|
var el = document.getElementById("doc-body");
|
|
var loading = document.getElementById("doc-loading");
|
|
var links = document.querySelectorAll(".doc-link");
|
|
|
|
links.forEach(function (l) { l.classList.remove("active"); });
|
|
|
|
var activeLink = document.querySelector('.doc-link[href="#' + name + '"]');
|
|
if (activeLink) activeLink.classList.add("active");
|
|
|
|
var script = document.getElementById("doc-" + name);
|
|
if (!script) {
|
|
loading.style.display = "none";
|
|
el.innerHTML = "<h2>Document not found</h2><p>The document <strong>" + name + "</strong> does not exist.</p>";
|
|
return;
|
|
}
|
|
|
|
loading.style.display = "none";
|
|
el.innerHTML = marked.parse(script.textContent);
|
|
|
|
el.querySelectorAll("a").forEach(function (a) {
|
|
var href = a.getAttribute("href");
|
|
if (href && !href.startsWith("http") && !href.startsWith("#")) {
|
|
var match = href.match(/^(.+)\.md(#.*)?$/);
|
|
if (match && docNames.indexOf(match[1]) !== -1) {
|
|
a.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
loadDoc(match[1]);
|
|
window.location.hash = match[1];
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function hashChanged() {
|
|
var hash = window.location.hash.replace("#", "");
|
|
if (hash && docNames.indexOf(hash) !== -1) {
|
|
loadDoc(hash);
|
|
} else {
|
|
document.getElementById("doc-loading").style.display = "none";
|
|
document.getElementById("doc-body").innerHTML =
|
|
"<h2>Welcome to the ReviveSparc Documentation</h2>" +
|
|
"<p>Select a topic from the sidebar to get started.</p>" +
|
|
"<ul>" +
|
|
"<li><a href='#getting-started'>Getting Started Guide</a> — Build and run your first SPARC program</li>" +
|
|
"<li><a href='#build-guide'>Build Guide</a> — Detailed build instructions</li>" +
|
|
"<li><a href='#isa-reference'>ISA Reference</a> — SPARC V9 instruction set</li>" +
|
|
"<li><a href='#linux-guide'>Linux Guide</a> — Building Linux for ReviveSparc</li>" +
|
|
"<li><a href='#faq'>FAQ</a> — Frequently asked questions</li>" +
|
|
"</ul>";
|
|
document.querySelectorAll(".doc-link").forEach(function (l) { l.classList.remove("active"); });
|
|
}
|
|
}
|
|
|
|
document.querySelectorAll(".doc-link").forEach(function (link) {
|
|
link.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
var name = link.getAttribute("href").replace("#", "");
|
|
window.location.hash = name;
|
|
});
|
|
});
|
|
|
|
window.addEventListener("hashchange", hashChanged);
|
|
hashChanged();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|