Skip to main content

RIME: resident management environment for the Lattice ECP5 IcePi Zero, synthesized with nosis (no yosys)

Project description

RIME

RIME is the Resident IcePi Management Environment.

It is the resident control plane for the IcePi Zero: a persistent boot image that manages flash, SDRAM, and SD card operations over a UART protocol. The host-side CLI handles build, inspect, install, verify, doctor, janitor, compose, and reload workflows.

The short version:

  • Lattice ECP5-25F: 24,288 LUTs, 56 block RAMs, 28 multipliers.
  • RIME makes it dependable — safe flash updates with write-unlock gating, verified readback, one CLI for everything.
  • Synthesized by nosis, a pure-Python SystemVerilog synthesizer; placed and packed with the OSS CAD Suite toolchain.
  • Two firmware images:
Image LUTs BRAMs Purpose
RIME ~5,966 (24%) 0 Flash + SDRAM service, SD install engine, auto-recovery FSM
EMBER 9,534 (39%) 2 Hardware TRNG: 192 ring oscillators, AES-128-CBC, NIST health tests

RIME includes an app shell with LED heartbeat, SD card read/write, firmware-mediated SD bundle install (sd_install_engine.sv), host-mediated staged install, inline-key write gating on destructive operations, length-prefixed responses with CRC-8 integrity, and a compositor system for stackable FPGA modules with N-way composition. Auto-recovery from SD is wired and silicon-verified (arm → boot → install → verify full cycle). EMBER's entropy subsystem is available as a composable module (EMBER-LITE).

Examples below assume the current working directory is the repository root. Board identity, layout, and toolchain paths resolve through command-line flags, environment variables, or optional local configuration rather than fixed host paths.

Hardware

RIME targets the IcePi Zero board:

Component Part Detail
FPGA Lattice ECP5U-25F 24,288 LUTs, 56 block RAMs, 28 multipliers
Package CABGA256 256-ball BGA
Flash Winbond W25Q128 16 MB QSPI NOR, 64 KB erase sectors
SDRAM Winbond W9825G6KH 32 MB SDR, x16, 512 columns, 8192 rows, 4 banks
SD slot microSD SPI mode, SDHC/SDXC only (SDSC not supported)
USB bridge FTDI FT231X UART (VCP driver) or JTAG (WinUSB driver)
Clock 50 MHz oscillator Divided to 25 MHz system clock in fabric
I/O 5 LEDs, 2 buttons Active-low button[0] is reset

The upstream schematic uses a generic Micron MT48LC16M16A2P KiCad symbol but the BOM populates a Winbond W9825G6KH (LCSC C62246). Both are pin-compatible 256 Mbit SDRAMs in TSOP-II 54 with identical organization: 8192 rows, 512 columns, 4 banks, 16-bit data. The SDRAM controller addresses the full 32 MB.

SDRAM

The full 32 MB SDRAM is operational. All 13 row address bits are verified functional on silicon, including row-boundary writes.

The install command auto-detects full SDRAM and uses the staged upload path: stream the entire bitstream into SDRAM over UART, then commit to flash at SPI speed with on-board verify. See docs/THROUGHPUT.md for current reference-silicon timings (regenerated by scripts/bench_report.py).

Why RIME Exists

IcePi Zero is a portable FPGA board with flash, SD, and direct host connectivity. RIME exists to turn it from "interesting FPGA hardware" into "a board you can iterate on, deploy to, and recover with confidence":

  • rewrite flash safely, gated behind a write-unlock handshake
  • verify readback instead of trusting writes blindly
  • install from SD through the resident service or via autonomous boot-time recovery
  • inspect board state, flash state, and SD state from one coherent interface
  • compose multiple hardware modules into a single bitstream from the command line

Who It Is For

  • firmware and FPGA iteration on a board that may need repeated updates
  • portable or bench workflows where SD-based staging is useful
  • setups where you want one operator surface for build, inspect, install, verify, compose, and reload

Less of a fit:

  • one-off SRAM loads with no interest in persistence
  • generic FPGA bring-up on non-IcePi targets

Resource Footprint

RIME service image

Resource Used Available Utilization
LUT4 ~5,966 24,288 24%
DFF ~3,500 24,288 14%
DP16KD (block RAM) 0 56 0%
MULT18X18D 0 28 0%

