crcglot 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crcglot-0.1.0/PKG-INFO +85 -0
- crcglot-0.1.0/README.md +59 -0
- crcglot-0.1.0/pyproject.toml +60 -0
- crcglot-0.1.0/src/crcglot/__init__.py +62 -0
- crcglot-0.1.0/src/crcglot/_helpers.py +124 -0
- crcglot-0.1.0/src/crcglot/c.py +496 -0
- crcglot-0.1.0/src/crcglot/catalogue.py +179 -0
- crcglot-0.1.0/src/crcglot/cli.py +340 -0
- crcglot-0.1.0/src/crcglot/python.py +189 -0
- crcglot-0.1.0/src/crcglot/rust.py +456 -0
- crcglot-0.1.0/src/crcglot/vhdl.py +281 -0
crcglot-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crcglot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Verified CRC source-code for C, Rust, VHDL, Python — catalogue-driven, self-test embedded.
|
|
5
|
+
Keywords: crc,checksum,code-generation,embedded,reveng,rocksoft,williams
|
|
6
|
+
Author: Chuck Bass
|
|
7
|
+
Author-email: Chuck Bass <chuck@acrocad.net>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Project-URL: Homepage, https://github.com/hucker/crcglot
|
|
23
|
+
Project-URL: Repository, https://github.com/hucker/crcglot
|
|
24
|
+
Project-URL: Issues, https://github.com/hucker/crcglot/issues
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# crcglot
|
|
28
|
+
|
|
29
|
+
**Verified CRC source code for C, Rust, VHDL, and Python.** Catalogue-driven, self-test embedded, multi-language by design.
|
|
30
|
+
|
|
31
|
+
LLMs will gladly write you CRC code. It might even be right. `crcglot` guarantees the generated code matches the canonical [reveng catalogue](https://reveng.sourceforge.io/crc-catalogue/all.htm) test vector (`crc("123456789") == <check value>`) and ships a self-test you can run on your toolchain to prove it.
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install crcglot
|
|
37
|
+
|
|
38
|
+
crcglot c crc32 --slice8 file=mycrc # → mycrc.h + mycrc.c
|
|
39
|
+
crcglot rust crc64-xz --slice8 > mycrc.rs
|
|
40
|
+
crcglot vhdl crc32 > mycrc.vhd
|
|
41
|
+
crcglot python crc16-modbus > mycrc.py
|
|
42
|
+
|
|
43
|
+
crcglot list # browse the catalogue
|
|
44
|
+
crcglot info crc32 # show parameters
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## What you get per language
|
|
48
|
+
|
|
49
|
+
| Function | Purpose |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `<fname>_init` / `_update` / `_finalize` | Streaming triple — feed data chunk by chunk |
|
|
52
|
+
| `<fname>` | One-shot wrapper that calls the streaming triple |
|
|
53
|
+
| `<fname>_self_test` | Verify against the reveng check value on your toolchain |
|
|
54
|
+
|
|
55
|
+
C / Rust / VHDL ship `_self_test()` returning 0/1 (or boolean for VHDL). Python verifies via the docstring's `check:` line — the same interpreter generated it.
|
|
56
|
+
|
|
57
|
+
## Implementations
|
|
58
|
+
|
|
59
|
+
| Flag | Description | Width support |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| (default) bit-by-bit | Smallest code, zero RAM table, slowest | All |
|
|
62
|
+
| `--table` | 256-entry lookup table, 4-8× faster | All |
|
|
63
|
+
| `--slice8` | 8 lookup tables, 5-10× faster than `--table` | CRC-32 / CRC-64 only |
|
|
64
|
+
|
|
65
|
+
Each generated file embeds the chosen implementation and the self-test. In constrained embedded targets, standard toolchain flags (`-Wl,--gc-sections` for C, LTO for Rust) strip whatever you don't call.
|
|
66
|
+
|
|
67
|
+
## Custom polynomials
|
|
68
|
+
|
|
69
|
+
For algorithms not in the catalogue, pass Rocksoft/Williams parameters directly:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
crcglot c --custom width=16 poly=0x1234 init=0xFFFF refin=true refout=true xorout=0x0000 file=mycustom
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Catalogue
|
|
76
|
+
|
|
77
|
+
64+ algorithms covering everything from CRC-8 (ATM, AUTOSAR, Bluetooth, Maxim 1-Wire) through CRC-16 (Modbus, XMODEM, CCITT, IBM SDLC) through CRC-32 (Ethernet, bzip2, iSCSI, AUTOSAR) to CRC-64 (XZ, ECMA-182, NVMe, Redis). Browse with `crcglot list`.
|
|
78
|
+
|
|
79
|
+
## Acknowledgments
|
|
80
|
+
|
|
81
|
+
CRC catalogue data is derived from Greg Cook's [reveng project](https://reveng.sourceforge.io/) — the canonical source for CRC algorithm parameters since 1999.
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
crcglot-0.1.0/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# crcglot
|
|
2
|
+
|
|
3
|
+
**Verified CRC source code for C, Rust, VHDL, and Python.** Catalogue-driven, self-test embedded, multi-language by design.
|
|
4
|
+
|
|
5
|
+
LLMs will gladly write you CRC code. It might even be right. `crcglot` guarantees the generated code matches the canonical [reveng catalogue](https://reveng.sourceforge.io/crc-catalogue/all.htm) test vector (`crc("123456789") == <check value>`) and ships a self-test you can run on your toolchain to prove it.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install crcglot
|
|
11
|
+
|
|
12
|
+
crcglot c crc32 --slice8 file=mycrc # → mycrc.h + mycrc.c
|
|
13
|
+
crcglot rust crc64-xz --slice8 > mycrc.rs
|
|
14
|
+
crcglot vhdl crc32 > mycrc.vhd
|
|
15
|
+
crcglot python crc16-modbus > mycrc.py
|
|
16
|
+
|
|
17
|
+
crcglot list # browse the catalogue
|
|
18
|
+
crcglot info crc32 # show parameters
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## What you get per language
|
|
22
|
+
|
|
23
|
+
| Function | Purpose |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `<fname>_init` / `_update` / `_finalize` | Streaming triple — feed data chunk by chunk |
|
|
26
|
+
| `<fname>` | One-shot wrapper that calls the streaming triple |
|
|
27
|
+
| `<fname>_self_test` | Verify against the reveng check value on your toolchain |
|
|
28
|
+
|
|
29
|
+
C / Rust / VHDL ship `_self_test()` returning 0/1 (or boolean for VHDL). Python verifies via the docstring's `check:` line — the same interpreter generated it.
|
|
30
|
+
|
|
31
|
+
## Implementations
|
|
32
|
+
|
|
33
|
+
| Flag | Description | Width support |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| (default) bit-by-bit | Smallest code, zero RAM table, slowest | All |
|
|
36
|
+
| `--table` | 256-entry lookup table, 4-8× faster | All |
|
|
37
|
+
| `--slice8` | 8 lookup tables, 5-10× faster than `--table` | CRC-32 / CRC-64 only |
|
|
38
|
+
|
|
39
|
+
Each generated file embeds the chosen implementation and the self-test. In constrained embedded targets, standard toolchain flags (`-Wl,--gc-sections` for C, LTO for Rust) strip whatever you don't call.
|
|
40
|
+
|
|
41
|
+
## Custom polynomials
|
|
42
|
+
|
|
43
|
+
For algorithms not in the catalogue, pass Rocksoft/Williams parameters directly:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
crcglot c --custom width=16 poly=0x1234 init=0xFFFF refin=true refout=true xorout=0x0000 file=mycustom
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Catalogue
|
|
50
|
+
|
|
51
|
+
64+ algorithms covering everything from CRC-8 (ATM, AUTOSAR, Bluetooth, Maxim 1-Wire) through CRC-16 (Modbus, XMODEM, CCITT, IBM SDLC) through CRC-32 (Ethernet, bzip2, iSCSI, AUTOSAR) to CRC-64 (XZ, ECMA-182, NVMe, Redis). Browse with `crcglot list`.
|
|
52
|
+
|
|
53
|
+
## Acknowledgments
|
|
54
|
+
|
|
55
|
+
CRC catalogue data is derived from Greg Cook's [reveng project](https://reveng.sourceforge.io/) — the canonical source for CRC algorithm parameters since 1999.
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "crcglot"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Verified CRC source-code for C, Rust, VHDL, Python — catalogue-driven, self-test embedded."
|
|
5
|
+
license = "MIT"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
authors = [{name = "Chuck Bass", email = "chuck@acrocad.net"}]
|
|
9
|
+
keywords = ["crc", "checksum", "code-generation", "embedded", "reveng", "rocksoft", "williams"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 4 - Beta",
|
|
12
|
+
"Environment :: Console",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Topic :: Software Development :: Code Generators",
|
|
22
|
+
"Topic :: Software Development :: Embedded Systems",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [] # pure stdlib
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
crcglot = "crcglot.cli:main"
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/hucker/crcglot"
|
|
31
|
+
Repository = "https://github.com/hucker/crcglot"
|
|
32
|
+
Issues = "https://github.com/hucker/crcglot/issues"
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["uv_build"]
|
|
36
|
+
build-backend = "uv_build"
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
testpaths = ["tests"]
|
|
40
|
+
addopts = "-v --cov=crcglot --cov-report=term-missing -n auto"
|
|
41
|
+
markers = [
|
|
42
|
+
"slow: subprocess-spawning test (compiles + runs generated code via gcc / rustc / ghdl). Skip with -m 'not slow' for fast iteration.",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.coverage.run]
|
|
46
|
+
source = ["src/crcglot"]
|
|
47
|
+
|
|
48
|
+
[tool.coverage.report]
|
|
49
|
+
exclude_lines = [
|
|
50
|
+
"if __name__",
|
|
51
|
+
"pragma: no cover",
|
|
52
|
+
]
|
|
53
|
+
show_missing = true
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = [
|
|
57
|
+
"pytest>=8.0",
|
|
58
|
+
"pytest-cov>=7.0",
|
|
59
|
+
"pytest-xdist>=3.8",
|
|
60
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""crcglot -- multi-language CRC code generator.
|
|
2
|
+
|
|
3
|
+
Generate ready-to-compile CRC source code in C, Rust, VHDL, or Python
|
|
4
|
+
for any of 64+ named algorithms (reveng catalogue) or any custom
|
|
5
|
+
Rocksoft/Williams polynomial. Three implementation shapes per target:
|
|
6
|
+
bit-by-bit (smallest), table-driven (4-8x faster), and slice-by-8
|
|
7
|
+
(another 5-10x faster, CRC-32/64 only).
|
|
8
|
+
|
|
9
|
+
Public API:
|
|
10
|
+
- CRC_CATALOGUE: dict of named algorithm parameters.
|
|
11
|
+
- generate_c, generate_python, generate_rust, generate_vhdl:
|
|
12
|
+
name-lookup generators.
|
|
13
|
+
- generate_c_from_entry, etc.: generate from a custom entry dict
|
|
14
|
+
(Rocksoft/Williams params without catalogue lookup).
|
|
15
|
+
- GENERATORS, GENERATORS_FROM_ENTRY: dicts of the two forms
|
|
16
|
+
keyed by language code, for parameterized callers.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Callable
|
|
22
|
+
|
|
23
|
+
from crcglot.c import generate_c, generate_c_from_entry
|
|
24
|
+
from crcglot.catalogue import CRC_CATALOGUE, _generic_crc, _reflect
|
|
25
|
+
from crcglot.python import generate_python, generate_python_from_entry
|
|
26
|
+
from crcglot.rust import generate_rust, generate_rust_from_entry
|
|
27
|
+
from crcglot.vhdl import generate_vhdl, generate_vhdl_from_entry
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Language code -> name-lookup generator callable.
|
|
31
|
+
GENERATORS: dict[str, Callable] = {
|
|
32
|
+
"c": generate_c,
|
|
33
|
+
"python": generate_python,
|
|
34
|
+
"rust": generate_rust,
|
|
35
|
+
"vhdl": generate_vhdl,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Language code -> entry-dict generator callable (custom-params path).
|
|
40
|
+
GENERATORS_FROM_ENTRY: dict[str, Callable] = {
|
|
41
|
+
"c": generate_c_from_entry,
|
|
42
|
+
"python": generate_python_from_entry,
|
|
43
|
+
"rust": generate_rust_from_entry,
|
|
44
|
+
"vhdl": generate_vhdl_from_entry,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"CRC_CATALOGUE",
|
|
50
|
+
"GENERATORS",
|
|
51
|
+
"GENERATORS_FROM_ENTRY",
|
|
52
|
+
"_generic_crc",
|
|
53
|
+
"_reflect",
|
|
54
|
+
"generate_c",
|
|
55
|
+
"generate_c_from_entry",
|
|
56
|
+
"generate_python",
|
|
57
|
+
"generate_python_from_entry",
|
|
58
|
+
"generate_rust",
|
|
59
|
+
"generate_rust_from_entry",
|
|
60
|
+
"generate_vhdl",
|
|
61
|
+
"generate_vhdl_from_entry",
|
|
62
|
+
]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Language-agnostic helpers shared by every target generator.
|
|
2
|
+
|
|
3
|
+
Function-name sanitization, hex formatting, bit masks, and CRC table
|
|
4
|
+
pre-computation are identical across Python / C / Rust / VHDL output
|
|
5
|
+
because they're math, not syntax. Each language module imports what
|
|
6
|
+
it needs from here; per-language helpers (table formatters,
|
|
7
|
+
self-test scaffolds, header builders) stay local to their target.
|
|
8
|
+
|
|
9
|
+
Underscore-prefixed; the package's public API is ``__init__.py``.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from crcglot.catalogue import _reflect
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _func_name(algo_name: str) -> str:
|
|
18
|
+
"""Convert a CRC algorithm name into a valid identifier.
|
|
19
|
+
|
|
20
|
+
Algorithm names from the reveng catalogue use ``-`` and ``.``
|
|
21
|
+
which aren't valid in C / Python / Rust / VHDL identifiers;
|
|
22
|
+
swap them for underscores. Same mangling is applied
|
|
23
|
+
consistently across all four target languages.
|
|
24
|
+
"""
|
|
25
|
+
return algo_name.replace("-", "_").replace(".", "_")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _hex(value: int, width: int) -> str:
|
|
29
|
+
"""Format an integer as a ``0xHEX`` literal sized for ``width`` bits.
|
|
30
|
+
|
|
31
|
+
The ``0x``-prefixed form is identical in C / Python / Rust source
|
|
32
|
+
(and acceptable in VHDL comments), so callers across all target
|
|
33
|
+
languages share this helper. VHDL *code* uses :func:`_vhdl_lit`
|
|
34
|
+
from the vhdl module because hex literals there have a different
|
|
35
|
+
syntax for arithmetic contexts.
|
|
36
|
+
"""
|
|
37
|
+
hex_w = (width + 3) // 4
|
|
38
|
+
return f"0x{value:0{hex_w}X}"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _mask(width: int) -> str:
|
|
42
|
+
"""Format ``(1 << width) - 1`` as a hex literal of matching width."""
|
|
43
|
+
return _hex((1 << width) - 1, width)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _build_table(width: int, poly: int, refin: bool) -> list[int]:
|
|
47
|
+
"""Pre-compute the 256-entry CRC lookup table for an algorithm.
|
|
48
|
+
|
|
49
|
+
Returns the table as a list of ``width``-bit integers, one per
|
|
50
|
+
possible byte value. Caller renders this list to its target
|
|
51
|
+
language's array syntax via per-language formatters.
|
|
52
|
+
|
|
53
|
+
The reflected-input case uses the reflected polynomial and
|
|
54
|
+
right-shifts; the normal case left-shifts. Both are textbook
|
|
55
|
+
Sarwate's algorithm.
|
|
56
|
+
"""
|
|
57
|
+
table = []
|
|
58
|
+
if refin:
|
|
59
|
+
ref_poly = _reflect(poly, width)
|
|
60
|
+
for i in range(256):
|
|
61
|
+
crc = i
|
|
62
|
+
for _ in range(8):
|
|
63
|
+
if crc & 1:
|
|
64
|
+
crc = (crc >> 1) ^ ref_poly
|
|
65
|
+
else:
|
|
66
|
+
crc >>= 1
|
|
67
|
+
table.append(crc & ((1 << width) - 1))
|
|
68
|
+
else:
|
|
69
|
+
for i in range(256):
|
|
70
|
+
crc = i << (width - 8)
|
|
71
|
+
for _ in range(8):
|
|
72
|
+
if crc & (1 << (width - 1)):
|
|
73
|
+
crc = (crc << 1) ^ poly
|
|
74
|
+
else:
|
|
75
|
+
crc <<= 1
|
|
76
|
+
crc &= (1 << width) - 1
|
|
77
|
+
table.append(crc)
|
|
78
|
+
return table
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _build_slice8_tables(
|
|
82
|
+
width: int, poly: int, refin: bool,
|
|
83
|
+
) -> list[list[int]]:
|
|
84
|
+
"""Pre-compute the 8 tables used by slice-by-8 CRC.
|
|
85
|
+
|
|
86
|
+
Returns ``[T0, T1, ..., T7]``: each Tk is a 256-entry list of
|
|
87
|
+
width-bit ints. Tk[i] is the CRC of ``[i] + [0] * k`` -- i.e.
|
|
88
|
+
the contribution to the running CRC of a byte at position k.
|
|
89
|
+
|
|
90
|
+
The recurrence: ``T(k+1)[i] = T0[low_byte(Tk[i])] ^ shifted_rest(Tk[i])``
|
|
91
|
+
where the shift direction matches the polynomial direction. This
|
|
92
|
+
is what powers Intel's slice-by-8 (5-10x throughput over standard
|
|
93
|
+
table-driven for CRC-32 / CRC-64 on big buffers).
|
|
94
|
+
"""
|
|
95
|
+
mask = (1 << width) - 1
|
|
96
|
+
t0 = _build_table(width, poly, refin)
|
|
97
|
+
tables = [t0]
|
|
98
|
+
for _ in range(7):
|
|
99
|
+
prev = tables[-1]
|
|
100
|
+
nxt: list[int] = []
|
|
101
|
+
if refin:
|
|
102
|
+
# Reflected: low byte feeds next lookup, rest shifts right.
|
|
103
|
+
for i in range(256):
|
|
104
|
+
v = prev[i]
|
|
105
|
+
nxt.append((t0[v & 0xFF] ^ (v >> 8)) & mask)
|
|
106
|
+
else:
|
|
107
|
+
# Normal: high byte feeds next lookup, rest shifts left.
|
|
108
|
+
for i in range(256):
|
|
109
|
+
v = prev[i]
|
|
110
|
+
top = (v >> (width - 8)) & 0xFF
|
|
111
|
+
nxt.append((t0[top] ^ ((v << 8) & mask)) & mask)
|
|
112
|
+
tables.append(nxt)
|
|
113
|
+
return tables
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# Note: a Python reference for slice-by-8 was considered but dropped.
|
|
117
|
+
# It would have served as a test oracle for the generated C / Rust
|
|
118
|
+
# code, but Python doesn't benefit from slice-by-N at runtime (per-int
|
|
119
|
+
# overhead eats the win), and using it as an oracle adds a third
|
|
120
|
+
# implementation that itself needs verification. Better verification:
|
|
121
|
+
# generate both bit-by-bit and slice-by-8 in the target language,
|
|
122
|
+
# compile both, run both on the same inputs, assert they agree.
|
|
123
|
+
# Bit-by-bit is reveng-verified, so equivalence means slice-by-8 is
|
|
124
|
+
# correct. Tests live in tests/test_crc_codegen_exec.py.
|