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
|
||||
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):
|
||||
if io_region: # 2019-10-30: io_region retro-compatibility
|
||||
deprecated_warning(": io_region replaced by type=\"io\".")
|
||||
type = "io"
|
||||
length = 2**log2_int(length, False)
|
||||
if "io" in 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],
|
||||
))
|
||||
assert name in self.mem_map.keys()
|
||||
self.add_mem_region(name, length, type)
|
||||
|
||||
def register_mem(self, name, address, interface, size=0x10000000):
|
||||
self.add_wb_slave(address, interface, size)
|
||||
|
|
Loading…
Reference in New Issue