1 // 2 // Copyright (c) 2010-2019 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.Peripherals.Bus; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Time; 11 using System; 12 using Antmicro.Renode.Logging; 13 14 namespace Antmicro.Renode.Peripherals.Miscellaneous 15 { 16 public class SAM_TRNG : BasicDoubleWordPeripheral, IKnownSize 17 { SAM_TRNG(IMachine machine)18 public SAM_TRNG(IMachine machine) : base(machine) 19 { 20 DefineRegisters(); 21 } 22 23 public long Size => 0x4000; 24 DefineRegisters()25 private void DefineRegisters() 26 { 27 Registers.Control.Define(this) 28 .WithFlag(0, out var enableUnverified, FieldMode.Write, name: "CR_ENABLE") 29 .WithReservedBits(1, 7) 30 .WithValueField(8, 24, out var enableKey, FieldMode.Write, name: "CR_KEY") 31 .WithWriteCallback((_, __) => 32 { 33 /* The enable bit and enable key have to be written at 34 * the same time - verify it here. 35 */ 36 if(enableUnverified.Value && enableKey.Value == RngKey) 37 { 38 enable.Value = true; 39 } 40 }); 41 42 Registers.InterruptStatus.Define(this) 43 .WithFlag(0, out enable, FieldMode.Read, name: "ISR_DATRDY"); 44 45 Registers.OutputData.Define(this) 46 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => 47 { 48 if(!enable.Value) 49 { 50 this.Log(LogLevel.Warning, "Reading TRNG data from an uninitialized device"); 51 52 return 0; 53 } 54 55 return (uint)rng.Next(); 56 }, name: "ODATA"); 57 58 /* Interrupts not generated properly yet */ 59 Registers.InterruptEnable.Define(this) 60 .WithFlag(0, FieldMode.Write, writeCallback: (_, value) => 61 { 62 if(value) 63 { 64 interruptEnabled.Value = true; 65 } 66 }, name: "IER_DATRDY"); 67 68 Registers.InterruptDisable.Define(this) 69 .WithFlag(0, FieldMode.Write, writeCallback: (_, value) => 70 { 71 if(value) 72 { 73 interruptEnabled.Value = false; 74 } 75 }, name: "IER_DATRDY"); 76 77 Registers.InterruptMask.Define(this) 78 .WithFlag(0, out interruptEnabled, FieldMode.Read, name: "IMR_DATRDY"); 79 } 80 81 private readonly PseudorandomNumberGenerator rng = EmulationManager.Instance.CurrentEmulation.RandomGenerator; 82 83 private IFlagRegisterField enable; 84 private IFlagRegisterField interruptEnabled; 85 86 /* Enable key - ASCII for "RNG" */ 87 private const uint RngKey = 0x524E47; 88 89 private enum Registers 90 { 91 Control = 0x0, 92 InterruptEnable = 0x10, 93 InterruptDisable = 0x14, 94 InterruptMask = 0x18, 95 InterruptStatus = 0x1C, 96 OutputData = 0x50, 97 } 98 } 99 } 100