The service provides 27 commands covering flash read/write/erase (with UNLOCK gating), SDRAM read/write/stream/commit/verify, SD card read/write/CRC/install, raw SDRAM word access, app shell identity/uptime, and diagnostics. It enters service mode via the app shell (phase 4 → phase 5).

The boot image includes the SD install engine (sd_install_engine.sv) for firmware-mediated bundle installs and the auto-recovery FSM (auto_recovery.sv) for autonomous SD-to-flash restore on boot.

EMBER — Entropy Measurement and Board-level Environmental Randomness

Resource Used Available Utilization
LUT4 9,534 24,288 39%
DFF 1,959 24,288 8%
DP16KD (block RAM) 2 56 3%

EMBER is a hardware true random number generator. 192 ring oscillators in three thermally isolated paths (64 per path), majority-voted, Von Neumann debiased, LFSR whitened, then AES-128-CBC conditioned. NIST SP 800-90B health tests run continuously. 60-second thermal warmup.

EMBER is a standalone experiment image. When loaded, it takes 100% of the FPGA.

Compositor Modules

The compositor (icepi/compose.py) combines RIME-I (a RISC-V soft CPU) with up to 16 hardware modules into a single bitstream. Each module declares its resource budget and interfaces in a module.json manifest. The compositor validates that the combined budget fits the ECP5, assigns each module a unique address region (0x30-0x3F), generates the top-level wrapper, and builds through the standard pipeline.

rime compose anvil cairn scry --clean

Modules that declare a snoop interface requirement (like SCRY) get bus observation ports wired automatically.

Current modules (LUT4 counts from per-module synth_ecp5 -noflatten, refreshed by scripts/verify_manifest_luts.py; integration may shift these by ±15%):

