ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
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 
59 namespace etiss
60 {
61 namespace interfaces
62 {
63 
64 template <typename T, unsigned align>
66 
67 template <>
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 
76 class Delegate
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 
111 template <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>
117 bool 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 
162 template <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;
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 
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
etiss_int32 int32
Definition: 386-GCC.h:81
#define static_assert(x, y)
Definition: Fault.cpp:60
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
Delegate(ETISS_System &system, ETISS_CPU &cpu)
Definition: Delegate.cpp:50
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
std::list< uint64_t > & injectionAddresses()
Definition: Delegate.h:299
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::list< uint64_t > injectionAddresses_
Definition: Delegate.h:308
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::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
#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)
MM_EXPORT const int32_t NOERROR
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