Exemple #1
0
def _get_incremental_codewords(config, base_ecc, existing_words):
    '''Get all possible incremental codewords fulfilling the constraints.'''

    base_data = base_ecc[config['secded']['ecc_width']:]

    # We only need to spin through data bits that have not been set yet.
    # Hence, we first count how many bits are zero (and hence still
    # modifyable). Then, we enumerate all possible combinations and scatter
    # the bits of the enumerated values into the correct bit positions using
    # the scatter_bits() function.
    incr_cands = []
    free_bits = base_data.count('0')
    for k in range(1, 2**free_bits):
        # Get incremental dataword by scattering the enumeration bits
        # into the zero bit positions in base_data.
        incr_cand = scatter_bits(base_data,
                                 format(k, '0' + str(free_bits) + 'b'))
        incr_cand_ecc = ecc_encode(config, incr_cand)

        # Dataword is correct by construction, but we need to check whether
        # the ECC bits are incremental.
        if _is_incremental_codeword(base_ecc, incr_cand_ecc):
            # Check whether the candidate fulfills the maximum
            # Hamming weight constraint.
            if incr_cand_ecc.count('1') <= config['max_hw']:
                # Check Hamming distance wrt all existing words.
                for w in existing_words + [base_ecc]:
                    if get_hd(incr_cand_ecc, w) < config['min_hd']:
                        break
                else:
                    incr_cands.append(incr_cand_ecc)

    return incr_cands
Exemple #2
0
def _get_new_state_word_pair(config, existing_words):
    '''Randomly generate a new incrementally writable word pair'''
    while 1:
        # Draw a random number and check whether it is unique and whether
        # the Hamming weight is in range.
        width = config['secded']['data_width']
        ecc_width = config['secded']['ecc_width']
        base = random.getrandbits(width)
        base = format(base, '0' + str(width) + 'b')
        base_cand_ecc = ecc_encode(config, base)
        # disallow all-zero and all-one states
        pop_cnt = base_cand_ecc.count('1')
        if pop_cnt >= config['min_hw'] and pop_cnt <= config['max_hw']:

            # Check Hamming distance wrt all existing words
            for w in existing_words:
                if get_hd(base_cand_ecc, w) < config['min_hd']:
                    break
            else:
                # Get encoded incremental candidates.
                incr_cands_ecc = _get_incremental_codewords(
                    config, base_cand_ecc, existing_words)
                # there are valid candidates, draw one at random.
                # otherwise we just start over.
                if incr_cands_ecc:
                    incr_cand_ecc = random.choice(incr_cands_ecc)
                    log.info('word {}: {}|{} -> {}|{}'.format(
                        int(len(existing_words) / 2),
                        base_cand_ecc[ecc_width:], base_cand_ecc[0:ecc_width],
                        incr_cand_ecc[ecc_width:], incr_cand_ecc[0:ecc_width]))
                    existing_words.append(base_cand_ecc)
                    existing_words.append(incr_cand_ecc)
                    return (base_cand_ecc, incr_cand_ecc)
Exemple #3
0
def _to_hexfile_with_ecc(data, annotation, config, data_perm):
    '''Compute ECC and convert into memory hexfile'''

    log.info('Convert to HEX file.')

    data_width = config['secded']['data_width']
    ecc_width = config['secded']['ecc_width']
    assert data_width % 8 == 0, \
        'OTP data width must be a multiple of 8'
    assert data_width <= 64, \
        'OTP data width cannot be larger than 64'

    num_words = len(data) * 8 // data_width
    bytes_per_word = data_width // 8
    # Byte aligned total width after adding ECC bits
    bytes_per_word_ecc = (data_width + ecc_width + 7) // 8
    bit_padding = bytes_per_word_ecc * 8 - data_width - ecc_width
    bin_format_str = '0' + str(data_width) + 'b'
    hex_format_str = '0' + str(bytes_per_word_ecc * 2) + 'x'
    memory_words = '// OTP memory hexfile with {} x {}bit layout\n'.format(
        num_words, bytes_per_word_ecc * 8)
    log.info('Memory layout is {} x {}bit (with ECC)'.format(
        num_words, bytes_per_word_ecc * 8))

    for k in range(num_words):
        # Assemble native OTP word and uniquify annotation for comments
        word = 0
        word_ann = {}
        for j in range(bytes_per_word):
            idx = k * bytes_per_word + j
            word += data[idx] << (j * 8)
            if annotation[idx] not in word_ann:
                word_ann.update({annotation[idx]: "1"})

        # This prints the byte offset of the corresponding
        # payload data in the memory map (excluding ECC bits)
        annotation_str = ' // {:06x}: '.format(k * bytes_per_word) + ', '.join(
            word_ann.keys())

        # ECC encode
        word_bin = format(word, bin_format_str)
        word_bin = ecc_encode(config, word_bin)
        # Pad to word boundary and permute data if needed
        word_bin = ('0' * bit_padding) + word_bin
        word_bin = permute_bits(word_bin, data_perm)
        word_hex = format(int(word_bin, 2), hex_format_str)
        memory_words += word_hex + annotation_str + '\n'

    log.info('Done.')

    return memory_words