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 Antmicro.Renode.Core;
8 using Antmicro.Renode.Time;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Logging;
11 
12 namespace Antmicro.Renode.Peripherals.Timers
13 {
14     // This peripheral implements an interface to Arm CoreSight SoC-400 timestamp generator module
15     public class RenesasRZG_SYC : BasicDoubleWordPeripheral, IKnownSize
16     {
RenesasRZG_SYC(IMachine machine, long frequency)17         public RenesasRZG_SYC(IMachine machine, long frequency) : base(machine)
18         {
19             timer = new LimitTimer(machine.ClockSource, frequency, this, "Timestamp generator", ulong.MaxValue, Direction.Ascending, workMode: WorkMode.Periodic);
20             DefineRegisters();
21             Reset();
22         }
23 
Reset()24         public override void Reset()
25         {
26             base.Reset();
27             timer.Reset();
28             timerValueLowerOverride = null;
29         }
30 
31         public long Size => 0x10000;
32 
DefineRegisters()33         private void DefineRegisters()
34         {
35             Registers.CounterControl.Define(this)
36                 .WithFlag(0, name: "EN",
37                     valueProviderCallback: _ => timer.Enabled,
38                     writeCallback: (_, value) => timer.Enabled = value)
39                 .WithTaggedFlag("HDBG", 1)
40                 .WithReservedBits(2, 30);
41 
42             Registers.CounterStatus.Define(this)
43                 .WithReservedBits(0, 1)
44                 .WithTaggedFlag("DBGH (Debug Halted)", 1)
45                 .WithReservedBits(2, 30);
46 
47             Registers.CounterValueLower.Define(this)
48                 .WithValueField(0, 32, name: "CNTCVL_L_32",
49                     valueProviderCallback: _ => timer.Value,
50                     writeCallback: (_, value) => timerValueLowerOverride = (uint)value);
51 
52             Registers.CounterValueUpper.Define(this)
53                 .WithValueField(0, 32, name: "CNTCVU_U_32",
54                     valueProviderCallback: _ => timer.Value >> 32,
55                     writeCallback: (_, value) =>
56                     {
57                         var newValue = (value << 32) | (timerValueLowerOverride ?? (uint)timer.Value);
58                         timerValueLowerOverride = null;
59 
60                         if(!timer.Enabled)
61                         {
62                             this.WarningLog("Attempt to set the counter value to {0} while timer is running, ignoring", newValue);
63                             return;
64                         }
65                         timer.Value = newValue;
66                     });
67 
68             Registers.BaseFrequencyId.Define(this)
69                 .WithValueField(0, 32, name: "FREQ",
70                     valueProviderCallback: _ => (uint)timer.Frequency,
71                     writeCallback: (_, value) => timer.Frequency = (long)value);
72 
73             Registers.CounterValueLowerReadOnly.Define(this)
74                 .WithValueField(0, 32, FieldMode.Read, name: "CNTCVL_L_32",
75                     valueProviderCallback: _ => timer.Value);
76 
77             Registers.CounterValueUpperReadOnly.Define(this)
78                 .WithValueField(0, 32, FieldMode.Read, name: "CNTCVU_U_32",
79                     valueProviderCallback: _ => timer.Value >> 32);
80 
81             DefineManagementRegisters(0x0);
82             DefineManagementRegisters(0x1000);
83         }
84 
DefineManagementRegisters(int offset)85         private void DefineManagementRegisters(int offset)
86         {
87             (ManagementRegisters.PeripheralID4 + offset).Define(this, 0x4)
88                 .WithTag("DES_2", 0, 4)
89                 .WithTag("SIZE", 4, 4)
90                 .WithReservedBits(8, 24);
91 
92             (ManagementRegisters.PeripheralID0 + offset).Define(this, 0x1)
93                 .WithTag("PART_0", 0, 8)
94                 .WithReservedBits(8, 24);
95 
96             (ManagementRegisters.PeripheralID1 + offset).Define(this, 0xB1)
97                 .WithTag("PART_1", 0, 4)
98                 .WithTag("DES_0", 4, 4)
99                 .WithReservedBits(8, 24);
100 
101             (ManagementRegisters.PeripheralID2 + offset).Define(this, 0x1B)
102                 .WithTag("DES_1", 0, 3)
103                 .WithTaggedFlag("JEDEC", 3)
104                 .WithTag("REVISION", 4, 4)
105                 .WithReservedBits(8, 24);
106 
107             (ManagementRegisters.PeripheralID3 + offset).Define(this, 0x0)
108                 .WithTag("CMOD", 0, 4)
109                 .WithTag("REVAND", 4, 4)
110                 .WithReservedBits(8, 24);
111 
112             (ManagementRegisters.ComponentID0 + offset).Define(this, 0xD)
113                 .WithTag("PRMBL_0", 0, 8)
114                 .WithReservedBits(8, 24);
115 
116             (ManagementRegisters.ComponentID1 + offset).Define(this, 0xF0)
117                 .WithTag("PRMBL_1", 0, 4)
118                 .WithTag("CLASS", 4, 4)
119                 .WithReservedBits(8, 24);
120 
121             (ManagementRegisters.ComponentID2 + offset).Define(this, 0x5)
122                 .WithTag("PRMBL_2", 0, 8)
123                 .WithReservedBits(8, 24);
124 
125             (ManagementRegisters.ComponentID3 + offset).Define(this, 0xB1)
126                 .WithTag("PRMBL_3", 0, 8)
127                 .WithReservedBits(8, 24);
128         }
129 
130         private readonly LimitTimer timer;
131         // Nullable uint is used, so that software has the ability to only override
132         // the upper half of the counter's value
133         private uint? timerValueLowerOverride;
134 
135         private enum Registers
136         {
137             CounterControl            = 0x0000, // CNTCR
138             CounterStatus             = 0x0004, // CNTSR
139             CounterValueLower         = 0x0008, // CNTCVL
140             CounterValueUpper         = 0x000C, // CNTCVU
141             BaseFrequencyId           = 0x0020, // CNTFID0
142             CounterValueLowerReadOnly = 0x1000, // CNTCVL
143             CounterValueUpperReadOnly = 0x1004, // CNTCVU
144         }
145 
146         private enum ManagementRegisters
147         {
148             PeripheralID4 = 0xFD0, // PIDR4
149             PeripheralID0 = 0xFE0, // PIDR0
150             PeripheralID1 = 0xFE4, // PIDR1
151             PeripheralID2 = 0xFE8, // PIDR2
152             PeripheralID3 = 0xFEC, // PIDR3
153             ComponentID0  = 0xFF0, // CIDR0
154             ComponentID1  = 0xFF4, // CIDR1
155             ComponentID2  = 0xFF8, // CIDR2
156             ComponentID3  = 0xFFC, // CIDR3
157         }
158     }
159 }
160