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 using System;
9 using Microsoft.Scripting.Hosting;
10 using Antmicro.Renode.Peripherals.Bus;
11 using Antmicro.Migrant.Hooks;
12 using Antmicro.Migrant;
13 using System.Linq;
14 using Antmicro.Renode.Core;
15 
16 namespace Antmicro.Renode.Peripherals.Python
17 {
18     public class PeripheralPythonEngine : PythonEngine
19     {
20         private readonly static string[] Imports =
21         {
22             "from Antmicro.Renode.Logging import Logger as logger",
23             "from Antmicro.Renode.Logging import LogLevel",
24         };
25 
26         protected override string[] ReservedVariables
27         {
28             get { return base.ReservedVariables.Union(PeripheralPythonEngine.InnerReservedVariables).ToArray(); }
29         }
30 
31         private readonly static string[] InnerReservedVariables =
32         {
33             "request",
34             "self",
35             "size",
36             "logger",
37             "LogLevel"
38         };
39 
InitScope(ScriptSource script)40         private void InitScope(ScriptSource script)
41         {
42             Request = new PythonRequest();
43 
44             Scope.SetVariable("request", Request);
45             Scope.SetVariable("self", peripheral);
46             Scope.SetVariable("size", peripheral.Size);
47 
48             source = script;
49             code = Compile(source);
50         }
51 
PeripheralPythonEngine(PythonPeripheral peripheral)52         public PeripheralPythonEngine(PythonPeripheral peripheral)
53         {
54             this.peripheral = peripheral;
55             InitScope(Engine.CreateScriptSourceFromString(Aggregate(Imports)));
56         }
57 
PeripheralPythonEngine(PythonPeripheral peripheral, Func<ScriptEngine, ScriptSource> sourceGenerator)58         public PeripheralPythonEngine(PythonPeripheral peripheral, Func<ScriptEngine, ScriptSource> sourceGenerator)
59         {
60             this.peripheral = peripheral;
61             InitScope(sourceGenerator(Engine));
62         }
63 
64         public string Code
65         {
66             get
67             {
68                 return source.GetCode();
69             }
70         }
71 
ExecuteCode()72         public void ExecuteCode()
73         {
74             Execute(code);
75         }
76 
77         [Transient]
78         private ScriptSource source;
79 
80         [Transient]
81         private CompiledCode code;
82 
Init()83         protected override void Init()
84         {
85             base.Init();
86             InitScope(Engine.CreateScriptSourceFromString(codeContent));
87             codeContent = null;
88         }
89 
90         #region Serialization
91 
92         [PreSerialization]
BeforeSerialization()93         protected void BeforeSerialization()
94         {
95             codeContent = Code;
96         }
97 
98         [PostSerialization]
AfterDeSerialization()99         private void AfterDeSerialization()
100         {
101             codeContent = null;
102         }
103 
104         private string codeContent;
105 
106         #endregion
107 
108         [Transient]
109         private PythonRequest request;
110 
111         public PythonRequest Request
112         {
113             get
114             {
115                 return request;
116             }
117             private set
118             {
119                 request = value;
120             }
121         }
122 
123         private readonly PythonPeripheral peripheral;
124 
125         // naming convention here is pythonic
126         public class PythonRequest
127         {
128             public ulong value { get; set; }
129             public byte length { get; set; }
130             public RequestType type { get; set; }
131             public long offset { get; set; }
132             public ulong absolute { get; set; }
133             public ulong counter { get; set; }
134 
135             public bool isInit
136             {
137                 get
138                 {
139                     return type == RequestType.INIT;
140                 }
141             }
142 
143             public bool isRead
144             {
145                 get
146                 {
147                     return type == RequestType.READ;
148                 }
149             }
150 
151             public bool isWrite
152             {
153                 get
154                 {
155                     return type == RequestType.WRITE;
156                 }
157             }
158 
159             public bool isUser
160             {
161                 get
162                 {
163                     return type == RequestType.USER;
164                 }
165             }
166 
167             public enum RequestType
168             {
169                 READ,
170                 WRITE,
171                 INIT,
172                 USER
173             }
174         }
175     }
176 }
177