1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Peripherals; 13 using Antmicro.Renode.Peripherals.Bus; 14 using Antmicro.Renode.Peripherals.CPU; 15 16 namespace Antmicro.Renode.Peripherals.Miscellaneous 17 { 18 public class S32KXX_ModeEntryModule : BasicDoubleWordPeripheral, IKnownSize 19 { S32KXX_ModeEntryModule(IMachine machine, ICPU core0, ICPU core1 = null, ICPU core2 = null, ICPU core3 = null, ICPU core4 = null, ICPU core5 = null)20 public S32KXX_ModeEntryModule(IMachine machine, ICPU core0, 21 ICPU core1 = null, ICPU core2 = null, ICPU core3 = null, ICPU core4 = null, ICPU core5 = null) 22 : base(machine) 23 { 24 cores = new ICPU[] 25 { 26 core0, 27 core1, 28 core2, 29 core3, 30 core4, 31 core5 32 }; 33 cofbsStatus = new uint[][] 34 { 35 new uint[2], 36 new uint[4], 37 new uint[3] 38 }; 39 DefineRegisters(); 40 Initialize(); 41 } 42 Reset()43 public override void Reset() 44 { 45 base.Reset(); 46 Initialize(); 47 } 48 49 public long Size => 0x4000; 50 DefineRegisters()51 private void DefineRegisters() 52 { 53 Registers.ControlKey.Define(this) 54 .WithTag("CTL_KEY (Control Key)", 0, 16) 55 .WithReservedBits(16, 16); 56 57 Registers.ModeConfiguration.Define(this) 58 .WithTaggedFlag("DEST_RST (Destructive Reset Request)", 0) 59 .WithTaggedFlag("FUNC_RST (Functional Reset Request)", 1) 60 .WithReservedBits(2, 13) 61 .WithTaggedFlag("STANDBY (Standby Request)", 15) 62 .WithReservedBits(16, 16); 63 64 Registers.ModeUpdate.Define(this) 65 .WithTaggedFlag("MODE_UPD (Mode Update)", 0) 66 .WithReservedBits(1, 31); 67 68 Registers.ModeStatus.Define(this) 69 .WithTaggedFlag("PREV_MODE (Previous Mode)", 0) 70 .WithReservedBits(1, 31); 71 72 Registers.MainCoreID.Define(this) 73 .WithTag("CIDX (Core Index)", 0, 2) 74 .WithReservedBits(3, 5) 75 .WithTag("PIDX (Partition Index)", 8, 5) 76 .WithReservedBits(13, 19); 77 78 uint partitionSize = Registers.Partition1ProcessConfiguration - Registers.Partition0ProcessConfiguration; 79 Registers.Partition0ProcessConfiguration.DefineMany(this, PartitionCount, stepInBytes: partitionSize, resetValue: 0x1, setup: (reg, index) => reg 80 .WithTaggedFlag("PCE (Partition Clock Enable)", 0) 81 .WithReservedBits(1, 31) 82 ); 83 84 Registers.Partition0ProcessUpdate.DefineMany(this, PartitionCount, stepInBytes: partitionSize, setup: (reg, index) => reg 85 .WithTaggedFlag("PCUD (Partition Clock Update)", 0) 86 .WithReservedBits(1, 31) 87 ); 88 89 Registers.Partition0Status.DefineMany(this, PartitionCount, stepInBytes: partitionSize, resetValue: 0x1, setup: (reg, index) => reg 90 .WithTaggedFlag("PCS (Partition Clock Status)", 0) 91 .WithReservedBits(1, 31) 92 ); 93 94 DefineStatusEnableRegisters(Registers.Partition0COFBSet0ClockStatus, cofbsStatus[0]); 95 DefineStatusEnableRegisters(Registers.Partition1COFBSet0ClockStatus, cofbsStatus[1]); 96 DefineStatusEnableRegisters(Registers.Partition2COFBSet0ClockStatus, cofbsStatus[2]); 97 98 // Registers specific for the Partition 0 99 Registers.Partition0CoreLockstepControl.Define(this) 100 .WithReservedBits(0, 2) 101 .WithTaggedFlag("LS2 (Lockstep 2)", 2) 102 .WithReservedBits(3, 29); 103 104 var coreSize = Registers.Partition0Core1ProcessConfiguration - Registers.Partition0Core0ProcessConfiguration; 105 foreach (var index in Enumerable.Range(0, cores.Length).Where(x => x != 2)) 106 { 107 var offset = index * coreSize; 108 (Registers.Partition0Core0ProcessConfiguration + offset).Define(this) 109 .WithTaggedFlag($"CCE (Core{index} Clock Enable)", 0) 110 .WithReservedBits(1, 31); 111 112 (Registers.Partition0Core0ProcessUpdate + offset).Define(this) 113 .WithTaggedFlag($"CCUPD (Core{index} Clock Update)", 0) 114 .WithReservedBits(1, 31); 115 } 116 117 // Currently only a single core configuration is supported. 118 // To mimics the initial state of a system, halted cores reports waiting for interrupt. 119 Registers.Partition0Core0Status.DefineMany(this, (uint)cores.Length, stepInBytes: (uint)coreSize, setup: (reg, index) => reg 120 .WithFlag(0, name: $"CCS (Core{index} Clock Process Status)", 121 valueProviderCallback: (_) => cores[index] != null 122 ) 123 .WithReservedBits(1, 30) 124 .WithFlag(31, name: "WFI (WaitForInterruptStatus)", 125 valueProviderCallback: (_) => cores[index]?.IsHalted ?? false 126 ) 127 ); 128 129 Registers.Partition0Core0Address.DefineMany(this, (uint)cores.Length, stepInBytes: (uint)coreSize, setup: (reg, index) => reg 130 .WithReservedBits(0, 2) 131 .WithTag($"ADDR (Core{index} Boot Address)", 2, 30) 132 ); 133 } 134 DefineStatusEnableRegisters(Registers statusOffset, uint[] statuses)135 private void DefineStatusEnableRegisters(Registers statusOffset, uint[] statuses) 136 { 137 // COFB enable and status registers provides just a readback functionality. 138 // The registers don't distinguish between regular fields and reserved bits. 139 statusOffset.DefineMany(this, (uint)statuses.Length, (reg, index) => reg 140 .WithValueField(0, 32, FieldMode.Read, name: "BLOCKn (IP Blocks Status)", 141 valueProviderCallback: (_) => statuses[index] 142 ) 143 ); 144 145 var enableOffset = statusOffset - Registers.Partition0COFBSet0ClockStatus + Registers.Partition0COFBSet0ClockEnable; 146 enableOffset.DefineMany(this, (uint)statuses.Length, (reg, index) => reg 147 .WithValueField(0, 32, name: "REQn (Clocks Enable)", 148 writeCallback: (_, val) => statuses[index] = (uint)val, 149 valueProviderCallback: (_) => statuses[index] 150 ) 151 ); 152 } 153 Initialize()154 private void Initialize() 155 { 156 cofbsStatus[0][0] = 0x00000004; 157 cofbsStatus[0][1] = 0x00001000; 158 cofbsStatus[1][0] = 0x5E3F0007; 159 cofbsStatus[1][1] = 0x7CFE2FFC; 160 cofbsStatus[1][2] = 0x300C0000; 161 cofbsStatus[1][3] = 0x00005FEE; 162 cofbsStatus[2][0] = 0x0600000F; 163 cofbsStatus[2][1] = 0xCC000000; 164 cofbsStatus[2][2] = 0x00000003; 165 } 166 167 private readonly uint[][] cofbsStatus; 168 private readonly ICPU[] cores; 169 private const uint PartitionCount = 3; 170 171 public enum Registers 172 { 173 ControlKey = 0x0, // CTL_KEY 174 ModeConfiguration = 0x4, // MODE_CONF 175 ModeUpdate = 0x8, // MODE_UPD 176 ModeStatus = 0xC, // MODE_STAT 177 MainCoreID = 0x10, // MAIN_COREID 178 Partition0ProcessConfiguration = 0x100, // PRTN0_PCONF 179 Partition0ProcessUpdate = 0x104, // PRTN0_PUPD 180 Partition0Status = 0x108, // PRTN0_STAT 181 Partition0CoreLockstepControl = 0x10C, // PRTN0_CORE_LOCKSTE 182 Partition0COFBSet0ClockStatus = 0x110, // PRTN0_COFB0_STAT 183 Partition0COFBSet1ClockStatus = 0x114, // PRTN0_COFB1_STAT 184 Partition0COFBSet0ClockEnable = 0x130, // PRTN0_COFB0_CLKE 185 Partition0COFBSet1ClockEnable = 0x134, // PRTN0_COFB1_CLKE 186 Partition0Core0ProcessConfiguration = 0x140, // PRTN0_CORE0_PCON 187 Partition0Core0ProcessUpdate = 0x144, // PRTN0_CORE0_PUPD 188 Partition0Core0Status = 0x148, // PRTN0_CORE0_STAT 189 Partition0Core0Address = 0x14C, // PRTN0_CORE0_ADDR 190 Partition0Core1ProcessConfiguration = 0x160, // PRTN0_CORE1_PCON 191 Partition0Core1ProcessUpdate = 0x164, // PRTN0_CORE1_PUPD 192 Partition0Core1Status = 0x168, // PRTN0_CORE1_STAT 193 Partition0Core1Address = 0x16C, // PRTN0_CORE1_ADDR 194 Partition0Core2Status = 0x188, // PRTN0_CORE2_STAT 195 Partition0Core2Address = 0x18C, // PRTN0_CORE2_ADDR 196 Partition0Core3ProcessConfiguration = 0x1A0, // PRTN0_CORE3_PCON 197 Partition0Core3ProcessUpdate = 0x1A4, // PRTN0_CORE3_PUPD 198 Partition0Core3Status = 0x1A8, // PRTN0_CORE3_STAT 199 Partition0Core3Address = 0x1AC, // PRTN0_CORE3_ADDR 200 Partition0Core4ProcessConfiguration = 0x1C0, // PRTN0_CORE4_PCON 201 Partition0Core4ProcessUpdate = 0x1C4, // PRTN0_CORE4_PUPD 202 Partition0Core4Status = 0x1C8, // PRTN0_CORE4_STAT 203 Partition0Core4Address = 0x1CC, // PRTN0_CORE4_ADDR 204 Partition0Core5ProcessConfiguration = 0x1E0, // PRTN0_CORE5_PCON 205 Partition0Core5ProcessUpdate = 0x1E4, // PRTN0_CORE5_PUPD 206 Partition0Core5Status = 0x1E8, // PRTN0_CORE5_STAT 207 Partition0Core5Address = 0x1EC, // PRTN0_CORE5_ADDR 208 Partition1ProcessConfiguration = 0x300, // PRTN1_PCONF 209 Partition1ProcessUpdate = 0x304, // PRTN1_PUPD 210 Partition1Status = 0x308, // PRTN1_STAT 211 Partition1COFBSet0ClockStatus = 0x310, // PRTN1_COFB0_STAT 212 Partition1COFBSet1ClockStatus = 0x314, // PRTN1_COFB1_STAT 213 Partition1COFBSet2ClockStatus = 0x318, // PRTN1_COFB2_STAT 214 Partition1COFBSet3ClockStatus = 0x31C, // PRTN1_COFB3_STAT 215 Partition1COFBSet0ClockEnable = 0x330, // PRTN1_COFB0_CLKE 216 Partition1COFBSet1ClockEnable = 0x334, // PRTN1_COFB1_CLKE 217 Partition1COFBSet2ClockEnable = 0x338, // PRTN1_COFB2_CLKE 218 Partition1COFBSet3ClockEnable = 0x33C, // PRTN1_COFB3_CLKE 219 Partition2ProcessConfiguration = 0x500, // PRTN2_PCONF 220 Partition2ProcessUpdate = 0x504, // PRTN2_PUPD 221 Partition2Status = 0x508, // PRTN2_STAT 222 Partition2COFBSet0ClockStatus = 0x510, // PRTN2_COFB0_STAT 223 Partition2COFBSet1ClockStatus = 0x514, // PRTN2_COFB1_STAT 224 Partition2COFBSet2ClockStatus = 0x518, // PRTN2_COFB2_STAT 225 Partition2COFBSet0ClockEnable = 0x530, // PRTN2_COFB0_CLKE 226 Partition2COFBSet1ClockEnable = 0x534, // PRTN2_COFB1_CLKE 227 Partition2COFBSet2ClockEnable = 0x538 // PRTN2_COFB2_CLKE 228 } 229 } 230 } 231