seL4/tools/hardware/memory.py
Simon Shields 75f2c54b42 tools: rewrite hardware_gen.py
This is almost a complete rewrite from the old hardware_gen.py.

It separates the 'parse DT' stage from the 'generate output'
devices more strictly, and is hopefully easier to understand and
easier to extend.

We also no longer generate the 'devices' list (in YAML)
or the dev_p_regs array (in C), as the kernel will implicitly
expose all non-RAM untypeds as devices.
2019-11-12 16:18:33 +11:00

111 lines
3.9 KiB
Python

#
# Copyright 2019, Data61
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
# ABN 41 687 119 230.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(DATA61_GPL)
#
import functools
import hardware.utils as utils
@functools.total_ordering
class Region:
''' Represents a region of memory. '''
def __init__(self, base: int, size: int, owner: 'WrappedNode'):
self.base = base
self.size = size
self.owner = owner
@staticmethod
def clone(other):
ret = Region(other.base, other.size)
return ret
def __repr__(self):
return 'Region(base=0x{:x},size=0x{:x})'.format(self.base, self.size)
def __eq__(self, other):
return self.base == other.base and self.size == other.size
def __ne__(self, other):
# Needed only for py2.
return not self.__eq__(other)
def __gt__(self, other):
return self.base > other.base
def __hash__(self):
return hash((self.base, self.size))
@staticmethod
def from_range(start, end, owner):
''' create a region from a start/end rather than start/size '''
ret = Region(start, end - start, owner)
return ret
def overlaps(self, other):
''' returns True if this region overlaps the given region '''
# either our base is first, and to overlap our end must be > other.base
if self.base <= other.base and (self.base + self.size) > other.base:
return True
# or other.base is first, and to overlap other's end must be > self.base
elif other.base <= self.base and (other.base + other.size) > self.base:
return True
return False
def reserve(self, excluded):
''' returns an array of regions that represent this region
minus the excluded range '''
if not self.overlaps(excluded):
return [Region(self.base, self.size, self.owner)]
ret = []
if self.base < excluded.base:
# the first region is from our base to excluded.base
ret.append(Region.from_range(self.base, excluded.base, self.owner))
# skip the region from excluded.base - excluded.base + excluded.size
# if there's anything left, add it.
if (excluded.base + excluded.size) < (self.base + self.size):
ret.append(Region.from_range(excluded.base + excluded.size,
self.base + self.size, self.owner))
else: # self.base >= excluded.base
# we skip the first chunk
# we add what's left after the current chunk.
if (self.base + self.size) > (excluded.base + excluded.size):
ret.append(Region.from_range(excluded.base + excluded.size,
self.base + self.size, self.owner))
return ret
def align_base(self, align_bits):
''' align this region up to a given number of bits '''
new_base = utils.align_up(self.base, align_bits)
diff = new_base - self.base
new_size = self.size - diff
new = Region(new_base, new_size, self.owner)
return new
def align_size(self, align_bits):
''' align this region's size to a given number of bits.
will move the base address down and the region's size
up '''
new_base = utils.align_down(self.base, align_bits)
new_size = utils.align_up(self.size, align_bits)
new = Region(new_base, new_size, self.owner)
return new
def make_chunks(self, chunksz):
base = self.base
size = self.size
ret = []
while size > 0:
ret.append(Region(base, min(size, chunksz), self.owner))
base += chunksz
size -= chunksz
return ret