1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-20 10:17:05 +00:00

Shunt CRC XOR table generation to compile time.

This commit is contained in:
Thomas Harte
2025-01-28 17:36:32 -05:00
parent bc8d1cc384
commit 53a3e88d16
3 changed files with 30 additions and 21 deletions
+28 -19
View File
@@ -8,6 +8,9 @@
#pragma once
#include "Carry.hpp"
#include <array>
#include <cstdint>
#include <vector>
@@ -26,30 +29,41 @@ constexpr uint8_t reverse_byte(uint8_t byte) {
}
/*! Provides a class capable of generating a CRC from source data. */
template <typename IntType, IntType reset_value, IntType output_xor, bool reflect_input, bool reflect_output>
template <
typename IntType,
IntType polynomial,
IntType reset_value,
IntType output_xor,
bool reflect_input,
bool reflect_output
>
class Generator {
public:
/*!
Instantiates a CRC16 that will compute the CRC16 specified by the supplied
@c polynomial and @c reset_value.
*/
constexpr Generator(IntType polynomial) noexcept: value_(reset_value) {
const IntType top_bit = IntType(~(IntType(~0) >> 1));
for(int c = 0; c < 256; c++) {
IntType shift_value = IntType(c << multibyte_shift);
for(int b = 0; b < 8; b++) {
IntType exclusive_or = (shift_value&top_bit) ? polynomial : 0;
shift_value = IntType(shift_value << 1) ^ exclusive_or;
}
xor_table[c] = shift_value;
}
}
constexpr Generator() noexcept: value_(reset_value) {}
/// Resets the CRC to the reset value.
void reset() { value_ = reset_value; }
/// Updates the CRC to include @c byte.
void add(uint8_t byte) {
static constexpr std::array<IntType, 256> xor_table = [] {
std::array<IntType, 256> table{};
constexpr IntType top_bit = Numeric::top_bit<IntType>();
for(size_t c = 0; c < 256; c++) {
IntType shift_value = IntType(c << multibyte_shift);
for(int b = 0; b < 8; b++) {
const IntType exclusive_or = (shift_value & top_bit) ? polynomial : 0;
shift_value = IntType(shift_value << 1) ^ exclusive_or;
}
table[c] = shift_value;
}
return table;
} ();
if constexpr (reflect_input) byte = reverse_byte(byte);
value_ = IntType((value_ << 8) ^ xor_table[(value_ >> multibyte_shift) ^ byte]);
}
@@ -100,7 +114,6 @@ public:
private:
static constexpr int multibyte_shift = (sizeof(IntType) * 8) - 8;
IntType xor_table[256];
IntType value_;
};
@@ -108,15 +121,11 @@ private:
Provides a generator of 16-bit CCITT CRCs, which amongst other uses are
those used by the FM and MFM disk encodings.
*/
struct CCITT: public Generator<uint16_t, 0xffff, 0x0000, false, false> {
CCITT(): Generator(0x1021) {}
};
using CCITT = Generator<uint16_t, 0x1021, 0xffff, 0x0000, false, false>;
/*!
Provides a generator of "standard 32-bit" CRCs.
*/
struct CRC32: public Generator<uint32_t, 0xffffffff, 0xffffffff, true, true> {
CRC32(): Generator(0x04c11db7) {}
};
using CRC32 = Generator<uint32_t, 0x04c11db7, 0xffffffff, 0xffffffff, true, true>;
}
+1 -1
View File
@@ -14,7 +14,7 @@ namespace {
constexpr int PLLClockRate = 1920000;
}
Parser::Parser(): crc_(0x1021) {
Parser::Parser() {
shifter_.set_delegate(this);
}
+1 -1
View File
@@ -58,7 +58,7 @@ private:
void process_pulse(const Storage::Tape::Pulse &) override;
bool did_update_shifter(int new_value, int length);
CRC::Generator<uint16_t, 0x0000, 0x0000, false, false> crc_;
CRC::Generator<uint16_t, 0x1021, 0x0000, 0x0000, false, false> crc_;
Shifter shifter_;
};