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