Module Type ~LUTs Description
RIME-I CPU ~4,050 RV32I base integer (37 instructions + FENCE), multi-cycle, 14 KB BRAM
SLAB Memory ~1,300/KB Stackable LUT Allocated Block. 1 KB distributed LUT RAM tile
SCRY Debug ~1,000 Circular trace buffer. Passively records CPU bus transactions
SIFT Filter ~3,200 256-bit Bloom filter, 3 hash functions
MARK Security ~250 Free-running LFSR sampled on demand. Timing-dependent fingerprint
DICE Compute ~300 256-cycle stochastic multiply/add
GLYPH Crypto ~500 GF(2^8) multiply, inverse, exponentiation
PACK Compress ~500 RLE compressor with 32-entry output FIFO
PARSE Match ~500 8-state configurable hardware NFA
TAPER Math ~250 Saturating add, signed multiply, min/max/abs
MOSS Spatial ~1,200 8x8 Game of Life with toroidal wrapping
AUGUR Probability ~600 4-chain Metropolis-Hastings MCMC sampler
ANVIL Checksum ~50 CRC-32 accelerator (IEEE 802.3)
LATCH Timer ~400 Watchdog timer + event counter with timestamp
HEDGE Control ~250 Token bucket rate limiter
EPOCH Clock ~450 Real-time clock synthesizer from 25 MHz sys_clk
CAIRN Stack ~2,000 16-deep 32-bit Forth-style stack machine
WEAVE Serial ALU ~550 Bit-serial 32-cycle add/sub/mul, 1-cycle logic
FLUX PID ~550 Fixed-point PID controller with anti-windup
ORACLE Interpolator ~1,800 64-entry lookup table with linear interpolation
DELTA Diff ~500 Byte-stream XOR differencing engine
VIGIL ECC ~150 Hamming(7,4) SEC encoder/decoder
GRAIL Merkle ~4,000 8-leaf CRC-32 Merkle tree hasher
SENTRY Protection ~400 Memory protection unit. 4 address ranges with R/W permissions
TIDE Waveform ~250 DDS waveform generator. Square/saw/triangle/sine
RUNE Font ~510 8x8 bitmap font renderer. Full printable ASCII (32-126)
VAULT Crypto ~150 AES-128 single-round (SubBytes+AddRoundKey, correct FIPS 197 S-box)
PRISM Color ~100 RGB to grayscale/min/max/saturation/invert
CHORD Audio ~570 4-voice DDS synthesizer. Square/saw/tri/sine per voice
QUILL Buffer ~550 4-channel 8-byte circular FIFO
EMBER-LITE TRNG ~124 8 ring oscillators (LUT4 primitives), Von Neumann debiased
AXIOM Tokenizer ~300 JSON token scanner with nesting depth tracking
SIGMA Checksum ~50 Fletcher-16 streaming checksum
BLOOM Bitops ~30 Popcount, CLZ, CTZ, bit reverse, parity
FORGE Hash ~800 Simplified single-word iterative hash (not a standard SHA-256 digest). Uses correct SHA-256 K constants, Ch, Maj, and Σ functions but processes one 32-bit word per invocation instead of a 512-bit message block — not interoperable with SHA-256
FLOCK Simulation ~100 4-agent boids with cohesion, separation, and alignment forces
MORTAR Matrix ~50 2x2 signed 8-bit matrix multiply
LACE Address ~50 Linear Address from Coordinate Encoding. Z-order bit interleave (2D + 3D)
FLIP Transform ~200 Fast Logical Interstitial Permutator. 8x8 and 32x32 bit-matrix transpose
APEX Data structure ~700 Asynchronous Priority Evaluation matriX. 16-entry hardware priority queue
HALO Buffer ~200 Hardware Assisted Loop Orchestrator. 64-entry ring buffer with watermark
HAMMER Matching ~250 Hardware Accelerated Matching and Measurement Engine Register. 256-bit Hamming distance
CHURN Hash ~300 Continuous Hash Updating and Rolling Node. 32-byte Rabin-Karp rolling hash
HEAT Profiling ~300 Hardware Execution Activity Tracker. 16-page memory access heatmap (snoop)
ECHO Debug ~300 Event Capture and Hardware Observer. 16-entry cycle-stamped bus logger (snoop)
LOGOS Math ~500 Logarithmic Operations and General Optimization System. Log-domain multiply/divide/sqrt
ORBIT Trig ~600 Optimized Rotation and Basic Iteration Toolkit. 20-iteration CORDIC
MIRROR Lookup ~1,000 Memory Indexing and Rapid Resolution Object Router. 16-entry masked pseudo-TCAM
MOUNT Crypto ~2,500 Modular Operation Utility for Number Theory. 256-bit Montgomery multiplier
DIVIDE Math ~400 Direct Integer Variable-length Iterative Division Engine. 32-bit unsigned divide
CRANK Math ~400 Cyclic Register Arithmetic Numerical Kernel. 32x32 to 64-bit iterative multiply
SIEVE Bitops ~700 Selective Indexed Extract and Variable Embed. Bit-field extract and deposit
TALLY DSP ~400 Triggered Accumulating Linear Logic sYnthesizer. 4-channel multiply-accumulate
PROOF Crypto ~650 Protected Read-Once Operational Fence. Constant-time 32-byte comparison
ETCH Crypto ~600 Encrypted Transform with Cyclic Hashing. XTEA 64-round Feistel block cipher
SEED Crypto ~500 Secure Entropy-Enhanced Derivation. FNV-1a nonce generator
NOTCH Control ~250 Noise-Opposing Transition and Contact Handler. 8-channel debounce filter
PHASE Control ~150 Periodic Hardware Accumulation and Signal Encoder. Quadrature decoder
TEMPO Control ~250 Timed Event Measurement and Period Observer. Frequency and period counter
CODEC Codec ~200 Compact Ordered Data Encoding/Decoding Coprocessor. Base64 encode/decode
RANK Sort ~2,400 Rapid Associative Numerical Keyed sorter. 8-element parallel sorting network
TRAP Debug ~350 Triggered Response to Address Predicate. 4-address hardware breakpoint (snoop)
GAUGE Profiling ~250 General Aggregated Utilization and Granular Estimator. Bus bandwidth counter (snoop)
DEPTH Debug ~350 Dynamic Execution Profile and Thread Height tracker. Stack pointer tracker (snoop)
CELL Spatial ~700 Configurable Elementary Local Logic automaton. 64-cell 1D Wolfram cellular automaton
SPARK ML ~300 Simple Perceptron with Activation and Responsive Kernel. 8-input single-layer perceptron
HAZE Procgen ~150 Hardware Approximation of Zoned Entropy. 2D gradient noise via hash and bilinear interpolation
CLASP Sync ~50 Contested Lock with Atomic Set Protocol. 8-slot atomic test-and-set mutex
GPIO I/O ~150 General Purpose Input/Output. 16 software-driven pins with direction and edge detect
PULSE I/O ~250 Programmable Unified Logic for Signal Emission. 4-channel 16-bit PWM generator
SPOKE I/O ~100 Serial Peripheral Output/Kernel Exchange. SPI master with internal loopback (no external pins)
WIRE I/O ~50 Wired Interconnect for Register Exchange. I2C master FSM with internal loopback (no external pins)
FERRY DMA ~1,500 Fast External Register Relay Engine. 16-word internal scratchpad copy engine
ARBOR IRQ ~150 Arbitrated Routing for Board-level Ordered Requests. 16-source priority interrupt controller
PYLON IPC ~250 Paired Yield-Linked Output Node. 8-deep 32-bit FIFO mailbox
DRUM Sequencer ~1,000 Driven Register Utility for Microsequencing. 16-instruction programmable sequencer

