def generate_cheader(fields, input_dir, output_dir):
    """ Generates C header file from the `template_file`.

    It produces a list of tuples with a field name and the `MemoryRegion`
    object, which is used in the `template_path`. The resulting header file is
    placed into `output_path`.
    """

    template_path = input_dir / 'manifest.h.tpl'
    output_path = output_dir / 'manifest.h'

    base_name = Name.from_snake_case("ROM_EXT")

    regions = []
    offsets = []
    current_offset_bytes = 0
    for field in fields:
        required_alignment_bits = field.get("alignment", 32)
        assert required_alignment_bits % 8 == 0
        required_alignment_bytes = required_alignment_bits // 8

        # The 8-byte two-step https://zinascii.com/2014/the-8-byte-two-step.html
        # This ends up aligning `current_offset_bytes` to `required_alignment_bytes`
        # that is greater than or equal to `current_offset_bytes`.
        current_offset_bytes = (current_offset_bytes + required_alignment_bytes - 1) \
                             & ~(required_alignment_bytes - 1)

        if field['type'] == "offset":
            offset_name = base_name + Name.from_snake_case(field['name'])
            offset = MemoryOffset(offset_name, current_offset_bytes)
            offsets.append((field['name'], offset))

        else:
            assert field['size'] % 8 == 0
            size_bytes = field['size'] // 8
            if field['type'] == "field":
                region_name = base_name + Name.from_snake_case(field['name'])
                region = MemoryRegion(region_name, current_offset_bytes,
                                      size_bytes)
                regions.append((field['name'], region))
            current_offset_bytes += size_bytes

    with template_path.open('r') as f:
        template = Template(f.read())

    header = template.render(regions=regions, offsets=offsets)

    with output_path.open('w') as f:
        f.write(header)

    print('Template sucessfuly written to {}.'.format(output_path))
def generate_defines(fields):
    """ Generates manifest defines.

    This produces two lists of tuples. One with a field name and the
    `MemoryRegion` object, and one with `MemoryOffset` object. Please see the
    description at the top for more information on the differences between these
    objects.
    """

    base_name = Name.from_snake_case("ROM_EXT")

    regions = []
    offsets = []
    current_offset_bytes = 0
    for field in fields:
        required_alignment_bits = field.get("alignment", 32)
        assert required_alignment_bits % 8 == 0
        required_alignment_bytes = required_alignment_bits // 8

        # The 8-byte two-step https://zinascii.com/2014/the-8-byte-two-step.html
        # This ends up aligning `current_offset_bytes` to `required_alignment_bytes`
        # that is greater than or equal to `current_offset_bytes`.
        current_offset_bytes = (current_offset_bytes + required_alignment_bytes - 1) \
            & ~(required_alignment_bytes - 1)

        if field['type'] == "offset":
            offset_name = base_name + Name.from_snake_case(field['name'])
            offset = MemoryOffset(offset_name, current_offset_bytes)
            offsets.append((field['name'], offset))

        else:
            assert field['size'] % 8 == 0
            size_bytes = field['size'] // 8
            if field['type'] == "field":
                region_name = base_name + Name.from_snake_case(field['name'])
                region = MemoryRegion(region_name, current_offset_bytes,
                                      size_bytes)
                regions.append((field['name'], region))
            current_offset_bytes += size_bytes

    return (regions, offsets)
Esempio n. 3
0
def generate_defines(fields, verbose=False):
    """ Generates manifest defines.

    This produces two lists of tuples. One with a field name and the
    `MemoryRegion` object, and one with `MemoryOffset` object. Please see the
    description at the top for more information on the differences between these
    objects.
    """
    def print_field_info(name, offset, size, alignment, required_alignment):
        if verbose:
            print("0x{:04x} - 0x{:04x}: {} (alignment: {} reqd: {})".format(
                offset, offset + size, name, alignment, required_alignment))

    def print_offset_info(name, offset, alignment, required_alignment):
        if verbose:
            print("       @ 0x{:04x}: {} (alignment: {} reqd: {})".format(
                offset, name, alignment, required_alignment))

    base_name = Name.from_snake_case("ROM_EXT")

    regions = []
    offsets = []
    current_offset_bytes = 0
    for field in fields:
        required_alignment_bits = field.get("alignment", 32)
        assert required_alignment_bits % 8 == 0
        required_alignment_bytes = required_alignment_bits // 8

        # The 8-byte two-step https://zinascii.com/2014/the-8-byte-two-step.html
        # This ends up aligning `new_offset_bytes` to `required_alignment_bytes`
        # that is greater than or equal to `current_offset_bytes`.
        new_offset_bytes = (current_offset_bytes + required_alignment_bytes - 1) \
            & ~(required_alignment_bytes - 1)

        if new_offset_bytes != current_offset_bytes and verbose:
            print("0x{:04x} - 0x{:04x}: - (realignment) -".format(
                current_offset_bytes, new_offset_bytes))

        current_offset_bytes = new_offset_bytes
        # This works becuase e.g. 6 is `0b0...00110` and ~(6-1) is `0b1..11010`,
        # giving a result of `0b0...010`, or 2.
        current_offset_alignment = current_offset_bytes \
            & ~(current_offset_bytes - 1)

        if field['type'] == "offset":
            offset_name = base_name + Name.from_snake_case(field['name'])
            offset = MemoryOffset(offset_name, current_offset_bytes)
            offsets.append((field['name'], offset))

            print_offset_info(field['name'], current_offset_bytes,
                              current_offset_alignment,
                              required_alignment_bytes)

        else:
            assert field['size'] % 8 == 0
            size_bytes = field['size'] // 8
            if field['type'] == "field":
                region_name = base_name + Name.from_snake_case(field['name'])
                region = MemoryRegion(region_name, current_offset_bytes,
                                      size_bytes)
                regions.append((field['name'], region))

                print_field_info(field['name'], current_offset_bytes,
                                 size_bytes, current_offset_alignment,
                                 required_alignment_bytes)
            elif field['type'] == 'reserved' and verbose:
                print_field_info('- reserved -', current_offset_bytes,
                                 size_bytes, current_offset_alignment, 0)

            current_offset_bytes += size_bytes

    return (regions, offsets)