ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Delegate.h
Go to the documentation of this file.
1
52#ifndef ETISS_INTERFACES_DELEGATE_H
53#define ETISS_INTERFACES_DELEGATE_H
54
55#include "etiss/Misc.h"
56#include "etiss/jit/ReturnCode.h"
57#include "etiss/jit/System.h"
58
59namespace etiss
60{
61namespace interfaces
62{
63
64template <typename T, unsigned align>
66
67template <>
69{
70 return ((((((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1)) & 0xcccccccc) >> 2) |
71 (((((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1)) & 0x33333333)
72 << 2)); // heavily requires compiler optimization. cannot be implemented smarter since a constexpr function
73 // may only have a return statement
74}
75
77{
78 private:
81
82 public:
84
85 void syncTime(uint64_t time_ps);
86
90 etiss::int32 read(bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len);
91
95 etiss::int32 write(bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len);
96
97 private:
98 public:
100 std::function<etiss::int32(bool /*ibus*/, uint64_t & /*time_ps*/, uint64_t /*addr*/, uint8_t * /*buf*/,
101 unsigned /*len*/, bool & /*continue*/, bool & /*handleNormal*/)>
103 std::function<etiss::int32(bool /*ibus*/, uint64_t & /*time_ps*/, uint64_t /*addr*/, uint8_t * /*buf*/,
104 unsigned /*len*/, bool & /*continue*/, bool & /*handleNormal*/)>
106
107 std::function<void(bool injected, const uint64_t &time_ps, uint64_t addr, const uint8_t *buf, unsigned len)>
109};
110
111template <typename T, bool (Delegate::*rwop)(bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len),
112 unsigned bytewidth, bool swapBitOrder_ = false>
117bool sel_rwop(Delegate &delg, bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, T sel_i)
118{
119 static_assert(std::is_integral<T>::value, "sel_rwop needs an integral type for the select signal");
120 static_assert(bytewidth > 0, "bytewidth cannot be 0");
121 if (unlikely(sel_i == 0))
122 {
123 return (delg.*rwop)(ibus, time_ps, addr, buf, 0);
124 }
125 // if (swapBitOrder_)
126 // sel_i = swapBitOrder<T,bytewidth>(sel_i);
127 // handle common cases quickly
128 if (likely(sel_i == ((1 << bytewidth) - 1)))
129 { // all bits are selected
130 return (delg.*rwop)(ibus, time_ps, addr, buf, bytewidth);
131 }
132 else
133 {
134 // std::cout << "sel_i = " << sel_i << std::endl;
135 if (!swapBitOrder_)
136 { // guessing common values
137 if ((sel_i == ((1 << (bytewidth >> 1)) - 1)) && (bytewidth > 1))
138 { // halve of the bits are selected
139 return (delg.*rwop)(ibus, time_ps, addr, buf, bytewidth >> 1);
140 }
141 else if ((sel_i == ((1 << (bytewidth >> 2)) - 1)) && (bytewidth > 3))
142 { // one bit is selected
143 return (delg.*rwop)(ibus, time_ps, addr, buf, bytewidth >> 2);
144 }
145 }
146 else
147 {
148 if ((sel_i == ((1 << (bytewidth >> 1)) - 1)) && (bytewidth > 1))
149 { // halve of the bits are selected
150 return (delg.*rwop)(ibus, time_ps, addr, buf, bytewidth >> 1);
151 }
152 else if ((sel_i == ((1 << (bytewidth >> 2)) - 1)) && (bytewidth > 3))
153 {
154 return (delg.*rwop)(ibus, time_ps, addr, buf, bytewidth >> 2);
155 }
156 }
157 }
158 etiss::log(etiss::FATALERROR, "not implemented", ETISS_SRCLOC, sel_i);
159 return false;
160}
161
162template <typename T>
164{
165 static_assert(std::is_pod<T>::value, "SimpleInstructionInjector<T> requires T to be a pod type");
166
167 public:
168 SimpleInstructionInjector(bool useRefetchCompensation = true)
169 : logInjectionAddresses_(false), useRefetchCompensation_(useRefetchCompensation)
170 {
171 }
172
173 void append(T val) { buffer.push_back(val); }
174
175 template <class InputIt>
176 void append(InputIt first, InputIt last)
177 {
178 buffer.insert(buffer.end(), first, last);
179 }
180
186 void setHelper(unsigned index, std::function<std::list<T>(T)> func)
187 {
188 genHelpers.insert(std::make_pair(index, func));
189 }
190
191 bool appendWithHelper(unsigned helper, T val)
192 {
193 auto fnc = genHelpers.find(helper);
194 if (fnc == genHelpers.end())
195 return false;
196
197 std::list<T> tmp = fnc->second(val);
198
199 append(tmp.begin(), tmp.end());
200
201 return true;
202 }
203
204 void appendRepetitions(unsigned count)
205 {
206 std::list<T> oldbuf = buffer;
207 for (unsigned i = 0; i < count; i++)
208 {
209 buffer.insert(buffer.end(), oldbuf.begin(), oldbuf.end());
210 }
211 }
212
216 std::function<etiss::int32(bool, uint64_t &, uint64_t, uint8_t *, unsigned, bool &, bool &)> toFunction()
217 {
218 std::map<uint64_t, T> refetchcompensation;
219 return [refetchcompensation, this](bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len,
220 bool &continu, bool &handleNormal) mutable {
221 continu = true;
222 handleNormal = false;
223
224 if (!ibus)
225 {
226 handleNormal = true;
227 return etiss::RETURNCODE::GENERALERROR; // X Read bus can not handle instruction injection.
228 }
229
230 if (len != sizeof(T))
231 {
233 "SimpleInstructionInjector detected an instruction read access of invalid length");
234 return etiss::RETURNCODE::IBUS_READ_ERROR;
235 }
236
237 // if data is fetched from the same address again then inject the same data again
238 // is a size limited form of this compensation usefull? e.g. execute from address 4,8,12,16,4 where the
239 // instructions at address 4 should differ -> size limit needs to be 3
241 {
242 auto refetch = refetchcompensation.find(addr);
243 if (refetch != refetchcompensation.end())
244 {
245 *((T *)buf) = refetch->second;
246 return etiss::RETURNCODE::NOERROR;
247 }
248 }
249
250 // note the injected sequence must guarantee that there is no refetch that
251 // would require instructions from this function. in case of an or1k
252 // processor this can be achieved by adding l.nop operations at the end
253 if (buffer.size() == 0)
254 {
255 continu = false;
256 handleNormal = true;
257 return etiss::RETURNCODE::IBUS_READ_ERROR; // X
258 }
259
260 *((T *)buf) = buffer.front();
262 refetchcompensation.insert(std::pair<uint64_t, T>(addr, buffer.front()));
263 buffer.pop_front();
264
265 continu = buffer.size() != 0;
266
268 {
269 // std::cout << "push_back(0x" << std::hex << addr << std::dec << ")" << std::endl;
270 injectionAddresses_.push_back(addr);
271 }
272
273 // std::cout << "Pending: " << buffer.size() << std::endl;
274
275 return etiss::RETURNCODE::NOERROR;
276 };
277 }
278
283 {
284 for (auto iter = buffer.begin(); iter != buffer.end(); iter++)
285 {
286 T tmp = *iter;
287 for (size_t i = 0; i < (sizeof(T) >> 1); i++)
288 {
289 ((char *)&(*iter))[i] = ((char *)&tmp)[sizeof(T) - 1 - i];
290 ((char *)&(*iter))[sizeof(T) - 1 - i] = ((char *)&tmp)[i];
291 }
292 }
293 }
294
295 inline bool injectionFinished() { return buffer.empty(); }
296
298 inline void logInjectionAddresses(bool val) { logInjectionAddresses_ = val; }
299 inline std::list<uint64_t> &injectionAddresses() { return injectionAddresses_; }
300
301 private:
302 std::list<T> buffer;
303
304 std::map<unsigned, std::function<std::list<T>(T)>> genHelpers;
305
308 std::list<uint64_t> injectionAddresses_;
309};
310
311} // namespace interfaces
312} // namespace etiss
313
314#endif // ETISS_INTERFACES_DELEGATE_H
general configuration and logging
#define ETISS_SRCLOC
Definition Misc.h:239
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ uint64_t
Definition arm_cde.h:31
static __inline__ uint8_t
Definition arm_mve.h:323
#define likely(x)
Definition types.h:73
#define unlikely(x)
Definition types.h:74
std::function< etiss::int32(bool, uint64_t &, uint64_t, uint8_t *, unsigned, bool &, bool &)> injectedRead
if valid then this function will be called by read() instead of performing any action itself
Definition Delegate.h:102
void syncTime(uint64_t time_ps)
Definition Delegate.cpp:52
etiss::int32 read(bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len)
handles read operations.
Definition Delegate.cpp:66
ETISS_System & system
Definition Delegate.h:79
etiss::int32 write(bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, unsigned len)
handles write operations.
Definition Delegate.cpp:124
std::function< etiss::int32(bool, uint64_t &, uint64_t, uint8_t *, unsigned, bool &, bool &)> redirectedWrite
Definition Delegate.h:105
std::function< void(bool injected, const uint64_t &time_ps, uint64_t addr, const uint8_t *buf, unsigned len)> snoopRead
Definition Delegate.h:108
bool appendWithHelper(unsigned helper, T val)
Definition Delegate.h:191
void swapEndianness()
swaps the endianness of all stored buffer values
Definition Delegate.h:282
SimpleInstructionInjector(bool useRefetchCompensation=true)
Definition Delegate.h:168
std::map< unsigned, std::function< std::list< T >(T)> > genHelpers
Definition Delegate.h:304
std::function< etiss::int32(bool, uint64_t &, uint64_t, uint8_t *, unsigned, bool &, bool &)> toFunction()
Definition Delegate.h:216
void setHelper(unsigned index, std::function< std::list< T >(T)> func)
Adds a function with an unique ID to the SimpleInstructionInjector.
Definition Delegate.h:186
void append(InputIt first, InputIt last)
Definition Delegate.h:176
std::list< uint64_t > & injectionAddresses()
Definition Delegate.h:299
#define CONSTEXPR
Definition config.h:91
CONSTEXPR uint32_t swapBitOrder< uint32_t, 4 >(uint32_t t)
Definition Delegate.h:68
bool sel_rwop(Delegate &delg, bool ibus, uint64_t &time_ps, uint64_t addr, uint8_t *buf, T sel_i)
this function handles read writes in case of busses that have a fixed output with and a select signal...
Definition Delegate.h:117
CONSTEXPR T swapBitOrder(T t)
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition Benchmark.h:53
@ ERROR
Definition Misc.h:127
@ FATALERROR
Definition Misc.h:126
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:125
#define false
Definition stdbool.h:17
#define bool
Definition stdbool.h:15
basic cpu state structure needed for execution of any cpu architecture.
Definition CPU.h:89
memory access and time synchronization functions.
Definition System.h:78