blob: 255cf5a93bb23c3a12c9f358d9fb95a09805d3e3 [file] [log] [blame]
Zane Shelley871adec2019-07-30 11:01:39 -05001#pragma once
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05002
3/**
4 * @brief Models register.It does not contain target.
5 *
6 * This class stores the hash id and bit length of scom registers It models
7 * registers without maintaining target information. Instances of this class
8 * are shared across rule chip objects of same type.Once prd object model is
9 * built, instances of this register are saved in flyweight.These instances
10 * persist as long as prd object model survives.
11 */
12
Zane Shelley52cb1a92019-08-21 14:38:31 -050013#include <hei_includes.hpp>
14#include <register/hei_register.hpp>
15#include <util/hei_bit_string.hpp>
16
Zane Shelley871adec2019-07-30 11:01:39 -050017namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050018{
19
Zane Shelley61565dc2019-09-18 21:57:10 -050020/**
21 * @brief Stores information (e.g. address, type, length, etc.) for an actual
22 * hardware register.
23 *
24 * Hardware access:
25 *
26 * Actual hardware access is defined by the user application via the user
27 * interface APIs. In order to tell the user application which chip to target,
28 * the user application gives the isolator pointers to its chip objects. As
29 * each chip needs to be accessed, the isolator must store the chip in a
30 * static variable defined in this class. The intended use is:
31 *
32 * - Call HardwareRegister::setAccessor() with the target chip.
33 * - Perform all necessary hardware accesses to that chip.
34 * - Call HardwareRegister::clearAccessor() to remove the chip access. This
35 * helps ensure we don't try to access the wrong chip.
Zane Shelleyd0af3582019-09-19 10:48:59 -050036 *
37 * Register cache:
38 *
39 * In order to save memory space, each instance of this class does not store
40 * the contents of the target hardware register. Instead, that data is stored
41 * in a register cache, which a static variable defined in this class. This
42 * allows us to store only what we need. The cache can also be thought of as a
43 * snapshot of the registers at the time of isolation, which can be useful if
44 * the hardware is still running and register values could change.
45 *
46 * In order to ensure stale data isn't used from the cache, call
47 * HardwareRegister::flushAll() before beginning isolation on a new attention.
48 * Also, HardwareRegister::flushAll() should be called when the isolator is
49 * uninitialized before the rest of the isolation objects are deleted.
Zane Shelley61565dc2019-09-18 21:57:10 -050050 */
Zane Shelleycd36f432019-08-30 21:22:07 -050051class HardwareRegister : public Register
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050052{
53 public:
54
Zane Shelley61565dc2019-09-18 21:57:10 -050055#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050056 /**
57 * @brief constructor
58 * @param i_address address of the register
59 * @param i_bitLength bit length of register
60 * @param i_targetType target type associated with register
61 */
Zane Shelleycd36f432019-08-30 21:22:07 -050062 HardwareRegister( uint64_t i_address, uint32_t i_bitLength,
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050063 TARGETING::TYPE i_targetType, AccessLevel i_access ) :
Zane Shelley23244cb2019-08-30 21:12:12 -050064 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050065 iv_bitLength( i_bitLength ),
66 iv_chipType( i_targetType ),
67 iv_scomAddress( i_address ),
68 iv_operationType( i_access )
69 {}
70
71 /**
72 * @brief constructor .Added this because we save object of this type in
73 * @ FlyweightS
74 */
Zane Shelleycd36f432019-08-30 21:22:07 -050075 HardwareRegister():
Zane Shelley23244cb2019-08-30 21:12:12 -050076 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050077 iv_bitLength( 0 ),
78 iv_chipType( TARGETING::TYPE_NA ),
79 iv_scomAddress( 0 ),
80 iv_operationType( ACCESS_NONE )
81 {}
Zane Shelley65ed96a2019-10-14 13:06:11 -050082#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050083
Zane Shelley65ed96a2019-10-14 13:06:11 -050084 /** Function overloaded from parent Register class. */
85 virtual const BitString * getBitString() const { return nullptr; }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050086
Zane Shelley65ed96a2019-10-14 13:06:11 -050087#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050088 /**
89 * @brief Updates bit string contents associated with register
90 * @param i_bs poiner to bit string
91 * @return Nil
92 */
93
94 virtual void SetBitString(const BitString * i_bs) ;
95
96 /**
97 * @brief Returns length of the bits string associated with register
98 * @return length of bit string
99 */
100 uint32_t GetBitLength(void) const { return iv_bitLength ;}
Zane Shelley61565dc2019-09-18 21:57:10 -0500101#endif
Zane Shelleyd0af3582019-09-19 10:48:59 -0500102 size_t getByteSize() const { return 8; } // TODO
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500103
104 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500105 * @brief Reads a register from hardware via the user interface APIs.
106 * @param i_force When false, this function will only read from hardware if
107 * an entry for this instance does not already exist in the
108 * register cache. When true, the entry in the register
109 * cache is flushed, if it exists. Then this function will
110 * read from hardware and update the cache.
111 * @return See the return code from the registerRead() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500112 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500113 ReturnCode read( bool i_force = false ) const;
114
115 #ifndef __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500116
117 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500118 * @brief Writes the value stored in the register cache to hardware via the
119 * user interface APIs.
120 * @return See the return code from the registerWrite() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500121 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500122 ReturnCode write() const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500123
Zane Shelley61565dc2019-09-18 21:57:10 -0500124 #endif // __HEI_READ_ONLY
125
126#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500127 /**
128 * @brief Returns the hash id of register
129 * @return returns hash id of register
130 * @pre None
131 * @post None
132 * @note
133 */
134 virtual uint16_t GetId(void) const { return iv_shortId; };
135
136 /**
137 * @brief Sets the hash id of register
138 * @param i_id hash id of register
139 * @return Nil
140 */
141 virtual void SetId(uint16_t i_id) { iv_shortId = i_id; };
142
143 /**
144 * @brief Returns type of Target associated with register.
145 * @return Refer to function description
146 */
147 TARGETING::TYPE getChipType()const{ return iv_chipType ;} ;
148 /**
149 * @brief Returns scom address of register
150 * @return Refer to function description
151 */
152 uint64_t GetAddress( ) const {return iv_scomAddress ;};
Zane Shelley65ed96a2019-10-14 13:06:11 -0500153#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500154 /**
155 * @brief compares two ScomRegisterAccess register for equality
156 * @param i_rightRegister register to be compared against
157 * @return Returns true if registers are equal false otherwise
158 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500159 bool operator == ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500160 /**
161 * @brief defines < operation for ScomRegisterAccess
162 * @param i_rightRegister register to be compared against
163 * @return Returns false if i_rightRegisters is less and true otherwise
164 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500165 bool operator < ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelley65ed96a2019-10-14 13:06:11 -0500166#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500167 /**
168 * @brief defines >= operation for ScomRegisterAccess
169 * @param i_rightRegister register to be compared against
170 * @return Returns true if registers is >= i_rightRegister false
171 * otherwise
172 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500173 bool operator >= ( const HardwareRegister & i_rightRegister ) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500174
175 /** @return The register access level (see enum AccessLevel). */
176 virtual AccessLevel getAccessLevel() const { return iv_operationType; }
177
178 /** @brief Sets the register access level (see enum AccessLevel). */
179 virtual void setAccessLevel( AccessLevel i_op ) { iv_operationType = i_op; }
180
181 protected: // Functions
182
183 /**
184 * @brief copy constructor
185 * @param i_scomRegister scomRegister instance to be copied
186 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500187 HardwareRegister( const Register & i_scomRegister ):
Zane Shelley23244cb2019-08-30 21:12:12 -0500188 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500189 iv_bitLength( i_scomRegister.GetBitLength() ),
190 iv_shortId( i_scomRegister.GetId() ),
191 iv_chipType( i_scomRegister.getChipType() ),
192 iv_scomAddress( i_scomRegister.GetAddress() ),
193 iv_operationType( i_scomRegister.getAccessLevel() )
194 {}
195
196 /**
197 * @brief Returns reference to bit string associated with register
198 * @return Refer to function description
199 */
200 virtual BitString & AccessBitString( );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500201
202private: // functions
203
204 friend class CaptureData;
205
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500206 private: // Data
207
208 uint32_t iv_bitLength; // bit length of scom
209 uint16_t iv_shortId; // unique hash id of register
210 TARGETING::TYPE iv_chipType; // type of target associated with register
211 uint64_t iv_scomAddress; // scom address associated with regiser
212 AccessLevel iv_operationType; // Operation supported (RO, WO, or RW)
213
Zane Shelleyb77b5732019-08-30 22:01:06 -0500214#endif
Zane Shelley61565dc2019-09-18 21:57:10 -0500215
216 private: // Hardware accessor class variable
217
218 /** @brief A simple class that stores the chip used to access hardware. */
219 class Accessor
220 {
221 public:
222
223 /**
224 * @brief Constructor.
225 * @param i_chip The chip used to access hardware.
226 */
227 explicit Accessor( const Chip & i_chip ) :
228 iv_chip( i_chip )
229 {}
230
231 /** @brief Destructor. */
232 ~Accessor() = default;
233
234 /** @brief Copy constructor. */
235 Accessor( const Accessor & ) = delete;
236
237 /** @brief Assignment operator. */
238 Accessor & operator=( const Accessor & ) = delete;
239
240 /** @return The chip used to access hardware. */
241 const Chip & getChip() const { return iv_chip; }
242
243 private:
244
245 /**
246 * A Chip object provided by the user application. The isolator does not
247 * know anything about this object nor how to use it. Its only purpose
248 * is to get passed back to the user application for hardware access
249 * operations.
250 */
251 const Chip iv_chip;
252
253 }; // end class Accessor
254
255 /**
256 * This allows all HardwareRegister objects access to a chip via the user
257 * interface APIs. It is intentially defined as a pointer. It can be set to
258 * nullptr to signify that access is restricted at this time. This is useful
259 * to prevent users from accidentally accessing registers on the wrong chip.
260 * It is recommended to use setAccessor() and clearAccessor() to manage this
261 * variable.
262 */
263 static Accessor * cv_accessor;
264
265 public: // Hardware accessor management functions.
266
267 /**
268 * @brief Initializes a new hardware accessor.
269 * @param i_chip The chip used to access hardware.
270 */
271 static void setAccessor( const Chip & i_chip )
272 {
273 clearAccessor();
274 cv_accessor = new Accessor( i_chip );
275 }
276
277 /** @brief Deletes the current hardware accessor. */
278 static void clearAccessor()
279 {
280 delete cv_accessor;
281 cv_accessor = nullptr;
282 }
283
284 private: // Hardware accessor management functions.
285
286 /** @return The chip stored in cv_accessor. */
287 const Chip & getAccessorChip() const
288 {
289 HEI_ASSERT( nullptr != cv_accessor );
290
291#if 0
292 // Extra sanity check to verify this register belongs on the target
293 // accessor chip.
294 HEI_ASSERT( getChipType() != cv_accessor->getChip().getChipType() );
295#endif
296
297 return cv_accessor->getChip();
298 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500299
300 private: // Register cache class variable
301
302 /**
303 * @brief Caches the contents of registers read from hardware.
304 *
305 * The goal is to create a snapshot of the hardware register contents as
306 * close to the reported attention as possible. This snapshot is then used
307 * for additional analysis/debug when needed.
308 */
309 class Cache
310 {
311 public:
312
313 /** @brief Default constructor. */
314 Cache() = default;
315
316 /** @brief Destructor. */
317 ~Cache() = default;
318
319 /** @brief Copy constructor. */
320 Cache( const Cache & ) = delete;
321
322 /** @brief Assignment operator. */
323 Cache & operator=( const Cache & ) = delete;
324
325 /**
326 * @brief Queries if a specific entry exists in the cache.
327 * @param i_chip The target chip.
328 * @param i_hwReg The target register.
329 * @return True if the entry exists, false otherwise.
330 */
331 bool query( const Chip & i_chip,
332 const HardwareRegister * i_hwReg ) const;
333
334 /**
335 * @brief Returns the data buffer for the given chip and register.
336 * @param i_chip The target chip.
337 * @param i_hwReg The target register.
338 * @return A reference to the BitString containing the register data.
339 * @note If an entry does not exist in the cache, an entry will be
340 * created and the BitString will be initialized to 0.
341 */
342 BitString & access( const Chip & i_chip,
343 const HardwareRegister * i_hwReg );
344
345 /** @brief Flushes entire contents from cache. */
346 void flush();
347
348 /**
349 * @brief Removes a single register from the cache.
350 * @param i_chip The target chip.
351 * @param i_hwReg The target register.
352 */
353 void flush( const Chip & i_chip, const HardwareRegister * i_hwReg );
354
355 private:
356
357 /**
358 * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
359 *
360 * The HardwareRegister keys will just be pointers to the isolation
361 * objects created in the main initialize() API. Those should exist
362 * until the main uninitialize() API is called. It is important that the
363 * cache is flushed at the beginning of the uninitialize() API before
364 * the rest of the isolation objects are deleted.
365 *
366 * The Chip keys are copies of the objects passed to the isolator
367 * because the user application is responsible for storage of the
368 * objects passed to the isolator. We don't want to chance a Chip was
369 * created as a local variable that goes out of scope, or other similar
370 * situations.
371 */
372 std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
373 };
374
375 /** This allows all HardwareRegister objects access to the cache. */
376 static Cache cv_cache;
377
378 public: // Register cache management functions.
379
380 /** @brief Flushes the entire register cache. */
381 static void flushAll() { cv_cache.flush(); }
382
383 private: // Register cache management functions.
384
385 /** @return True if an entry for this register exist in this cache. */
386 bool queryCache() const
387 {
388 return cv_cache.query( getAccessorChip(), this );
389 }
390
391 /** @return A reference to this register's BitString in cache. */
392 BitString & accessCache() const
393 {
394 return cv_cache.access( getAccessorChip(), this );
395 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500396};
397
Zane Shelley871adec2019-07-30 11:01:39 -0500398} // end namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500399