soc_core: add new alloc_mem/add_mem_region to allow automatic allocation of memory regions
With add_memory_region, user needs to provide the memory origin, which should not be needed since could be retrieved from mem_map and prevent automatic allocation which is already possible for csr and interrupts. New add_mem_region method now allows both: defining the memory origin in mem_map (which will then be used) or let the SoC builder automatically find and allocate a memory region.
This commit is contained in:
parent
eae0e00496
commit
53bc18cc3f
|
@ -403,23 +403,68 @@ class SoCCore(Module):
|
||||||
i += 1
|
i += 1
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def alloc_mem_region(self, name, length, type):
|
||||||
|
# Use type to limit search regions
|
||||||
|
search_regions = []
|
||||||
|
if "io" in type:
|
||||||
|
for _origin, _length in self.soc_io_regions.items():
|
||||||
|
search_regions.append(SoCMemRegion(origin=_origin, length=_length, type=type))
|
||||||
|
else:
|
||||||
|
search_regions.append(SoCMemRegion(origin=0x00000000, length=0x80000000, type=type))
|
||||||
|
# Iterate over search_regions and origin to find a candidate region
|
||||||
|
for search_region in search_regions:
|
||||||
|
origin = search_region.origin
|
||||||
|
while (origin + length) < (search_region.origin + search_region.length):
|
||||||
|
# Create a candidate mem region.
|
||||||
|
candidate_region = SoCMemRegion(origin=origin, length=length, type=type)
|
||||||
|
candidate_overlap = False
|
||||||
|
# Check candidate does not overlap with allocated mem regions.
|
||||||
|
for _, allocated_region in self.mem_regions.items():
|
||||||
|
if self.check_regions_overlap({"0": allocated_region, "1": candidate_region}) is not None:
|
||||||
|
origin = allocated_region.origin + allocated_region.length
|
||||||
|
candidate_overlap = True
|
||||||
|
break
|
||||||
|
if not candidate_overlap:
|
||||||
|
# If no overlap, the candidate is selected.
|
||||||
|
#print("{} region allocated at: {:08x}".format(name, candidate_region.origin))
|
||||||
|
return candidate_region
|
||||||
|
msg = "Not enough addressable memory space to allocate mem region {} of length 0x{:0x}".format(
|
||||||
|
name, length)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
def add_mem_region(self, name, length, type="cached"):
|
||||||
|
# Check name conflicts.
|
||||||
|
if name in self.mem_regions.keys():
|
||||||
|
raise ValueError("Memory region conflict, {} name already used".format(name))
|
||||||
|
# Round length to next power of 2.
|
||||||
|
length = 2**log2_int(length, False)
|
||||||
|
# Get mem origin; if not defined in mem_map, allocate a new mem region, else use mem_map
|
||||||
|
# mapping and check for type/overlap conflicts.
|
||||||
|
origin = self.mem_map.get(name, None)
|
||||||
|
if origin is None:
|
||||||
|
self.mem_regions[name] = self.alloc_mem_region(name, length, type)
|
||||||
|
else:
|
||||||
|
# Check type
|
||||||
|
if "io" in type:
|
||||||
|
self.check_io_region(name,origin, length)
|
||||||
|
# Add region
|
||||||
|
self.mem_regions[name] = SoCMemRegion(origin, length, type)
|
||||||
|
# Check overlap
|
||||||
|
overlap = self.check_regions_overlap(self.mem_regions)
|
||||||
|
if overlap is not None:
|
||||||
|
o0, o1 = overlap[0], overlap[1]
|
||||||
|
raise ValueError("Memory region conflict between {} ({}) and {} ({})".format(
|
||||||
|
o0, self.mem_regions[o0],
|
||||||
|
o1, self.mem_regions[o1],
|
||||||
|
))
|
||||||
|
|
||||||
|
# FIXME: add deprecated warning?
|
||||||
def add_memory_region(self, name, origin, length, type="cached", io_region=False):
|
def add_memory_region(self, name, origin, length, type="cached", io_region=False):
|
||||||
if io_region: # 2019-10-30: io_region retro-compatibility
|
if io_region: # 2019-10-30: io_region retro-compatibility
|
||||||
deprecated_warning(": io_region replaced by type=\"io\".")
|
deprecated_warning(": io_region replaced by type=\"io\".")
|
||||||
type = "io"
|
type = "io"
|
||||||
length = 2**log2_int(length, False)
|
assert name in self.mem_map.keys()
|
||||||
if "io" in type:
|
self.add_mem_region(name, length, type)
|
||||||
self.check_io_region(name, origin, length)
|
|
||||||
if name in self.mem_regions.keys():
|
|
||||||
raise ValueError("Memory region conflict, {} name already used".format(name))
|
|
||||||
self.mem_regions[name] = SoCMemRegion(origin, length, type)
|
|
||||||
overlap = self.check_regions_overlap(self.mem_regions)
|
|
||||||
if overlap is not None:
|
|
||||||
o0, o1 = overlap[0], overlap[1]
|
|
||||||
raise ValueError("Memory region conflict between {} ({}) and {} ({})".format(
|
|
||||||
o0, self.mem_regions[o0],
|
|
||||||
o1, self.mem_regions[o1],
|
|
||||||
))
|
|
||||||
|
|
||||||
def register_mem(self, name, address, interface, size=0x10000000):
|
def register_mem(self, name, address, interface, size=0x10000000):
|
||||||
self.add_wb_slave(address, interface, size)
|
self.add_wb_slave(address, interface, size)
|
||||||
|
|
Loading…
Reference in New Issue