blob: 7588a6c8e29ec19a8682c02360ceee3fa23c824d [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 {}
82
83 /**
84 * @brief Returns the pointer to bit string
85 * @param i_type attention type
86 * @return BitString * pointer to bit string
87 */
88
89 virtual const BitString * GetBitString(ATTENTION_TYPE i_type =
90 INVALID_ATTENTION_TYPE) const;
91 /**
92 * @brief Updates bit string contents associated with register
93 * @param i_bs poiner to bit string
94 * @return Nil
95 */
96
97 virtual void SetBitString(const BitString * i_bs) ;
98
99 /**
100 * @brief Returns length of the bits string associated with register
101 * @return length of bit string
102 */
103 uint32_t GetBitLength(void) const { return iv_bitLength ;}
Zane Shelley61565dc2019-09-18 21:57:10 -0500104#endif
Zane Shelleyd0af3582019-09-19 10:48:59 -0500105 size_t getByteSize() const { return 8; } // TODO
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500106
107 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500108 * @brief Reads a register from hardware via the user interface APIs.
109 * @param i_force When false, this function will only read from hardware if
110 * an entry for this instance does not already exist in the
111 * register cache. When true, the entry in the register
112 * cache is flushed, if it exists. Then this function will
113 * read from hardware and update the cache.
114 * @return See the return code from the registerRead() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500115 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500116 ReturnCode read( bool i_force = false ) const;
117
118 #ifndef __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500119
120 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500121 * @brief Writes the value stored in the register cache to hardware via the
122 * user interface APIs.
123 * @return See the return code from the registerWrite() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500124 */
Zane Shelley61565dc2019-09-18 21:57:10 -0500125 ReturnCode write() const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500126
Zane Shelley61565dc2019-09-18 21:57:10 -0500127 #endif // __HEI_READ_ONLY
128
129#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500130 /**
131 * @brief Returns the hash id of register
132 * @return returns hash id of register
133 * @pre None
134 * @post None
135 * @note
136 */
137 virtual uint16_t GetId(void) const { return iv_shortId; };
138
139 /**
140 * @brief Sets the hash id of register
141 * @param i_id hash id of register
142 * @return Nil
143 */
144 virtual void SetId(uint16_t i_id) { iv_shortId = i_id; };
145
146 /**
147 * @brief Returns type of Target associated with register.
148 * @return Refer to function description
149 */
150 TARGETING::TYPE getChipType()const{ return iv_chipType ;} ;
151 /**
152 * @brief Returns scom address of register
153 * @return Refer to function description
154 */
155 uint64_t GetAddress( ) const {return iv_scomAddress ;};
156 /**
157 * @brief compares two ScomRegisterAccess register for equality
158 * @param i_rightRegister register to be compared against
159 * @return Returns true if registers are equal false otherwise
160 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500161 bool operator == ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500162 /**
163 * @brief defines < operation for ScomRegisterAccess
164 * @param i_rightRegister register to be compared against
165 * @return Returns false if i_rightRegisters is less and true otherwise
166 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500167 bool operator < ( const HardwareRegister & i_rightRegister ) const ;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500168 /**
169 * @brief defines >= operation for ScomRegisterAccess
170 * @param i_rightRegister register to be compared against
171 * @return Returns true if registers is >= i_rightRegister false
172 * otherwise
173 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500174 bool operator >= ( const HardwareRegister & i_rightRegister ) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500175
176 /** @return The register access level (see enum AccessLevel). */
177 virtual AccessLevel getAccessLevel() const { return iv_operationType; }
178
179 /** @brief Sets the register access level (see enum AccessLevel). */
180 virtual void setAccessLevel( AccessLevel i_op ) { iv_operationType = i_op; }
181
182 protected: // Functions
183
184 /**
185 * @brief copy constructor
186 * @param i_scomRegister scomRegister instance to be copied
187 */
Zane Shelleycd36f432019-08-30 21:22:07 -0500188 HardwareRegister( const Register & i_scomRegister ):
Zane Shelley23244cb2019-08-30 21:12:12 -0500189 Register(),
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500190 iv_bitLength( i_scomRegister.GetBitLength() ),
191 iv_shortId( i_scomRegister.GetId() ),
192 iv_chipType( i_scomRegister.getChipType() ),
193 iv_scomAddress( i_scomRegister.GetAddress() ),
194 iv_operationType( i_scomRegister.getAccessLevel() )
195 {}
196
197 /**
198 * @brief Returns reference to bit string associated with register
199 * @return Refer to function description
200 */
201 virtual BitString & AccessBitString( );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500202
203private: // functions
204
205 friend class CaptureData;
206
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500207 private: // Data
208
209 uint32_t iv_bitLength; // bit length of scom
210 uint16_t iv_shortId; // unique hash id of register
211 TARGETING::TYPE iv_chipType; // type of target associated with register
212 uint64_t iv_scomAddress; // scom address associated with regiser
213 AccessLevel iv_operationType; // Operation supported (RO, WO, or RW)
214
Zane Shelleyb77b5732019-08-30 22:01:06 -0500215#endif
Zane Shelley61565dc2019-09-18 21:57:10 -0500216
217 private: // Hardware accessor class variable
218
219 /** @brief A simple class that stores the chip used to access hardware. */
220 class Accessor
221 {
222 public:
223
224 /**
225 * @brief Constructor.
226 * @param i_chip The chip used to access hardware.
227 */
228 explicit Accessor( const Chip & i_chip ) :
229 iv_chip( i_chip )
230 {}
231
232 /** @brief Destructor. */
233 ~Accessor() = default;
234
235 /** @brief Copy constructor. */
236 Accessor( const Accessor & ) = delete;
237
238 /** @brief Assignment operator. */
239 Accessor & operator=( const Accessor & ) = delete;
240
241 /** @return The chip used to access hardware. */
242 const Chip & getChip() const { return iv_chip; }
243
244 private:
245
246 /**
247 * A Chip object provided by the user application. The isolator does not
248 * know anything about this object nor how to use it. Its only purpose
249 * is to get passed back to the user application for hardware access
250 * operations.
251 */
252 const Chip iv_chip;
253
254 }; // end class Accessor
255
256 /**
257 * This allows all HardwareRegister objects access to a chip via the user
258 * interface APIs. It is intentially defined as a pointer. It can be set to
259 * nullptr to signify that access is restricted at this time. This is useful
260 * to prevent users from accidentally accessing registers on the wrong chip.
261 * It is recommended to use setAccessor() and clearAccessor() to manage this
262 * variable.
263 */
264 static Accessor * cv_accessor;
265
266 public: // Hardware accessor management functions.
267
268 /**
269 * @brief Initializes a new hardware accessor.
270 * @param i_chip The chip used to access hardware.
271 */
272 static void setAccessor( const Chip & i_chip )
273 {
274 clearAccessor();
275 cv_accessor = new Accessor( i_chip );
276 }
277
278 /** @brief Deletes the current hardware accessor. */
279 static void clearAccessor()
280 {
281 delete cv_accessor;
282 cv_accessor = nullptr;
283 }
284
285 private: // Hardware accessor management functions.
286
287 /** @return The chip stored in cv_accessor. */
288 const Chip & getAccessorChip() const
289 {
290 HEI_ASSERT( nullptr != cv_accessor );
291
292#if 0
293 // Extra sanity check to verify this register belongs on the target
294 // accessor chip.
295 HEI_ASSERT( getChipType() != cv_accessor->getChip().getChipType() );
296#endif
297
298 return cv_accessor->getChip();
299 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500300
301 private: // Register cache class variable
302
303 /**
304 * @brief Caches the contents of registers read from hardware.
305 *
306 * The goal is to create a snapshot of the hardware register contents as
307 * close to the reported attention as possible. This snapshot is then used
308 * for additional analysis/debug when needed.
309 */
310 class Cache
311 {
312 public:
313
314 /** @brief Default constructor. */
315 Cache() = default;
316
317 /** @brief Destructor. */
318 ~Cache() = default;
319
320 /** @brief Copy constructor. */
321 Cache( const Cache & ) = delete;
322
323 /** @brief Assignment operator. */
324 Cache & operator=( const Cache & ) = delete;
325
326 /**
327 * @brief Queries if a specific entry exists in the cache.
328 * @param i_chip The target chip.
329 * @param i_hwReg The target register.
330 * @return True if the entry exists, false otherwise.
331 */
332 bool query( const Chip & i_chip,
333 const HardwareRegister * i_hwReg ) const;
334
335 /**
336 * @brief Returns the data buffer for the given chip and register.
337 * @param i_chip The target chip.
338 * @param i_hwReg The target register.
339 * @return A reference to the BitString containing the register data.
340 * @note If an entry does not exist in the cache, an entry will be
341 * created and the BitString will be initialized to 0.
342 */
343 BitString & access( const Chip & i_chip,
344 const HardwareRegister * i_hwReg );
345
346 /** @brief Flushes entire contents from cache. */
347 void flush();
348
349 /**
350 * @brief Removes a single register from the cache.
351 * @param i_chip The target chip.
352 * @param i_hwReg The target register.
353 */
354 void flush( const Chip & i_chip, const HardwareRegister * i_hwReg );
355
356 private:
357
358 /**
359 * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
360 *
361 * The HardwareRegister keys will just be pointers to the isolation
362 * objects created in the main initialize() API. Those should exist
363 * until the main uninitialize() API is called. It is important that the
364 * cache is flushed at the beginning of the uninitialize() API before
365 * the rest of the isolation objects are deleted.
366 *
367 * The Chip keys are copies of the objects passed to the isolator
368 * because the user application is responsible for storage of the
369 * objects passed to the isolator. We don't want to chance a Chip was
370 * created as a local variable that goes out of scope, or other similar
371 * situations.
372 */
373 std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
374 };
375
376 /** This allows all HardwareRegister objects access to the cache. */
377 static Cache cv_cache;
378
379 public: // Register cache management functions.
380
381 /** @brief Flushes the entire register cache. */
382 static void flushAll() { cv_cache.flush(); }
383
384 private: // Register cache management functions.
385
386 /** @return True if an entry for this register exist in this cache. */
387 bool queryCache() const
388 {
389 return cv_cache.query( getAccessorChip(), this );
390 }
391
392 /** @return A reference to this register's BitString in cache. */
393 BitString & accessCache() const
394 {
395 return cv_cache.access( getAccessorChip(), this );
396 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500397};
398
Zane Shelley871adec2019-07-30 11:01:39 -0500399} // end namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500400