Source code for luna_soc.util.readbin

import logging, math, os, struct

[docs] 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): # TODO This is cursed: # # * SoC definitions occur in the SoC constructor. # * The SRAMPeripheral 'init' parameter requires a list of int rather than a filename. # * This causes instantiation of the SoC to fail even if the goal # is only to introspect the design in order to generate the 'init' file! # # A better solution will be to go back to using our own fork of SRAMPeripheral # and extends with the option to take a filename for the 'init' parameter and which # which is only resolved to the file data at elaboration time. logging.warn(f"Memory image '{filename}' has not yet been generated.") return None #raise FileNotFoundError(f"Unable to find '{filename}' memory content file.") _, ext = os.path.splitext(filename) if ext == ".json": f = open(filename, "r") _regions = json.load(f) # .json regions = dict() for k, v in _regions.items(): regions[os.path.join(os.path.dirname(filename), k)] = v f.close() else: regions = {filename: f"{offset:08x}"} return regions
[docs] def get_mem_data(filename_or_regions, data_width=32, endianness="big", mem_size=None, offset=0): assert data_width % 32 == 0 assert endianness in ["big", "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) if regions is None: return None # Determine data_size. data_size = 0 for filename, base in regions.items(): if not os.path.isfile(filename): raise OSError(f"Unable to find '{filename}' memory content file.") data_size = max(int(base, 16) + os.path.getsize(filename) - offset, data_size) assert data_size > 0 if mem_size is not None: assert data_size < mem_size, ( "file is too big: {}/{} bytes".format( data_size, mem_size)) # Fill data. bytes_per_data = data_width//8 data = [0]*math.ceil(data_size/bytes_per_data) for filename, base in regions.items(): base = int(base, 16) 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
[docs] def get_boot_address(filename_or_regions, offset=0): # Create memory regions. regions = get_mem_regions(filename_or_regions, offset) # Boot on last region. filename, base = regions.popitem() return int(base, 0)