RIME-I is a multi-cycle RV32I soft CPU. 5-state FSM, 38 instructions (37 base integer + FENCE). Memory is 14 KB of block RAM (7 DP16KD) with firmware initialized via initial blocks and $readmemh. The RV32I assembler (gen_firmware.py) covers the full ISA.

See modules/ for manifests, HDL sources, and test scripts.

Quick Start

Minimum host requirements:

  • Python 3.11 or newer
  • OSS CAD Suite providing nextpnr-ecp5, ecppack, and openFPGALoader

Install from PyPI (pulls the nosis synthesizer and pyserial):

pip install rime-ecp5

The firmware sources are bundled, so rime build works from the installed package (it writes build artifacts to ./rime-build/). For development from a source checkout:

python -m pip install -e ".[dev]"
pre-commit install

First Success Path

rime status
rime doctor
rime build rime --clean
rime install rime --slot boot --reload --build

(From a source checkout, python icepi_helper.py <command> is equivalent to rime <command>.)

Board Modes

The IcePi Zero shares one USB-C port between UART (serial communication) and JTAG (bitstream loading). Only one mode is active at a time.

  • UART mode: all RIME commands. Normal operating mode.
  • JTAG mode: openFPGALoader for SRAM loads and QSPI bootstrap. Only needed for first-time setup, disaster recovery, or standalone experiment bitstreams.
rime-admin uart     # switch to UART
rime-admin jtag     # switch to JTAG

The UART-only workflow avoids driver switching entirely.

Service Mode

RIME boots to an app shell that responds to HELLO, PING, UPTIME, and IDENTITY. Service commands are gated until ENTER_SERVICE switches to service mode. EXIT_SERVICE returns to app mode.

Destructive operations (ERASE64, PROGRAM16) carry an inline 4-byte RIME key prefix (0x52 0x49 0x4D 0x45) in every request payload. There is no stateful unlock or expiry timer. The legacy UNLOCK command (0x03) is retained as a benign no-op for backwards compatibility.

See PROTOCOL.md for the full command specification.

Update Paths

Full SDRAM-Staged Update (default)

Stream the entire bitstream into SDRAM in 4 KB blocks over UART, then commit to flash at SPI speed with on-board verify. See docs/THROUGHPUT.md for current measured timings.

Chunked SDRAM Update (fallback)

For boards with row-aliased SDRAM, repeatedly stream 1 KB to SDRAM word 0 and commit that chunk to flash. Slower than full staging but robust against SDRAM row failures. upload_bitstream() automatically falls back to this path if the staged path fails.

SD Bundle Install

Stage a RIME bundle to raw SD space, then sd-install <lba> installs it through the resident service. The install engine (sd_install_engine.sv) parses the bundle header, erases flash sectors, and programs from SD — all on-board.

Auto-Recovery

The boot image includes an auto-recovery FSM that checks SD LBA 1 for an armed control block on every boot. If armed, it initializes SD, reads the control block, validates the checksum, and installs the staged bundle to flash. Any UART byte during recovery aborts to the app shell (the operator is never locked out).

rime sd-auto-arm rime --slot boot --build

Bootstrap / Recovery

rime-admin flash-qspi rime

JTAG path. For when the resident service is absent or suspect.

Flash Layout

config/icepi-layout.json defines named flash slots, aliases, and bundle geometry.

