Bluespec Verilog PowerISA Core.
Azurite is named for the vivid blue copper mineral found in Arizona's copper country. The name ties the project to the repo owner's home state, nods to Bluespec through its deep blue color, and points toward copper itself: the metal of conductors, traces, and electrical power. Like the mineral, the core is meant to reward close inspection: compact, structured, and transparent enough that behavior can be traced from ISA intent through RTL and verification.
This project takes inspiration from the Bluespec Piccolo / Flute projects. It is modeled and structured similarly to shorten bring-up of the initial core and verification flow.
Azurite is in early bring-up. The main remaining architectural bring-up items are a proper instruction prefetcher and complete architectural interrupt/exception entry and return sequencing, including external interrupt delivery, saved-state updates, vector dispatch, and return-to-program flow. The current repository contains:
- Bluespec SystemVerilog source for the core shell, CPU stages, register bank, execution units, memory stage, cache shims, AXI4 fabric types, and PowerISA instruction declarations under
src_Core/. - A cocotb/Verilator testbench under
src_Testbench/. - PowerPC bring-up programs and payload artifacts under
programs/bringup/. - PowerISA reference links, instruction implementation notes, architecture notes, implementation checklists, and extracted Appendix G CSV files under
docs/PowerPC/. - A Docker-based build environment with Bluespec
bsc, Verilator, cocotb, PowerPC cross compilers, and QEMU. - QEMU oracle tooling under
tools/qemu_oracle/for C/C++ source compilation, randomized instruction generation, signature checking, and retired-instruction trace comparison against RTL.
.
├── src_Core/
│ ├── Core/ # mkCore top-level and external interface
│ ├── CPU/ # PC, IF, ID, EX, MEM, RB, IC/DC, and pipeline modules
│ ├── ISA/ # PowerISA type/form/opcode declarations
│ ├── Fabrics/ # AXI4 type and fabric definitions
│ └── BSV_Additional_Libs/ # local Bluespec utility modules
├── src_Testbench/ # cocotb testbench and simulation Makefile
├── programs/ # bare-metal and QEMU bring-up programs
├── docs/PowerPC/ # ISA references and decoded instruction tables
├── docker/entrypoint.sh # container startup helper
├── Dockerfile # full toolchain image
└── Makefile # RTL generation and simulation entry points
The recommended starting point is the Docker image because the native dependency set is large.
You need:
- Docker with BuildKit support.
- GitHub SSH access if you build the current
Dockerfileunchanged, because it clones this private repo during image build. - A working SSH agent with a GitHub key loaded.
The Docker image installs/builds:
- Ubuntu 22.04 base tools.
- Bluespec compiler
bscfromB-Lang-org/bsc, defaultBSC_REF=2025.01.1. - Verilator from source, default
VERILATOR_TAG=v5.036. - Python packages:
pytest,pytest-xdist,cocotb,cocotb-test,cocotbext-axi,pyelftools. - PowerPC cross toolchains and binutils:
powerpc-linux-gnu-*powerpc64-linux-gnu-*powerpc64le-linux-gnu-*
- QEMU 10.1.0 with PowerPC softmmu/user targets, including
qemu-ppc64andqemu-ppc64lefor the oracle flow. - GTKWave for waveform viewing.
From the repository root:
$env:DOCKER_BUILDKIT = "1"
ssh-add -l
ssh-add $env:USERPROFILE\.ssh\id_ed25519
docker build --ssh default -t azurite-build .On Linux/macOS:
export DOCKER_BUILDKIT=1
ssh-add -l || ssh-add ~/.ssh/id_ed25519
docker build --ssh default -t azurite-build .Note: the current
Dockerfileclonesgit@github.com:mgjaggers/Azurite.gitinto/workspace/repo/Azuriteduring the image build. If you want faster local iteration, consider changing the Dockerfile later to install only the toolchain and then bind-mount this checkout into the container.
docker run --rm -it azurite-buildFor local iteration against your working tree instead of the copy baked into the image:
docker run --rm -it \
-v "$PWD":/workspace/repo/Azurite \
-w /workspace/repo/Azurite \
azurite-buildInside the container, from the repository root:
makeThis compiles src_Core/Core/Core.bsv with top module mkCore and writes the
selected Verilog variant to:
build/rtl/mkCore.v
build/rtl/mkCore.v is the active generated core. Each build command below
overwrites that file with the selected configuration. Bluespec intermediate
artifacts are kept in variant-specific directories under build/bld/, and
build/rtl/core_params.txt records the compile-time defines used for the
current mkCore.v.
| Goal | Command |
|---|---|
| Default core: big-endian, passthrough cache shims | make |
| Explicit big-endian passthrough core | make CORE_ENDIAN=be |
| Little-endian passthrough core | make CORE_ENDIAN=le |
| Big-endian core with concrete L1 I-cache and D-cache | make CORE_ENDIAN=be ENABLE_L1_CACHES=1 |
| Little-endian core with concrete L1 I-cache and D-cache | make CORE_ENDIAN=le ENABLE_L1_CACHES=1 |
| Big-endian core with only concrete I-cache | make CORE_ENDIAN=be ENABLE_ICACHE=1 |
| Big-endian core with only concrete D-cache | make CORE_ENDIAN=be ENABLE_DCACHE=1 |
The same switches also work with the explicit RTL target:
make CORE_ENDIAN=le ENABLE_L1_CACHES=1 build/rtl/mkCore.v| Make variable | Default | Effect |
|---|---|---|
CORE_ENDIAN |
be |
Selects core memory byte order. Use be/big/big-endian or le/little/little-endian. |
ENABLE_L1_CACHES |
0 |
Enables both concrete L1 caches. |
ENABLE_ICACHE |
0 |
Enables only the concrete instruction cache unless ENABLE_L1_CACHES=1. |
ENABLE_DCACHE |
0 |
Enables only the concrete data cache unless ENABLE_L1_CACHES=1. |
These switches map to the following Bluespec defines:
FABRIC64 default core/fabric build
AZURITE_CORE_LITTLE_ENDIAN selected by CORE_ENDIAN=le
AZURITE_ENABLE_ICACHE selected by ENABLE_ICACHE=1 or ENABLE_L1_CACHES=1
AZURITE_ENABLE_DCACHE selected by ENABLE_DCACHE=1 or ENABLE_L1_CACHES=1
The instruction and data memory paths always pass through cache-facing shim interfaces. With the default settings those shims are AXI passthrough modules. With cache defines enabled, the concrete caches are 4 KiB, 2-way set associative, 32-byte line caches with round-robin replacement. The I-cache is read-allocate. The D-cache is read-allocate, write-through, and write-allocate; a D-cache store miss refills the line, merges the store into the cached copy, installs the line, then performs the write-through to AXI.
Normal halfword/word loads and stores follow CORE_ENDIAN; byte-reverse
instructions invert the normal transfer order for that mode. make sim passes
CORE_ENDIAN into cocotb and defaults AZURITE_QEMU_ENDIAN to the same value,
so the compiler, QEMU target, payload, signature parsing, and RTL memory byte
ordering stay matched. If you manually override AZURITE_QEMU_ENDIAN, keep it
matched to CORE_ENDIAN; intentional mismatches will fail byte-lane-sensitive
tests such as lbz_byte_lane_1.
See docs/PowerPC/Architecture.md for the current stage and cache-shim
architecture.
The default simulation builds and runs the big-endian passthrough core:
make simCommon simulation variants:
# Little-endian core and matching LE payload/oracle
make CORE_ENDIAN=le sim
# Concrete L1 caches
make CORE_ENDIAN=be ENABLE_L1_CACHES=1 sim
make CORE_ENDIAN=le ENABLE_L1_CACHES=1 sim
# Focused cocotb test
make CORE_ENDIAN=le ENABLE_L1_CACHES=1 TESTCASE=test_integer_memory_load_store_instructions simThe default simulation parameters are controlled by the top-level Makefile:
CORE_ENDIAN ?= be
PROGRAM ?= programs/bringup/bare-metal/$(CORE_ENDIAN_CANON)_payload.elf
LOAD_BASE ?= 0x80000000
MEM_SIZE ?= 0x02000000
BUS_ROLE ?= masterOverride them on the command line when needed:
make CORE_ENDIAN=le sim PROGRAM=$(pwd)/programs/bringup/bare-metal/le_payload.elf LOAD_BASE=0x80000000The cocotb testbench can also compile C/C++ sources into PowerPC ELFs, load those ELFs into the RTL memory model, run the same ELFs under QEMU, and compare final signatures or retired-instruction traces.
Run one C source through the ELF oracle test:
AZURITE_ORACLE_SOURCE=programs/oracle/longer_signature.c \
AZURITE_ORACLE_SIGNATURE_WORDS=8 \
AZURITE_ORACLE_MAX_CYCLES=1600 \
make sim TESTCASE=test_qemu_oracle_elf_source_from_envRun randomized source generation and QEMU-vs-RTL checks:
# Generate one deterministic random C source without running RTL
python3 tools/qemu_oracle/random_source.py --seed 1 --ops 32 --signature-words 16 --profile stable
# Run a randomized signature check
python3 tools/qemu_oracle/run_random.py --seed 1 --count 1 --ops 32 --signature-words 16 --profile stable
# Run a short seed sweep with retired-instruction trace comparison
python3 tools/qemu_oracle/run_random.py --seed 1 --count 10 --ops 64 --signature-words 16 --profile stable --traceGenerate and run per-instruction stress cases:
# Generate 100 unrolled instances of each target instruction corner case
python3 tools/qemu_oracle/instruction_stress.py --repeat 100 --signature-words 16
# Run one instruction family through QEMU-vs-RTL trace/register checking
python3 tools/qemu_oracle/instruction_stress.py --instruction addi --repeat 100 --signature-words 16 --run --traceGenerated random sources and ELFs are written under build/qemu_oracle/.
Generated stress sources and their manifest.json are written under
build/qemu_oracle/instruction_stress/. The QEMU user-mode oracle defaults to
QEMU_CPU=power10; override with AZURITE_QEMU_CPU if needed. Direct Python
entry points inherit your shell environment, so set CORE_ENDIAN and
AZURITE_QEMU_ENDIAN together when running LE cases outside make sim.
Little-endian QEMU stress runs exclude lmw/stmw because GNU rejects those
mnemonics in little-endian mode; deterministic cocotb coverage still exercises
the RTL implementation.
Coverage collection combines deterministic cocotb tests and QEMU stress tests:
make coverage
make coverage-smokeFor the existing bare-metal payload:
cd programs/bringup
qemu-system-ppc64 -M powernv10 -cpu power10 -nographic -kernel ./bare-metal/be_payload.elfSee also:
programs/README.md
programs/bringup/bare-metal/README.md
If you do not use Docker, install equivalent native tools:
makebscverilatorpython3,pip, andcocotb-config- Python packages:
cocotb,cocotb-test,cocotbext-axi,pyelftools,pytest - PowerPC cross compilers/binutils for big-endian and little-endian payloads
qemu-system-ppc64/ PowerPC QEMU targets- Optional:
gtkwave
Quick sanity checks:
bsc -v
verilator --version
cocotb-config --version
powerpc64le-linux-gnu-gcc --version
qemu-system-ppc64 --versionbsc: command not found— use the Docker image or install Bluespecbscnatively.cocotb-config: No such file or directory— install cocotb in the active Python environment.No rule to make target '/Makefile.sim'—cocotb-config --makefilesfailed, usually because cocotb is not installed.fatal: cannot exec 'ssh'while building/cloning — verify SSH is installed, an SSH agent is running, and your GitHub key is loaded.- Docker cannot access the daemon — start Docker Desktop/daemon, or on Linux try
sudo docker ...depending on your setup.
- OpenPOWER ISA specifications
- PowerISA v3.1C PDF mirror
- Bluespec Compiler
- Verilator
- cocotb
- cocotbext-axi
- QEMU
See LICENSE.
