genparams.py
1 from __future__ import annotations 2 3 from amaranth.utils import ceil_log2, exact_log2 4 5 from coreblocks.arch.isa import ISA, gen_isa_string 6 from .icache_params import ICacheParameters 7 from .vmem_params import VirtualMemoryParameters 8 from .fu_params import extensions_supported 9 from ..peripherals.wishbone import WishboneParameters 10 from transactron.utils import DependentCache 11 12 from typing import TYPE_CHECKING 13 14 if TYPE_CHECKING: 15 from .configurations import CoreConfiguration 16 17 __all__ = ["GenParams"] 18 19 20 class GenParams(DependentCache): 21 def __init__(self, cfg: CoreConfiguration): 22 super().__init__() 23 24 self.func_units_config = cfg.func_units_config 25 26 ext_partial, ext_full = extensions_supported(self.func_units_config, cfg.embedded, cfg.compressed, cfg.zcb) 27 extensions = ext_partial if cfg.allow_partial_extensions else ext_full 28 if not cfg.allow_partial_extensions and ext_partial != ext_full: 29 raise RuntimeError(f"Extensions {ext_partial & ~ext_full!r} are only partially supported") 30 31 extensions |= cfg._implied_extensions 32 self.isa_str = gen_isa_string(extensions, cfg.xlen) 33 34 self.isa = ISA(self.isa_str) 35 36 self.pma = cfg.pma 37 38 bytes_in_word = self.isa.xlen // 8 39 bytes_in_word_log = exact_log2(bytes_in_word) 40 41 max_phys_addr_bits = VirtualMemoryParameters.max_physical_address_bits(cfg.xlen, cfg.supported_vm_schemes) 42 self.phys_addr_bits = cfg.phys_addr_bits if cfg.phys_addr_bits is not None else max_phys_addr_bits 43 if self.phys_addr_bits < bytes_in_word_log: 44 raise ValueError( 45 f"Physical address width ({self.phys_addr_bits}) " f"must be at least {bytes_in_word_log} bits" 46 ) 47 if self.phys_addr_bits > max_phys_addr_bits: 48 raise ValueError( 49 "Physical address width " 50 f"({self.phys_addr_bits}) exceeds maximum {max_phys_addr_bits} " 51 f"bits for XLEN={cfg.xlen}" 52 ) 53 54 self.wb_params = WishboneParameters( 55 data_width=self.isa.xlen, 56 addr_width=self.phys_addr_bits - bytes_in_word_log, 57 ) 58 59 self.vmem_params = VirtualMemoryParameters( 60 xlen=cfg.xlen, 61 supervisor_mode=cfg.supervisor_mode, 62 asidlen=cfg.asidlen, 63 supported_schemes=cfg.supported_vm_schemes, 64 ) 65 66 self.icache_params = ICacheParameters( 67 addr_width=self.phys_addr_bits, 68 word_width=self.isa.xlen, 69 fetch_block_bytes_log=cfg.fetch_block_bytes_log, 70 num_of_ways=cfg.icache_ways, 71 num_of_sets_bits=cfg.icache_sets_bits, 72 line_bytes_log=cfg.icache_line_bytes_log, 73 enable=cfg.icache_enable, 74 ) 75 76 self.debug_signals_enabled = cfg.debug_signals 77 78 # Verification temporally disabled 79 # if not optypes_required_by_extensions(self.isa.extensions) <= optypes_supported(func_units_config): 80 # raise Exception(f"Functional unit configuration do not support all extension required by{isa_str}") 81 82 self.max_rs_entries = 1 83 84 for block in self.func_units_config: 85 self.max_rs_entries = max(self.max_rs_entries, block.get_rs_entry_count()) 86 87 self.rs_number_bits = ceil_log2(len(self.func_units_config)) 88 89 self.phys_regs = 2**cfg.phys_regs_bits 90 self.rob_entries = 2**cfg.rob_entries_bits 91 92 self.phys_regs_bits = cfg.phys_regs_bits 93 self.rob_entries_bits = cfg.rob_entries_bits 94 self.max_rs_entries_bits = ceil_log2(self.max_rs_entries) 95 self.start_pc = cfg.start_pc 96 97 self.frontend_superscalarity = cfg.frontend_superscalarity 98 self.announcement_superscalarity = cfg.announcement_superscalarity 99 self.retirement_superscalarity = cfg.retirement_superscalarity 100 max_superscalarity = max(self.frontend_superscalarity, self.retirement_superscalarity) 101 if max_superscalarity & (max_superscalarity - 1) != 0: 102 raise ValueError("Maximum of frontend and retirement superscalarity must be a power of 2") 103 104 self.checkpoint_count = cfg.checkpoint_count 105 self.tag_bits = cfg.tag_bits 106 assert cfg.checkpoint_count < 2**cfg.tag_bits 107 108 self.min_instr_width_bytes = 2 if cfg.compressed or cfg.zcb else 4 109 self.min_instr_width_bytes_log = exact_log2(self.min_instr_width_bytes) 110 111 self.fetch_block_bytes_log = cfg.fetch_block_bytes_log 112 if self.fetch_block_bytes_log < bytes_in_word_log: 113 raise ValueError("Fetch block must be not smaller than the machine word.") 114 self.fetch_block_bytes = 2**self.fetch_block_bytes_log 115 self.fetch_width = 2**cfg.fetch_block_bytes_log // self.min_instr_width_bytes 116 self.fetch_width_log = exact_log2(self.fetch_width) 117 118 self.instr_buffer_size = cfg.instr_buffer_size 119 self.extra_verification = cfg.extra_verification 120 121 self.interrupt_custom_count = cfg.interrupt_custom_count 122 self.interrupt_custom_edge_trig_mask = cfg.interrupt_custom_edge_trig_mask 123 124 self.user_mode = cfg.user_mode 125 self.supervisor_mode = cfg.supervisor_mode 126 self.hpm_counters_count = cfg.hpm_counters_count 127 128 if self.hpm_counters_count < 0 or self.hpm_counters_count > 29: 129 raise ValueError("HPM counters count must be in range [0, 29]") 130 131 # TODO: remove when HPM counters are implemented 132 if self.hpm_counters_count > 0: 133 raise NotImplementedError("HPM counters are currently not implemented") 134 135 if self.supervisor_mode and not self.user_mode: 136 raise ValueError("Supervisor mode support requires user mode support") 137 138 self.pmp_register_count = cfg.pmp_register_count 139 if self.pmp_register_count not in [0, 16, 64]: 140 raise ValueError("PMP register count must be 0, 16, or 64") 141 142 if cfg.pmp_grain_log < 2: 143 raise ValueError("pmp_grain_log must be >= 2 (minimum 4-byte granularity)") 144 145 self.pmp_grain = cfg.pmp_grain_log - 2 # G parameter from RISC-V spec 146 self.pmp_grain_bytes = 2**cfg.pmp_grain_log 147 if self.pmp_register_count > 0 and self.icache_params.enable: 148 if self.pmp_grain_bytes < self.icache_params.line_size_bytes: 149 raise ValueError("PMP grain size must be >= cache line size") 150 151 self._toolchain_isa_str = gen_isa_string(extensions, cfg.xlen, skip_internal=True) 152 153 self._generate_test_hardware = cfg._generate_test_hardware 154 155 self.marchid = cfg.marchid 156 self.mimpid = cfg.mimpid 157 158 self.multiport_memory_type = cfg.multiport_memory_type