Slot Offset Size Purpose
boot 0x000000 1 MB Resident boot image
backup 0x100000 1 MB Secondary firmware slot
staging 0x200000 1 MB Alternate firmware slot
scratch 0x300000 13 MB Data, manifests, experiments

Composing Modules

# Validate resource budget without building
rime compose anvil cairn scry --validate-only

# Compose and build
rime compose anvil cairn scry --clean

The compositor assigns each module an address region (0x30-0x3F) and generates a complete SoC wrapper with RIME-I, BRAM, UART, and N module instantiations.

Configuration

Board selection and tool resolution come from command-line flags, environment variables, or config/board.local.json.

Variable Purpose
ICEPI_ROOT Repository root override
ICEPI_LAYOUT_FILE Path to flash layout JSON
ICEPI_BOARD_CONFIG Path to local board identity JSON
ICEPI_USB_SERIAL USB serial number filter
ICEPI_BAUD UART baud rate (default 115200)
ICEPI_OSS_CAD_ROOT OSS CAD Suite root directory
ICEPI_PYTHON Python interpreter override

Build System

nosisnextpnr-ecp5ecppack. The build system auto-detects module dependencies by scanning instantiated names in project sources. Per-project build.json provides custom nextpnr flags.

rime build --list
rime build rime --clean
rime build ember --clean

Testing

RIME has two regression suites that cover different failure domains and neither subsumes the other.

Board regression (UART):

python tests/regression.py           # single CRC through every subsystem
python tests/regression.py --verbose  # show per-step accumulator detail

Threads a CRC-32 accumulator through: app shell round-trip, protocol core, DEBUG state verification, CRC-8 frame integrity, JEDEC 3x, flash write/verify, stale-read regression, deployed-bitstream match, SDRAM round-trip, row isolation, 64-chunk fill, flash/SDRAM crosstalk, bank isolation, row boundary, 9-bit column stress, row errata scan, stream 16/64/32K, timeout recovery, 1024-byte chunked commit with host and on-board verify, SD read/write/CRC, SD_INSTALL bundle round-trip, auto-recovery arm/disarm, SD_CRC32_RANGE, staged upload with wipe_slot, address clamping, SET_WATCHDOG, inline-key rejection, 8-byte error frames, RAW_WRITE row boundary, throughput bench, and janitor cleanup. Output: one hex value (CHAIN:XXXXXXXX). If any subsystem fails, the chain diverges and the value is wrong.

Themed composition regressions (JTAG):

Seven themed composition images, each with a verification firmware that exercises every module in the image and prints labelled readbacks for host-side comparison against a Python predictor.

Image Modules Regression
compute (Gauntlet) divide, crank, sieve, tally, taper, weave, bloom, mortar, logos, flip, lace, orbit, mount, glyph gauntlet.py
crypto (Seal) vault, forge, vigil, grail, anvil, sigma, emberlite, mark, sentry, churn, hammer, proof, etch, seed seal.py
control (Servo) tide, chord, flux, oracle, epoch, latch, hedge, notch, phase, tempo servo.py
data (Ingest) apex, axiom, cairn, codec, delta, halo, mirror, pack, parse, quill, rank, rune, sift ingest.py
observe (Profile) scry, echo, heat, epoch, latch, prism, trap, gauge, depth profile.py
sim (Evolve) augur, cell, dice, emberlite, epoch, flock, flux, haze, moss, oracle, spark evolve.py
peripheral clasp, gpio, pulse, spoke, wire, ferry, arbor, pylon, drum peripheral.py
python modules/compositions/gauntlet.py --gen-only    # generate firmware + sim

To run on silicon, generate the composition top.sv via icepi.compose.compose() then build with icepi_helper.py build compositions --clean and flash via JTAG.

Module torture sweep (offline, no hardware):

python modules/torture_sweep.py

Discovers every test_*_torture.py under modules/, calls each gen(), and verifies the firmware fits in the 1024-word BRAM. Any new module with a torture test is automatically included.

Offline Python tests (no hardware):

pip install -e ".[dev]"
python -m pytest tests/ --ignore=tests/regression.py -q
ruff check .

Repository Surface

