diff --git a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson index 226faefaad6a09..98479843ddb2c6 100644 --- a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson +++ b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson @@ -4082,6 +4082,10 @@ hart: 0x30600000 } } + cpu_visible: + [ + ram + ] memory: { ram: @@ -4277,6 +4281,12 @@ soc_dbg: 0x00000000 } } + cpu_not_visible: + [ + mem + regs + dbg + ] param_decl: { SecVolatileRawUnlockEn: top_pkg::SecVolatileRawUnlockEn @@ -7024,6 +7034,10 @@ soc_mbx: 0x01465000 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -7160,6 +7174,10 @@ soc_mbx: 0x01465100 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -7296,6 +7314,10 @@ soc_mbx: 0x01465200 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -7432,6 +7454,10 @@ soc_mbx: 0x01465300 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -7568,6 +7594,10 @@ soc_mbx: 0x01465400 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -7976,6 +8006,10 @@ soc_dbg: 0x1000 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -8112,6 +8146,10 @@ soc_mbx: 0x01460100 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra @@ -8248,6 +8286,10 @@ soc_mbx: 0x01460200 } } + cpu_not_visible: + [ + soc + ] clock_connections: { clk_i: clkmgr_aon_clocks.clk_main_infra diff --git a/hw/top_darjeeling/data/top_darjeeling.hjson b/hw/top_darjeeling/data/top_darjeeling.hjson index ec2c11cc675a83..b02d71c34b4db3 100644 --- a/hw/top_darjeeling/data/top_darjeeling.hjson +++ b/hw/top_darjeeling/data/top_darjeeling.hjson @@ -553,6 +553,7 @@ regs: {hart: "0x30500000"}, ram: {hart: "0x30600000"}, }, + cpu_visible: ['ram'] // Memory regions must be associated with a dedicated // TL-UL device interface. memory: { @@ -577,6 +578,7 @@ regs: {hart: "0x21200000"}, dbg: {soc_dbg: "0x00000000"}, }, + cpu_not_visible: ["mem", "regs", "dbg"] param_decl: { // NOTE THAT THIS IS A FEATURE FOR TEST CHIPS ONLY TO MITIGATE // THE RISK OF A BROKEN OTP MACRO. THIS WILL BE DISABLED FOR @@ -810,6 +812,7 @@ core: {hart: "0x22000000"}, soc: {soc_mbx: "0x01465000"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx1", type: "mbx", @@ -820,6 +823,7 @@ core: {hart: "0x22000100"}, soc: {soc_mbx: "0x01465100"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx2", type: "mbx", @@ -830,6 +834,7 @@ core: {hart: "0x22000200"}, soc: {soc_mbx: "0x01465200"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx3", type: "mbx", @@ -840,6 +845,7 @@ core: {hart: "0x22000300"}, soc: {soc_mbx: "0x01465300"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx4", type: "mbx", @@ -850,6 +856,7 @@ core: {hart: "0x22000400"}, soc: {soc_mbx: "0x01465400"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx5", type: "mbx", @@ -880,6 +887,7 @@ core: {hart: "0x22000800"}, soc: {soc_dbg: "0x1000"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx_pcie0", type: "mbx", @@ -890,6 +898,7 @@ core: {hart: "0x22040000"}, soc: {soc_mbx: "0x01460100"}, }, + cpu_not_visible: ['soc'] }, { name: "mbx_pcie1", type: "mbx", @@ -900,6 +909,7 @@ core: {hart: "0x22040100"}, soc: {soc_mbx: "0x01460200"}, }, + cpu_not_visible: ['soc'] }, { name: "rv_core_ibex", type: "rv_core_ibex", diff --git a/hw/top_darjeeling/sw/autogen/chip/top_darjeeling.rs b/hw/top_darjeeling/sw/autogen/chip/top_darjeeling.rs index 2798bf4982658f..a5de689108de83 100644 --- a/hw/top_darjeeling/sw/autogen/chip/top_darjeeling.rs +++ b/hw/top_darjeeling/sw/autogen/chip/top_darjeeling.rs @@ -2748,4 +2748,4 @@ pub enum TopDarjeelingHintableClocks { /// configuration space, i.e. ROM, main SRAM, and flash are excluded but /// retention SRAM, spi_device memory, or usbdev memory are included. pub const TOP_DARJEELING_MMIO_BASE_ADDR: usize = 0x21100000; -pub const TOP_DARJEELING_MMIO_SIZE_BYTES: usize = 0xF400020; +pub const TOP_DARJEELING_MMIO_SIZE_BYTES: usize = 0xF501000; diff --git a/hw/top_darjeeling/sw/autogen/chip/top_darjeeling_memory.rs b/hw/top_darjeeling/sw/autogen/chip/top_darjeeling_memory.rs index 1216ec9816016f..c2cabd49b63f45 100644 --- a/hw/top_darjeeling/sw/autogen/chip/top_darjeeling_memory.rs +++ b/hw/top_darjeeling/sw/autogen/chip/top_darjeeling_memory.rs @@ -737,4 +737,4 @@ pub const TOP_DARJEELING_RV_CORE_IBEX_CFG_SIZE_BYTES: usize = 0x800; /// configuration space, i.e. ROM, main SRAM, and flash are excluded but /// retention SRAM, spi_device memory, or usbdev memory are included. pub const TOP_DARJEELING_MMIO_BASE_ADDR: usize = 0x21100000; -pub const TOP_DARJEELING_MMIO_SIZE_BYTES: usize = 0xF400020; +pub const TOP_DARJEELING_MMIO_SIZE_BYTES: usize = 0xF501000; diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index c82d7060678c78..afbcbd2012f34a 100644 --- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson @@ -4814,6 +4814,10 @@ hart: 0x40600000 } } + cpu_visible: + [ + ram + ] memory: { ram: @@ -5462,6 +5466,11 @@ hart: 0x41200000 } } + cpu_not_visible: + [ + mem + regs + ] generate_dif: false clock_connections: { diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson index fe30cc4ed34803..43391a31ce21dc 100644 --- a/hw/top_earlgrey/data/top_earlgrey.hjson +++ b/hw/top_earlgrey/data/top_earlgrey.hjson @@ -649,6 +649,7 @@ regs: {hart: "0x40500000"}, ram: {hart: "0x40600000"}, } + cpu_visible: ["ram"] // Memory regions must be associated with a dedicated // TL-UL device interface. memory: { @@ -705,6 +706,7 @@ mem: {hart: "0x00010000"}, regs: {hart: "0x41200000"} }, + cpu_not_visible: ["mem", "regs"] generate_dif: "False" }, { name: "rv_plic", diff --git a/util/topgen/c.py b/util/topgen/c.py index ad7f1c42f49fa6..f7b910f4ecd656 100644 --- a/util/topgen/c.py +++ b/util/topgen/c.py @@ -10,32 +10,11 @@ from mako.template import Template from reggen.ip_block import IpBlock -from .lib import Name, get_base_and_size +from .lib import Name, get_base_and_size, MemoryRegion, init_mmio_region C_FILE_EXTENSIONS = (".c", ".h", ".cc", ".inc") -class MemoryRegion(object): - def __init__(self, name: Name, base_addr: int, size_bytes: int): - assert isinstance(base_addr, int) - self.name = name - self.base_addr = base_addr - self.size_bytes = size_bytes - self.size_words = (size_bytes + 3) // 4 - - def base_addr_name(self): - return self.name + Name(["base", "addr"]) - - def offset_name(self): - return self.name + Name(["offset"]) - - def size_bytes_name(self): - return self.name + Name(["size", "bytes"]) - - def size_words_name(self): - return self.name + Name(["size", "words"]) - - class CEnum(object): def __init__(self, name): self.name = name @@ -123,7 +102,7 @@ def __init__(self, top_info, name_to_block: Dict[str, IpBlock]): self._init_rstmgr_sw_rsts() self._init_pwrmgr_reset_requests() self._init_clkmgr_clocks() - self._init_mmio_region() + self.mmio = init_mmio_region(self.top, self._top_name, self.memories(), self.devices()) def devices(self) -> List[Tuple[Tuple[str, Optional[str]], MemoryRegion]]: '''Return a list of MemoryRegion objects for devices on the bus @@ -510,30 +489,3 @@ def _init_clkmgr_clocks(self): self.clkmgr_gateable_clocks = gateable_clocks self.clkmgr_hintable_clocks = hintable_clocks - - def _init_mmio_region(self): - """ - Computes the bounds of the MMIO region. - - MMIO region excludes any memory that is separate from the module configuration - space, i.e. ROM, main SRAM, and flash are excluded but retention SRAM, - spi_device memory, or usbdev memory are included. - """ - memories = [region.base_addr for (_, region) in self.memories()] - # TODO(#14345): Remove the hardcoded "rv_dm" name check below. - # TODO: we need a cleaner way to define which buses are visible - # by the CPU and which ones are not. For now, exclude every - # interface with the name `dbg`, since that is attached to the - # debug bus which is not connected to the CPU LSU. - regions = [ - region for ((dev_name, if_name), region) in self.devices() - if (dev_name == "sram_ctrl_ret_aon" and if_name == 'ram') or - (region.base_addr not in memories and dev_name != "rv_dm" and - (if_name is None or if_name != 'dbg')) - ] - # Note: The memory interface of the retention RAM is in the MMIO address space, - # which we prefer since it reduces the number of ePMP regions we need. - mmio = range(min([r.base_addr for r in regions]), - max([r.base_addr + r.size_bytes for r in regions])) - self.mmio = MemoryRegion(self._top_name + Name(["mmio"]), mmio.start, - mmio.stop - mmio.start) diff --git a/util/topgen/lib.py b/util/topgen/lib.py index 9286ea806468ef..f22ab45bd0530c 100644 --- a/util/topgen/lib.py +++ b/util/topgen/lib.py @@ -85,6 +85,27 @@ def remove_part(self, part_to_remove: str) -> "Name": return Name([p for p in self.parts if p != part_to_remove]) +class MemoryRegion(object): + def __init__(self, name: Name, base_addr: int, size_bytes: int): + assert isinstance(base_addr, int) + self.name = name + self.base_addr = base_addr + self.size_bytes = size_bytes + self.size_words = (size_bytes + 3) // 4 + + def base_addr_name(self): + return self.name + Name(["base", "addr"]) + + def offset_name(self): + return self.name + Name(["offset"]) + + def size_bytes_name(self): + return self.name + Name(["size", "bytes"]) + + def size_words_name(self): + return self.name + Name(["size", "words"]) + + def is_ipcfg(ip: Path) -> bool: # return bool log.info("IP Path: %s" % repr(ip)) ip_name = ip.parents[1].name @@ -566,3 +587,34 @@ def is_lc_ctrl(modules): return True return False + + +def init_mmio_region(top, top_name, memories, devices): + """ + Computes the bounds of the MMIO region. + + MMIO region excludes any memory that is separate from the module configuration + space, i.e. ROM, main SRAM, and flash are excluded but retention SRAM, + spi_device memory, or usbdev memory are included. + """ + memories = [region.base_addr for (_, region) in memories] + regions = [] + for ((dev_name, if_name), region) in devices: + module = get_module_by_name(top, dev_name) + + # Ignore interface if explicitly not visible to the CPU + if 'cpu_not_visible' in module and if_name in module['cpu_not_visible']: + continue + # Include interface if explicitly visible to the CPU + if (('cpu_visible' in module and if_name in module['cpu_visible']) or + region.base_addr not in memories): + regions.append(region) + + if len(regions): + # Note: The memory interface of the retention RAM is in the MMIO address space, + # which we prefer since it reduces the number of ePMP regions we need. + mmio = range(min([r.base_addr for r in regions]), + max([r.base_addr + r.size_bytes for r in regions])) + return MemoryRegion(top_name + Name(["mmio"]), mmio.start, mmio.stop - mmio.start) + else: + return None \ No newline at end of file diff --git a/util/topgen/rust.py b/util/topgen/rust.py index 6fe1e6e0fc554b..3d9570e0aa57c1 100644 --- a/util/topgen/rust.py +++ b/util/topgen/rust.py @@ -9,32 +9,11 @@ from mako.template import Template from reggen.ip_block import IpBlock -from .lib import Name, get_base_and_size +from .lib import Name, get_base_and_size, MemoryRegion, init_mmio_region RUST_FILE_EXTENSIONS = (".rs") -class MemoryRegion(object): - def __init__(self, name: Name, base_addr: int, size_bytes: int): - assert isinstance(base_addr, int) - self.name = name - self.base_addr = base_addr - self.size_bytes = size_bytes - self.size_words = (size_bytes + 3) // 4 - - def base_addr_name(self): - return self.name + Name(["base", "addr"]) - - def offset_name(self): - return self.name + Name(["offset"]) - - def size_bytes_name(self): - return self.name + Name(["size", "bytes"]) - - def size_words_name(self): - return self.name + Name(["size", "words"]) - - class RustEnum(object): def __init__(self, top_name, name, repr_type=None): self.name = top_name + name @@ -214,7 +193,7 @@ def __init__(self, top_info, name_to_block: Dict[str, IpBlock], version_stamp: D self._init_rstmgr_sw_rsts() self._init_pwrmgr_reset_requests() self._init_clkmgr_clocks() - self._init_mmio_region() + self.mmio = init_mmio_region(self.top, self._top_name, self.memories(), self.devices()) def devices(self) -> List[Tuple[Tuple[str, Optional[str]], MemoryRegion]]: '''Return a list of MemoryRegion objects for devices on the bus @@ -597,29 +576,3 @@ def _init_clkmgr_clocks(self): self.clkmgr_gateable_clocks = gateable_clocks self.clkmgr_hintable_clocks = hintable_clocks - - def _init_mmio_region(self): - """ - Computes the bounds of the MMIO region. - - MMIO region excludes any memory that is separate from the module configuration - space, i.e. ROM, main SRAM, and flash are excluded but retention SRAM, - spi_device memory, or usbdev memory are included. - """ - memories = [region.base_addr for (_, region) in self.memories()] - # TODO(#14345): Remove the hardcoded "rv_dm" name check below. - # TODO: we need a cleaner way to define which buses are visible - # by the CPU and which ones are not. For now, exclude every - # interface with the name `dbg`, since that is attached to the - # debug bus which is not connected to the CPU LSU. - regions = [ - region for ((dev_name, if_name), region) in self.devices() - if region.base_addr not in memories and dev_name != "rv_dm" and - (if_name is None or if_name != 'dbg') - ] - # Note: The memory interface of the retention RAM is in the MMIO address space, - # which we prefer since it reduces the number of ePMP regions we need. - mmio = range(min([r.base_addr for r in regions]), - max([r.base_addr + r.size_bytes for r in regions])) - self.mmio = MemoryRegion(self._top_name + Name(["mmio"]), mmio.start, - mmio.stop - mmio.start) diff --git a/util/topgen/templates/toplevel.h.tpl b/util/topgen/templates/toplevel.h.tpl index 74b85614cd201b..cec9e48e33ae23 100644 --- a/util/topgen/templates/toplevel.h.tpl +++ b/util/topgen/templates/toplevel.h.tpl @@ -234,6 +234,7 @@ ${helper.clkmgr_gateable_clocks.render()} */ ${helper.clkmgr_hintable_clocks.render()} +% if helper.mmio: /** * MMIO Region * @@ -243,6 +244,7 @@ ${helper.clkmgr_hintable_clocks.render()} */ #define ${helper.mmio.base_addr_name().as_c_define()} ${"0x{:X}u".format(helper.mmio.base_addr)} #define ${helper.mmio.size_bytes_name().as_c_define()} ${"0x{:X}u".format(helper.mmio.size_bytes)} +% endif // Header Extern Guard #ifdef __cplusplus diff --git a/util/topgen/templates/toplevel.rs.tpl b/util/topgen/templates/toplevel.rs.tpl index 9971eead9efae6..72686362791fef 100644 --- a/util/topgen/templates/toplevel.rs.tpl +++ b/util/topgen/templates/toplevel.rs.tpl @@ -171,6 +171,7 @@ ${helper.clkmgr_gateable_clocks.render()} /// but the clock manager is in control of whether the clock actually is stopped. ${helper.clkmgr_hintable_clocks.render()} +% if helper.mmio: /// MMIO Region /// /// MMIO region excludes any memory that is separate from the module @@ -178,3 +179,4 @@ ${helper.clkmgr_hintable_clocks.render()} /// retention SRAM, spi_device memory, or usbdev memory are included. pub const ${helper.mmio.base_addr_name().as_rust_const()}: usize = ${"0x{:X}".format(helper.mmio.base_addr)}; pub const ${helper.mmio.size_bytes_name().as_rust_const()}: usize = ${"0x{:X}".format(helper.mmio.size_bytes)}; +% endif diff --git a/util/topgen/templates/toplevel_memory.h.tpl b/util/topgen/templates/toplevel_memory.h.tpl index bd3c73e1117dd0..5442567324abd5 100644 --- a/util/topgen/templates/toplevel_memory.h.tpl +++ b/util/topgen/templates/toplevel_memory.h.tpl @@ -100,6 +100,7 @@ #define ${size_bytes_name} ${hex_size_bytes} % endfor +% if helper.mmio: /** * MMIO Region * @@ -109,6 +110,7 @@ */ #define ${helper.mmio.base_addr_name().as_c_define()} ${"0x{:X}".format(helper.mmio.base_addr)} #define ${helper.mmio.size_bytes_name().as_c_define()} ${"0x{:X}".format(helper.mmio.size_bytes)} +% endif #endif // __ASSEMBLER__ diff --git a/util/topgen/templates/toplevel_memory.rs.tpl b/util/topgen/templates/toplevel_memory.rs.tpl index 0bf6e3097a1890..e2f05c01a8a23a 100644 --- a/util/topgen/templates/toplevel_memory.rs.tpl +++ b/util/topgen/templates/toplevel_memory.rs.tpl @@ -70,6 +70,7 @@ pub const ${base_addr_name}: usize = ${hex_base_addr}; pub const ${size_bytes_name}: usize = ${hex_size_bytes}; % endfor +% if helper.mmio: /// MMIO Region /// /// MMIO region excludes any memory that is separate from the module @@ -77,3 +78,4 @@ pub const ${size_bytes_name}: usize = ${hex_size_bytes}; /// retention SRAM, spi_device memory, or usbdev memory are included. pub const ${helper.mmio.base_addr_name().as_c_define()}: usize = ${"0x{:X}".format(helper.mmio.base_addr)}; pub const ${helper.mmio.size_bytes_name().as_c_define()}: usize = ${"0x{:X}".format(helper.mmio.size_bytes)}; +% endif diff --git a/util/topgen/validate.py b/util/topgen/validate.py index da214c72573209..43bc1c91f8a698 100644 --- a/util/topgen/validate.py +++ b/util/topgen/validate.py @@ -193,6 +193,8 @@ 'domain': ['l', 'optional list of power domains, defaults to Domain0'], 'clock_reset_export': ['l', 'optional list with prefixes for exported ' 'clocks and resets at the chip level'], + 'cpu_visible': ['list', 'List of address spaces visible to the CPU'], + 'cpu_not_visible': ['list', 'List of address spaces not visible to the CPU'], 'attr': ['s', 'optional attribute indicating whether the IP is ' '"templated" or "reggen_only"'], 'base_addr': ['g', 'dict of address space mapped to the corresponding '