1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 13 namespace Antmicro.Renode.Peripherals.Miscellaneous 14 { 15 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 16 public class LiteX_MMCM_CSR32 : BasicDoubleWordPeripheral, IKnownSize 17 { LiteX_MMCM_CSR32(IMachine machine)18 public LiteX_MMCM_CSR32(IMachine machine) : base(machine) 19 { 20 mmcmRegisters = new uint[RegistersCount]; 21 22 DefineRegisters(); 23 } 24 Reset()25 public override void Reset() 26 { 27 base.Reset(); 28 29 for(var i = 0; i < mmcmRegisters.Length; i++) 30 { 31 mmcmRegisters[i] = 0; 32 } 33 } 34 35 public long Size => 0x100; 36 DefineRegisters()37 private void DefineRegisters() 38 { 39 Registers.Reset.Define(this) 40 .WithFlag(0, FieldMode.WriteOneToClear, name: "reset", writeCallback: (_, val) => 41 { 42 if(val) 43 { 44 // this "reset" should not 45 // clear the internal mmcm registers 46 RegistersCollection.Reset(); 47 } 48 }) 49 .WithIgnoredBits(1, 31) 50 ; 51 52 Registers.Locked.Define(this) 53 .WithFlag(0, name: "locked", valueProviderCallback: _ => true) // we are always ready 54 .WithReservedBits(1, 7) 55 .WithIgnoredBits(8, 24) 56 ; 57 58 Registers.Read.Define(this) 59 .WithFlag(0, FieldMode.WriteOneToClear, name: "read", writeCallback: (_, val) => 60 { 61 if(val) 62 { 63 HandleRead(); 64 } 65 }) 66 .WithIgnoredBits(1, 31) 67 ; 68 69 Registers.Write.Define(this) 70 .WithFlag(0, FieldMode.WriteOneToClear, name: "write", writeCallback: (_, val) => 71 { 72 if(val) 73 { 74 HandleWrite(); 75 } 76 }) 77 .WithIgnoredBits(1, 31) 78 ; 79 80 Registers.DataReady.Define(this) 81 .WithFlag(0, out dataReadyField, name: "drdy") 82 .WithReservedBits(1, 7) 83 .WithIgnoredBits(8, 24) 84 ; 85 Registers.Address.Define(this) 86 .WithValueField(0, 8, out addressField, name: "addr") 87 .WithIgnoredBits(8, 24) 88 ; 89 Registers.DataWrite.Define(this) 90 .WithValueField(0, 16, out dataWriteField, FieldMode.Write, name: "dat_w") 91 .WithIgnoredBits(16, 16) 92 ; 93 Registers.DataRead.Define(this) 94 .WithValueField(0, 16, out dataReadField, FieldMode.Read, name: "dat_r") 95 .WithIgnoredBits(16, 16) 96 ; 97 } 98 HandleRead()99 private void HandleRead() 100 { 101 if((int)addressField.Value >= mmcmRegisters.Length) 102 { 103 this.Log(LogLevel.Error, "Trying to read from a non-existing MMCM register #{0}. This model supports registers <0-{1}>", addressField.Value, mmcmRegisters.Length - 1); 104 return; 105 } 106 107 dataReadField.Value = mmcmRegisters[addressField.Value]; 108 dataReadyField.Value = true; 109 } 110 HandleWrite()111 private void HandleWrite() 112 { 113 if((int)addressField.Value >= mmcmRegisters.Length) 114 { 115 this.Log(LogLevel.Error, "Trying to write to a non-existing MMCM register #{0}. This model supports registers <0-{1}>", addressField.Value, mmcmRegisters.Length - 1); 116 return; 117 } 118 119 mmcmRegisters[addressField.Value] = (uint)dataWriteField.Value; 120 dataReadyField.Value = true; 121 } 122 123 private IFlagRegisterField dataReadyField; 124 private IValueRegisterField addressField; 125 private IValueRegisterField dataReadField; 126 private IValueRegisterField dataWriteField; 127 128 private uint[] mmcmRegisters; 129 130 private const int RegistersCount = 0x50; // 0x4F is the last register in MMCM 131 132 private enum Registers 133 { 134 Reset = 0x0, 135 Locked = 0x4, 136 Read = 0x8, 137 Write = 0xc, 138 DataReady = 0x10, 139 Address = 0x14, 140 DataWrite = 0x18, 141 DataRead = 0x1c, 142 } 143 } 144 } 145