File Role
icepi_helper.py CLI entry point: 40+ subcommands
icepi/commands/ Command implementations
icepi_admin.py Admin wrapper: build, flash, driver switching, reload
icepi/flash_service.py Board discovery, UART transport, protocol client
icepi/compose.py N-way compositor: resource budgeting, top.sv generation
icepi/build.py FPGA build pipeline: source collection, synthesis, P&R
icepi/layout.py Flash layout loading, image planning
icepi/bundle.py RIME bundle format: parse, validate, build
icepi/sd.py SD partitions, FAT32 filesystem, auto-recovery control
icepi/models.py Domain model dataclasses
icepi/tools.py Path resolution, tool discovery, utilities
PROTOCOL.md UART protocol specification
config/icepi-layout.json Flash slot map, aliases, bundle geometry
firmware/images/rime/top.sv RIME top module (clock, reset, SDRAM, SPI, SD, install engine, auto-recovery)
firmware/images/rime/rime_service.sv UART protocol FSM (27 commands)
firmware/images/rime/rime_service_defs.svh Extracted command IDs, capability flags, FSM state encodings
firmware/images/ember/top.sv EMBER: hardware TRNG
firmware/core/flash_spi_master.sv QSPI flash transaction engine
firmware/core/sdram_controller.sv SDR SDRAM controller
firmware/core/sdram_bridge.sv 16-byte bulk SDRAM bridge
firmware/core/sd_spi_master.sv SD card SPI engine
firmware/core/sd_install_engine.sv Firmware-mediated SD bundle installer
firmware/core/auto_recovery.sv Boot-time auto-recovery FSM
modules/rime-i/rime_i_core.sv RV32I CPU core
modules/rime-i/gen_firmware.py RV32I assembler (38 instructions)
modules/rime-i/test_isa.py ISA torture test (37 instructions, single hash)
modules/compositor_template.py Shared top.sv generator for module tests
modules/compositor_test.py Shared test runner (build, JTAG flash, serial read)
modules/torture_gen.py Hash-based torture test generator framework
tests/regression.py Board regression: CRC chain through every subsystem
modules/compositions/{gauntlet,seal,servo,ingest,profile,evolve,peripheral}.py Seven themed composition silicon regressions
modules/compositions/verify.py Host verifier: build, flash, read, compare against Python predictor
modules/torture_sweep.py Offline torture sweep over all module tests
tests/test_protocol.py Offline protocol tests (MockSerial + Hypothesis)
tests/test_*.py Offline Python tests

Architecture

See docs/ARCHITECTURE.md for the layer diagram, data paths, FSM state table, bus muxing, module bus protocol, and test suite overview.

Contributing

See CONTRIBUTING.md for setup, module creation, register interface, and code style.

Known Limitations

  • The $signed() >>> shamt operator has a history of miscompiling for ECP5. The CPU uses explicit sign-extension masks instead.
  • BRAM INITVAL propagation via $readmemh works for initial blocks but not for runtime loading. The ecpbram patch path exists for firmware-only updates without re-synthesis.

The (* keep *) annotations in top.sv and rime_service.sv are retained as a backstop against constant-folding of signals involved in combinational cycles; the primary fix was removing svc_reset_req and wdog_reset from the rst wire (which created a feedback cycle through rime_service). CRC-8 frame integrity is computed inside the service FSM to avoid a similar feedback cycle through the top-level inject chain.

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rime_ecp5-0.1.2.tar.gz (1.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rime_ecp5-0.1.2-py3-none-any.whl (2.1 MB view details)

Uploaded Python 3

File details

Details for the file rime_ecp5-0.1.2.tar.gz.

File metadata

  • Download URL: rime_ecp5-0.1.2.tar.gz
  • Upload date:
  • Size: 1.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for rime_ecp5-0.1.2.tar.gz
Algorithm Hash digest
SHA256 33e325f3ba62d35bff8fa63b68ea3ff08d3d9919a994987a2885a2102e168578
MD5 7ae99df0e7e782aa09517f98410082e6
BLAKE2b-256 d94158b0a028d16a1d0e5af6af5cda8f256f5b7fd419b9e933f26eceae5b51c7

See more details on using hashes here.

File details

Details for the file rime_ecp5-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: rime_ecp5-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 2.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for rime_ecp5-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4af2dad9f849c00ae025acf6ba111d4b5301eb35f56ff92e34b1b4431d710e30
MD5 db5ed3f3d01ac542e80f8b66ef5a1735
BLAKE2b-256 4fc63df6f1ae5cb50307ff6ad9a8d0de356995a9692c9e2b30d67d4a2738d546

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page