Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#
# This file is part of LiteX.
#
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
import math
import json
import struct
from migen import *
# Helpers ----------------------------------------------------------------------------------------
def _get_region_base(base):
if isinstance(base, str):
return int(base, 16)
return int(base)
def get_mem_regions(filename_or_regions, offset):
if isinstance(filename_or_regions, dict):
regions = filename_or_regions
else:
filename = filename_or_regions
if not os.path.isfile(filename):
raise OSError(f"Unable to find {filename} memory content file.")
_, ext = os.path.splitext(filename)
if ext == ".json":
with open(filename, "r") as f:
_regions = json.load(f)
# .json
regions = dict()
for k, v in _regions.items():
regions[os.path.join(os.path.dirname(filename), k)] = v
else:
regions = {filename: f"{offset:08x}"}
return regions
def get_mem_data(filename_or_regions, data_width=32, endianness="big", mem_size=None, offset=0):
if data_width % 32:
raise ValueError("data_width must be a multiple of 32.")
if endianness not in ["big", "little"]:
raise ValueError("endianness must be big or little.")
# Return empty list if no filename or regions.
if filename_or_regions is None:
return []
# Create memory regions.
regions = get_mem_regions(filename_or_regions, offset)
# Determine data_size.
bytes_per_data = data_width//8
data_size = 0
data_regions = []
for filename, base in regions.items():
if not os.path.isfile(filename):
raise OSError(f"Unable to find {filename} memory content file.")
base = _get_region_base(base)
size = os.path.getsize(filename)
if base < offset:
raise ValueError("file base address is below offset: 0x{:08x} < 0x{:08x}".format(base, offset))
if (base - offset) % bytes_per_data:
raise ValueError(
"file base address is not aligned to data width: {} at 0x{:08x} ({}-byte alignment).".format(
filename, base, bytes_per_data))
for other_filename, other_base, other_size in data_regions:
if base < (other_base + other_size) and other_base < (base + size):
raise ValueError(
"memory data files overlap: {} at 0x{:08x}-0x{:08x} and {} at 0x{:08x}-0x{:08x}.".format(
other_filename, other_base, other_base + other_size,
filename, base, base + size))
data_regions.append((filename, base, size))
data_size = max(base + size - offset, data_size)
if data_size <= 0:
raise ValueError("memory data is empty.")
if mem_size is not None:
if data_size > mem_size:
raise ValueError("file is too big: {}/{} bytes".format(data_size, mem_size))
# Fill data.
data = [0]*math.ceil(data_size/bytes_per_data)
for filename, base, _ in data_regions:
with open(filename, "rb") as f:
i = 0
while True:
w = f.read(bytes_per_data)
if not w:
break
if len(w) != bytes_per_data:
for _ in range(len(w), bytes_per_data):
w += b'\x00'
unpack_order = {
"little": "<I",
"big": ">I"
}[endianness]
data[(base - offset)//bytes_per_data + i] = 0
for filled_data_width in range(0, data_width, 32):
cur_byte = filled_data_width//8
data[(base - offset)//bytes_per_data + i] |= (struct.unpack(unpack_order, w[cur_byte:cur_byte+4])[0] << filled_data_width)
i += 1
return data
def get_boot_address(filename_or_regions, offset=0):
# Create memory regions.
regions = dict(get_mem_regions(filename_or_regions, offset))
# Boot on last region.
filename, base = regions.popitem()
return _get_region_base(base)
4443d3b3aThis file is pinned to the selected release. Download the original to open it in your design tool.