blob: 3d2f97491bca9fd804e5717ff391dba23c496322 [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/**
Zane Shelley8deb0902019-10-14 15:52:27 -050021 * @brief An abstract class containing information (e.g. address, type, length,
22 * etc.) for an actual hardware register.
Zane Shelley61565dc2019-09-18 21:57:10 -050023 *
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 Shelley8deb0902019-10-14 15:52:27 -050055 /** @brief Pure virtual destructor. */
56 virtual ~HardwareRegister() = 0;
57
58 protected:
59
60 /**
61 * @brief Constructor from components.
62 * @param i_chipType Type of chip associated with this register.
63 * @param i_id Unique ID for this register.
64 * @param i_instance Instance of this register
65 * @param i_accessLevel Hardware access level for this register.
66 */
67 HardwareRegister( ChipType_t i_chipType, RegisterId_t i_id,
68 RegisterInstance_t i_instance,
69 RegisterAccessLevel_t i_accessLevel ) :
70 Register(), iv_chipType( i_chipType ), iv_id( i_id ),
71 iv_instance( i_instance ), iv_accessLevel( i_accessLevel )
72 {}
73
74 private: // Instance variables
75
76 /** The type of chip associated with register. */
77 const ChipType_t iv_chipType;
78
79 /** The unique ID for this register. */
80 const RegisterId_t iv_id;
81
82 /** A register may have multiple instances. All of which will have the same
83 * ID. This variable is used to distinguish between each instance of the
84 * register. */
85 const RegisterInstance_t iv_instance;
86
87 /** The hardware access level of this register (read/write, read-only,
88 * write-only, etc.). */
89 const RegisterAccessLevel_t iv_accessLevel;
90
91 public: // Accessor functions
92
93 /** @return The type of chip associated with this register. */
94 ChipType_t getChipType() const { return iv_chipType; }
95
96 /* @return The unique ID for this register. */
97 RegisterId_t getId() const { return iv_id; }
98
99 /* @return The instance of this register. */
100 RegisterInstance_t getInstance() const { return iv_instance; }
101
102 /** @return The hardware access level of this register. */
103 RegisterAccessLevel_t getAccessLevel() const { return iv_accessLevel; }
104
105 // NOTE: The following are determined by child classes.
106
107 /** @return This register's type. */
108 virtual RegisterType_t getRegisterType() const = 0;
109
110 /** @return The address of this register. */
111 virtual RegisterAddress_t getAddress() const = 0;
112
113 /** @return The size (in bytes) of this register. */
114 virtual size_t getSize() const = 0;
115
116 public:
117
Zane Shelley61565dc2019-09-18 21:57:10 -0500118#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500119 /**
120 * @brief constructor
121 * @param i_address address of the register
122 * @param i_bitLength bit length of register
123 * @param i_targetType target type associated with register
124 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500125 HardwareRegister( uint64_t i_address, uint32_t i_bitLength,
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500126 TARGETING::TYPE i_targetType, AccessLevel i_access ) :
Zane Shelley23244cb2019-08-30 21:12:12 -0500127 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500128 iv_bitLength( i_bitLength ),
129 iv_chipType( i_targetType ),
130 iv_scomAddress( i_address ),
131 iv_operationType( i_access )
132 {}
133
134 /**
135 * @brief constructor .Added this because we save object of this type in
136 * @ FlyweightS
137 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500138 HardwareRegister():
Zane Shelley23244cb2019-08-30 21:12:12 -0500139 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500140 iv_bitLength( 0 ),
141 iv_chipType( TARGETING::TYPE_NA ),
142 iv_scomAddress( 0 ),
143 iv_operationType( ACCESS_NONE )
144 {}
Zane Shelley65ed96a2019-10-14 13:06:11 -0500145#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500146
Zane Shelley65ed96a2019-10-14 13:06:11 -0500147 /** Function overloaded from parent Register class. */
148 virtual const BitString * getBitString() const { return nullptr; }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500149
Zane Shelley65ed96a2019-10-14 13:06:11 -0500150#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500151 /**
152 * @brief Updates bit string contents associated with register
153 * @param i_bs poiner to bit string
154 * @return Nil
155 */
156
157 virtual void SetBitString(const BitString * i_bs) ;
158
159 /**
160 * @brief Returns length of the bits string associated with register
161 * @return length of bit string
162 */
163 uint32_t GetBitLength(void) const { return iv_bitLength ;}
Zane Shelley61565dc2019-09-18 21:57:10 -0500164#endif
Zane Shelleyd0af3582019-09-19 10:48:59 -0500165 size_t getByteSize() const { return 8; } // TODO
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500166
167 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500168 * @brief Reads a register from hardware via the user interface APIs.
169 * @param i_force When false, this function will only read from hardware if
170 * an entry for this instance does not already exist in the
171 * register cache. When true, the entry in the register
172 * cache is flushed, if it exists. Then this function will
173 * read from hardware and update the cache.
174 * @return See the return code from the registerRead() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500175 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500176 ReturnCode read( bool i_force = false ) const;
177
178 #ifndef __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500179
180 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500181 * @brief Writes the value stored in the register cache to hardware via the
182 * user interface APIs.
183 * @return See the return code from the registerWrite() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500184 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500185 ReturnCode write() const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500186
Zane Shelley61565dc2019-09-18 21:57:10 -0500187 #endif // __HEI_READ_ONLY
188
189#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500190 /**
191 * @brief Returns the hash id of register
192 * @return returns hash id of register
193 * @pre None
194 * @post None
195 * @note
196 */
197 virtual uint16_t GetId(void) const { return iv_shortId; };
198
199 /**
200 * @brief Sets the hash id of register
201 * @param i_id hash id of register
202 * @return Nil
203 */
204 virtual void SetId(uint16_t i_id) { iv_shortId = i_id; };
205
206 /**
207 * @brief Returns type of Target associated with register.
208 * @return Refer to function description
209 */
210 TARGETING::TYPE getChipType()const{ return iv_chipType ;} ;
211 /**
212 * @brief Returns scom address of register
213 * @return Refer to function description
214 */
215 uint64_t GetAddress( ) const {return iv_scomAddress ;};
Zane Shelley65ed96a2019-10-14 13:06:11 -0500216#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500217 /**
218 * @brief compares two ScomRegisterAccess register for equality
219 * @param i_rightRegister register to be compared against
220 * @return Returns true if registers are equal false otherwise
221 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500222 bool operator == ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500223 /**
224 * @brief defines < operation for ScomRegisterAccess
225 * @param i_rightRegister register to be compared against
226 * @return Returns false if i_rightRegisters is less and true otherwise
227 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500228 bool operator < ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelley65ed96a2019-10-14 13:06:11 -0500229#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500230 /**
231 * @brief defines >= operation for ScomRegisterAccess
232 * @param i_rightRegister register to be compared against
233 * @return Returns true if registers is >= i_rightRegister false
234 * otherwise
235 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500236 bool operator >= ( const HardwareRegister & i_rightRegister ) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500237
238 /** @return The register access level (see enum AccessLevel). */
239 virtual AccessLevel getAccessLevel() const { return iv_operationType; }
240
241 /** @brief Sets the register access level (see enum AccessLevel). */
242 virtual void setAccessLevel( AccessLevel i_op ) { iv_operationType = i_op; }
243
244 protected: // Functions
245
246 /**
247 * @brief copy constructor
248 * @param i_scomRegister scomRegister instance to be copied
249 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500250 HardwareRegister( const Register & i_scomRegister ):
Zane Shelley23244cb2019-08-30 21:12:12 -0500251 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500252 iv_bitLength( i_scomRegister.GetBitLength() ),
253 iv_shortId( i_scomRegister.GetId() ),
254 iv_chipType( i_scomRegister.getChipType() ),
255 iv_scomAddress( i_scomRegister.GetAddress() ),
256 iv_operationType( i_scomRegister.getAccessLevel() )
257 {}
258
259 /**
260 * @brief Returns reference to bit string associated with register
261 * @return Refer to function description
262 */
263 virtual BitString & AccessBitString( );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500264
265private: // functions
266
267 friend class CaptureData;
268
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500269 private: // Data
270
271 uint32_t iv_bitLength; // bit length of scom
272 uint16_t iv_shortId; // unique hash id of register
273 TARGETING::TYPE iv_chipType; // type of target associated with register
274 uint64_t iv_scomAddress; // scom address associated with regiser
275 AccessLevel iv_operationType; // Operation supported (RO, WO, or RW)
276
Zane Shelleyb77b5732019-08-30 22:01:06 -0500277#endif
Zane Shelley61565dc2019-09-18 21:57:10 -0500278
279 private: // Hardware accessor class variable
280
281 /** @brief A simple class that stores the chip used to access hardware. */
282 class Accessor
283 {
284 public:
285
286 /**
287 * @brief Constructor.
288 * @param i_chip The chip used to access hardware.
289 */
290 explicit Accessor( const Chip & i_chip ) :
291 iv_chip( i_chip )
292 {}
293
294 /** @brief Destructor. */
295 ~Accessor() = default;
296
297 /** @brief Copy constructor. */
298 Accessor( const Accessor & ) = delete;
299
300 /** @brief Assignment operator. */
301 Accessor & operator=( const Accessor & ) = delete;
302
303 /** @return The chip used to access hardware. */
304 const Chip & getChip() const { return iv_chip; }
305
306 private:
307
308 /**
309 * A Chip object provided by the user application. The isolator does not
310 * know anything about this object nor how to use it. Its only purpose
311 * is to get passed back to the user application for hardware access
312 * operations.
313 */
314 const Chip iv_chip;
315
316 }; // end class Accessor
317
318 /**
319 * This allows all HardwareRegister objects access to a chip via the user
320 * interface APIs. It is intentially defined as a pointer. It can be set to
321 * nullptr to signify that access is restricted at this time. This is useful
322 * to prevent users from accidentally accessing registers on the wrong chip.
323 * It is recommended to use setAccessor() and clearAccessor() to manage this
324 * variable.
325 */
326 static Accessor * cv_accessor;
327
328 public: // Hardware accessor management functions.
329
330 /**
331 * @brief Initializes a new hardware accessor.
332 * @param i_chip The chip used to access hardware.
333 */
334 static void setAccessor( const Chip & i_chip )
335 {
336 clearAccessor();
337 cv_accessor = new Accessor( i_chip );
338 }
339
340 /** @brief Deletes the current hardware accessor. */
341 static void clearAccessor()
342 {
343 delete cv_accessor;
344 cv_accessor = nullptr;
345 }
346
347 private: // Hardware accessor management functions.
348
349 /** @return The chip stored in cv_accessor. */
350 const Chip & getAccessorChip() const
351 {
352 HEI_ASSERT( nullptr != cv_accessor );
353
354#if 0
355 // Extra sanity check to verify this register belongs on the target
356 // accessor chip.
357 HEI_ASSERT( getChipType() != cv_accessor->getChip().getChipType() );
358#endif
359
360 return cv_accessor->getChip();
361 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500362
363 private: // Register cache class variable
364
365 /**
366 * @brief Caches the contents of registers read from hardware.
367 *
368 * The goal is to create a snapshot of the hardware register contents as
369 * close to the reported attention as possible. This snapshot is then used
370 * for additional analysis/debug when needed.
371 */
372 class Cache
373 {
374 public:
375
376 /** @brief Default constructor. */
377 Cache() = default;
378
379 /** @brief Destructor. */
380 ~Cache() = default;
381
382 /** @brief Copy constructor. */
383 Cache( const Cache & ) = delete;
384
385 /** @brief Assignment operator. */
386 Cache & operator=( const Cache & ) = delete;
387
388 /**
389 * @brief Queries if a specific entry exists in the cache.
390 * @param i_chip The target chip.
391 * @param i_hwReg The target register.
392 * @return True if the entry exists, false otherwise.
393 */
394 bool query( const Chip & i_chip,
395 const HardwareRegister * i_hwReg ) const;
396
397 /**
398 * @brief Returns the data buffer for the given chip and register.
399 * @param i_chip The target chip.
400 * @param i_hwReg The target register.
401 * @return A reference to the BitString containing the register data.
402 * @note If an entry does not exist in the cache, an entry will be
403 * created and the BitString will be initialized to 0.
404 */
405 BitString & access( const Chip & i_chip,
406 const HardwareRegister * i_hwReg );
407
408 /** @brief Flushes entire contents from cache. */
409 void flush();
410
411 /**
412 * @brief Removes a single register from the cache.
413 * @param i_chip The target chip.
414 * @param i_hwReg The target register.
415 */
416 void flush( const Chip & i_chip, const HardwareRegister * i_hwReg );
417
418 private:
419
420 /**
421 * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
422 *
423 * The HardwareRegister keys will just be pointers to the isolation
424 * objects created in the main initialize() API. Those should exist
425 * until the main uninitialize() API is called. It is important that the
426 * cache is flushed at the beginning of the uninitialize() API before
427 * the rest of the isolation objects are deleted.
428 *
429 * The Chip keys are copies of the objects passed to the isolator
430 * because the user application is responsible for storage of the
431 * objects passed to the isolator. We don't want to chance a Chip was
432 * created as a local variable that goes out of scope, or other similar
433 * situations.
434 */
435 std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
436 };
437
438 /** This allows all HardwareRegister objects access to the cache. */
439 static Cache cv_cache;
440
441 public: // Register cache management functions.
442
443 /** @brief Flushes the entire register cache. */
444 static void flushAll() { cv_cache.flush(); }
445
446 private: // Register cache management functions.
447
448 /** @return True if an entry for this register exist in this cache. */
449 bool queryCache() const
450 {
451 return cv_cache.query( getAccessorChip(), this );
452 }
453
454 /** @return A reference to this register's BitString in cache. */
455 BitString & accessCache() const
456 {
457 return cv_cache.access( getAccessorChip(), this );
458 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500459};
460
Zane Shelley871adec2019-07-30 11:01:39 -0500461} // end namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500462