1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using System.IO; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Exceptions; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.UserInterface; 14 using Antmicro.Renode.Utilities; 15 16 namespace Antmicro.Renode.Peripherals.Python 17 { 18 public static class PythonPeripheralExtensions 19 { PyDevFromFile(this Machine @this, ReadFilePath path, ulong address, int size, bool initable = false, string name = null, ulong offset = 0)20 public static void PyDevFromFile(this Machine @this, ReadFilePath path, ulong address, int size, bool initable = false, string name = null, ulong offset = 0) 21 { 22 var pyDev = new PythonPeripheral(size, initable, filename: path); 23 @this.SystemBus.Register(pyDev, new BusPointRegistration(address, offset)); 24 if(!string.IsNullOrEmpty(name)) 25 { 26 @this.SetLocalName(pyDev, name); 27 } 28 } 29 PyDevFromString(this Machine @this, string script, ulong address, int size, bool initable = false, string name = null, ulong offset = 0)30 public static void PyDevFromString(this Machine @this, string script, ulong address, int size, bool initable = false, string name = null, ulong offset = 0) 31 { 32 var pyDev = new PythonPeripheral(size, initable, script: script); 33 @this.SystemBus.Register(pyDev, new BusPointRegistration(address, offset)); 34 if(!string.IsNullOrEmpty(name)) 35 { 36 @this.SetLocalName(pyDev, name); 37 } 38 } 39 } 40 41 [Icon("python")] 42 public class PythonPeripheral : IBytePeripheral, IWordPeripheral, IDoubleWordPeripheral, IQuadWordPeripheral, IKnownSize, IAbsoluteAddressAware 43 { PythonPeripheral(int size, bool initable = false, string script = null, string filename = null)44 public PythonPeripheral(int size, bool initable = false, string script = null, string filename = null) 45 { 46 this.size = size; 47 this.initable = initable; 48 this.script = script; 49 this.filename = filename; 50 51 if((this.script == null && this.filename == null) || (this.script != null && this.filename != null)) 52 { 53 throw new ConstructionException("Parameters `script` and `filename` cannot be both set or both unset."); 54 } 55 if(this.script != null) 56 { 57 this.pythonRunner = new PeripheralPythonEngine(this, x => x.CreateScriptSourceFromString(this.script)); 58 } 59 else if(this.filename != null) 60 { 61 if(!File.Exists(this.filename)) 62 { 63 throw new ConstructionException(string.Format("Could not find source file for the script: {0}.", this.filename)); 64 } 65 this.pythonRunner = new PeripheralPythonEngine(this, x => x.CreateScriptSourceFromFile(this.filename)); 66 } 67 } 68 SetAbsoluteAddress(ulong address)69 public void SetAbsoluteAddress(ulong address) 70 { 71 pythonRunner.Request.absolute = address; 72 } 73 ReadByte(long offset)74 public byte ReadByte(long offset) 75 { 76 pythonRunner.Request.length = 1; 77 HandleRead(offset); 78 return unchecked((byte)pythonRunner.Request.value); 79 } 80 WriteByte(long offset, byte value)81 public void WriteByte(long offset, byte value) 82 { 83 pythonRunner.Request.length = 1; 84 HandleWrite(offset, value); 85 } 86 ReadDoubleWord(long offset)87 public uint ReadDoubleWord(long offset) 88 { 89 pythonRunner.Request.length = 4; 90 HandleRead(offset); 91 return unchecked((uint)pythonRunner.Request.value); 92 } 93 WriteDoubleWord(long offset, uint value)94 public void WriteDoubleWord(long offset, uint value) 95 { 96 pythonRunner.Request.length = 4; 97 HandleWrite(offset, value); 98 } 99 ReadQuadWord(long offset)100 public ulong ReadQuadWord(long offset) 101 { 102 pythonRunner.Request.length = 8; 103 HandleRead(offset); 104 return unchecked(pythonRunner.Request.value); 105 } 106 WriteQuadWord(long offset, ulong value)107 public void WriteQuadWord(long offset, ulong value) 108 { 109 pythonRunner.Request.length = 8; 110 HandleWrite(offset, value); 111 } 112 ReadWord(long offset)113 public ushort ReadWord(long offset) 114 { 115 pythonRunner.Request.length = 2; 116 HandleRead(offset); 117 return unchecked((ushort)pythonRunner.Request.value); 118 } 119 WriteWord(long offset, ushort value)120 public void WriteWord(long offset, ushort value) 121 { 122 pythonRunner.Request.length = 2; 123 HandleWrite(offset, value); 124 } 125 ControlWrite(long command, ulong value)126 public void ControlWrite(long command, ulong value) 127 { 128 // ignoring the return value 129 ControlRead(command, value); 130 } 131 ControlRead(long command, ulong value)132 public ulong ControlRead(long command, ulong value) 133 { 134 EnsureInit(); 135 136 pythonRunner.Request.value = 0; 137 pythonRunner.Request.type = PeripheralPythonEngine.PythonRequest.RequestType.USER; 138 pythonRunner.Request.offset = command; 139 pythonRunner.Request.value = value; 140 pythonRunner.Request.length = 8; 141 Execute(); 142 return unchecked(pythonRunner.Request.value); 143 } 144 Reset()145 public void Reset() 146 { 147 inited = false; 148 EnsureInit(); 149 } 150 151 public long Size 152 { 153 get { return size; } 154 } 155 EnsureInit()156 public void EnsureInit() 157 { 158 if(!inited) 159 { 160 Init(); 161 inited = true; 162 } 163 } 164 165 public string Code 166 { 167 get 168 { 169 return pythonRunner.Code; 170 } 171 } 172 Init()173 private void Init() 174 { 175 if(initable) 176 { 177 pythonRunner.Request.type = PeripheralPythonEngine.PythonRequest.RequestType.INIT; 178 Execute(); 179 } 180 } 181 HandleRead(long offset)182 private void HandleRead(long offset) 183 { 184 EnsureInit(); 185 186 pythonRunner.Request.value = 0; 187 pythonRunner.Request.type = PeripheralPythonEngine.PythonRequest.RequestType.READ; 188 pythonRunner.Request.offset = offset; 189 pythonRunner.Request.counter = requestCounter++; 190 Execute(); 191 } 192 HandleWrite(long offset, ulong value)193 private void HandleWrite(long offset, ulong value) 194 { 195 EnsureInit(); 196 197 pythonRunner.Request.value = value; 198 pythonRunner.Request.type = PeripheralPythonEngine.PythonRequest.RequestType.WRITE; 199 pythonRunner.Request.offset = offset; 200 pythonRunner.Request.counter = requestCounter++; 201 Execute(); 202 } 203 Execute()204 private void Execute() 205 { 206 pythonRunner.ExecuteCode(); 207 } 208 209 private bool inited; 210 private ulong requestCounter; 211 212 private readonly PeripheralPythonEngine pythonRunner; 213 private readonly bool initable; 214 private readonly int size; 215 private readonly string script; 216 private readonly string filename; 217 } 218 } 219