diff --git a/.gitignore b/.gitignore index 4b87bac..1d9fbc1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ bazel-* MODULE.bazel.lock .vscode .spr.yml +__pycache__ diff --git a/MODULE.bazel b/MODULE.bazel index d20f62c..17e9af7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -18,7 +18,7 @@ This module defines the Bazel Module (bzlmod) configuration for the ECCGen proje module( name = "eccgen", - version = "0.0.1", + version = "0.1.0", ) bazel_dep(name = "rules_python", version = "1.5.1") diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..3cef3a4 --- /dev/null +++ b/README.adoc @@ -0,0 +1,99 @@ += ECCGen: Error Correcting Code Generator + +:ecc: https://en.wikipedia.org/wiki/Error_correction_code +:secded: https://en.wikipedia.org/wiki/Hamming_code +:hsiao1970: https://ieeexplore.ieee.org/abstract/document/5391627 +:chen2008: https://arxiv.org/pdf/0803.1217 +:bcr: https://registry.bazel.build/ + +image:https://github.com/xlsynth/eccgen/actions/workflows/ci.yml/badge.svg?branch=main["CI", link="https://github.com/xlsynth/eccgen/actions/workflows/ci.yml"] + +image:eccgen.png[ECCGen, width=300px] + +A Python tool that solves for a valid {ecc}[ECC^] construction given some input parameters and writes the generator (`G`) and parity-check (`H`) matrices to plain text output files. +You can use the generator matrix to implement an encoder and the parity-check matrix to implement the complementary decoder. + +== Usage with Python + +Setup: + +[source,shell] +---- +python3 -m venv ~/.virtualenvs/eccgen +source ~/.virtualenvs/eccgen/bin/activate +pip install -r requirements_3_12.in +---- + +Verbose args: + +[source,shell] +---- +python3 -m eccgen.eccgen --help +python3 -m eccgen.eccgen --scheme hsiao_secded --message-size 42 --generator-matrix-output $(pwd)/G.txt --parity-check-matrix-output $(pwd)/H.txt +---- + +Or with concise args: + +[source,shell] +---- +python3 -m eccgen.eccgen -h +python3 -m eccgen.eccgen -s hsiao_secded -k 42 -G $(pwd)/G.txt -H $(pwd)/H.txt +---- + +You can find pre-generated G-H pairs for powers-of-2 message and codeword sizes in `eccgen/matrices`. + +== Usage with Bazel + +You can use Bazel to run and test the tool, as well as depend on it from your own Bazel-based projects with Bzlmod. + +Run the tool: + +[source,shell] +---- +bazel run //eccgen:eccgen -- --scheme hsiao_secded --message-size 42 --generator-matrix-output $(pwd)/G.txt --parity-check-matrix-output $(pwd)/H.txt +---- + +Run the unit tests: + +[source,shell] +---- +bazel test //... +---- + +To depend on the tool from your own Bazel-based project, add the following to your `MODULE.bazel` file: + +[source,starlark] +---- +bazel_dep(name = "eccgen", version = "0.1.0") +git_override( + module_name = "eccgen", + commit = , + remote = "https://github.com/xlsynth/eccgen", +) +---- + +(At some point, we'll publish to the {bcr}[Bazel Central Registry^].) + + +== Hsiao codes + +Currently, the tool only supports {hsiao1970}[Hsiao] single-error-correcting, double-error-detecting ({secded}[SECDED^]) codes, which are commonly found in digital circuit designs. +(The tool can be extended to support other codes.) + +The Hsiao code solver is based on the algorithms from the following papers: + +* {hsiao1970}[Hsiao et. al. 1970^] +* {chen2008}[Chen et. al. 2008^] + +We only use the optimal solver up to `k = 256`; beyond that, we use a greedy solution which is still SECDED, but doesn't qualify as a Hsiao code. + +== Contributing + +We welcome your contributions! +Please feel free to open an issue or submit a pull request. + +We use GitHub Actions for CI: we run the pre-commit checks and all the Bazel tests. + +== License + +This project is licensed under the Apache License 2.0. diff --git a/README.md b/README.md deleted file mode 100644 index d884601..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# eccgen - -[![CI](https://github.com/xlsynth/eccgen/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/xlsynth/eccgen/actions/workflows/ci.yml) - -Error correcting code solver diff --git a/eccgen.png b/eccgen.png new file mode 100644 index 0000000..4b92825 Binary files /dev/null and b/eccgen.png differ diff --git a/eccgen/eccgen.py b/eccgen/eccgen.py index 8ed3609..aa747a2 100644 --- a/eccgen/eccgen.py +++ b/eccgen/eccgen.py @@ -20,75 +20,62 @@ ) import numpy as np -RTL_SUPPORTED_N_K = [ - (8, 4), - (13, 8), - (16, 11), - (22, 16), - (32, 26), - (39, 32), - (64, 57), - (72, 64), - (128, 120), - (137, 128), - (256, 247), - (266, 256), - (512, 502), - (523, 512), - (1024, 1013), - (1036, 1024), -] - def main(): parser = argparse.ArgumentParser(description="Error Correction Code Generator") parser.add_argument( "--scheme", + "-s", type=str, choices=["hsiao_secded"], required=True, help="The error correction code scheme to use (e.g., hsiao_secded)", ) parser.add_argument( - "--k", type=int, required=True, help="The number of data bits (k)" + "-message-size", + "-k", + type=int, + required=True, + help="The number of bits in the message (k)", ) parser.add_argument( "--print0", action="store_true", - help="Print 0s in the outputs (otherwise, leave blanks instead).", + help="Print 0s in the outputs (otherwise, leave blanks instead). Defaults to true.", ) parser.add_argument( "--generator-matrix-output", - "--G", + "-G", type=argparse.FileType("w"), required=True, help="The output file to write the generator matrix to", ) parser.add_argument( "--parity-check-matrix-output", - "--H", + "-H", type=argparse.FileType("w"), required=True, help="The output file to write the parity check matrix to", ) args = parser.parse_args() + k = args.message_size if args.scheme == "hsiao_secded": - r, n, G, H = hsiao_secded_code(args.k) + r, n, G, H = hsiao_secded_code(k) check_construction( G, H, # Code distance check is prohibitively expensive for large k - check_code_distance=(args.k <= MAX_K_FOR_OPTIMAL_ALGORITHM), + check_code_distance=(k <= MAX_K_FOR_OPTIMAL_ALGORITHM), # Row balance check is omitted for non-optimal constructions # since they aren't guaranteed to satisfy the property. - check_row_balance=(args.k <= MAX_K_FOR_OPTIMAL_ALGORITHM), + check_row_balance=(k <= MAX_K_FOR_OPTIMAL_ALGORITHM), ) file_header = "\n".join( [ - f"Number of data bits (k): {args.k}", + f"Number of data bits (k): {k}", f"Number of parity bits (r): {r}", f"Number of codeword bits (n): {n}", ] diff --git a/eccgen/matrices/BUILD.bazel b/eccgen/matrices/BUILD.bazel index 0d662d5..d9bcf45 100644 --- a/eccgen/matrices/BUILD.bazel +++ b/eccgen/matrices/BUILD.bazel @@ -71,7 +71,7 @@ GENERATED_HSIAO_H_K_FILES = ["gen_hsiao_H_k" + k + ".txt" for k in K] "gen_hsiao_G_k" + k + ".txt", "gen_hsiao_H_k" + k + ".txt", ], - cmd = "$(location //eccgen) --k " + k + " --scheme hsiao_secded --G=$(location gen_hsiao_G_k" + k + ".txt) --H=$(location gen_hsiao_H_k" + k + ".txt)", + cmd = "$(location //eccgen) -k " + k + " -s hsiao_secded -G=$(location gen_hsiao_G_k" + k + ".txt) -H=$(location gen_hsiao_H_k" + k + ".txt)", tools = ["//eccgen"], ), ]