blob: ead7b16eeb41c08ec2f3d60f467b7ce64d30deb5 [file] [log] [blame]
Zane Shelley871adec2019-07-30 11:01:39 -05001#pragma once
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05002
Zane Shelley52cb1a92019-08-21 14:38:31 -05003#include <hei_includes.hpp>
4#include <register/hei_register.hpp>
5#include <util/hei_bit_string.hpp>
6
Zane Shelley871adec2019-07-30 11:01:39 -05007namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05008{
9
Zane Shelley61565dc2019-09-18 21:57:10 -050010/**
Zane Shelley8deb0902019-10-14 15:52:27 -050011 * @brief An abstract class containing information (e.g. address, type, length,
12 * etc.) for an actual hardware register.
Zane Shelley61565dc2019-09-18 21:57:10 -050013 *
14 * Hardware access:
15 *
16 * Actual hardware access is defined by the user application via the user
17 * interface APIs. In order to tell the user application which chip to target,
Zane Shelley53efc352019-10-03 21:46:39 -050018 * the user application will give the isolator a list of pointers to its
19 * objects. They will then be passed into the public functions of this class
20 * and eventually given back to the user application when hardware access is
21 * needed.
Zane Shelleyd0af3582019-09-19 10:48:59 -050022 *
23 * Register cache:
24 *
25 * In order to save memory space, each instance of this class does not store
26 * the contents of the target hardware register. Instead, that data is stored
Paul Greenwood6574f6e2019-09-17 09:43:22 -050027 * in a register cache, which is a static variable defined in this class. This
Zane Shelleyd0af3582019-09-19 10:48:59 -050028 * allows us to store only what we need. The cache can also be thought of as a
29 * snapshot of the registers at the time of isolation, which can be useful if
30 * the hardware is still running and register values could change.
31 *
32 * In order to ensure stale data isn't used from the cache, call
33 * HardwareRegister::flushAll() before beginning isolation on a new attention.
34 * Also, HardwareRegister::flushAll() should be called when the isolator is
35 * uninitialized before the rest of the isolation objects are deleted.
Zane Shelley61565dc2019-09-18 21:57:10 -050036 */
Zane Shelleycd36f432019-08-30 21:22:07 -050037class HardwareRegister : public Register
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050038{
39 public:
40
Zane Shelley8deb0902019-10-14 15:52:27 -050041 /** @brief Pure virtual destructor. */
42 virtual ~HardwareRegister() = 0;
43
44 protected:
45
46 /**
47 * @brief Constructor from components.
48 * @param i_chipType Type of chip associated with this register.
49 * @param i_id Unique ID for this register.
50 * @param i_instance Instance of this register
51 * @param i_accessLevel Hardware access level for this register.
52 */
53 HardwareRegister( ChipType_t i_chipType, RegisterId_t i_id,
54 RegisterInstance_t i_instance,
55 RegisterAccessLevel_t i_accessLevel ) :
56 Register(), iv_chipType( i_chipType ), iv_id( i_id ),
57 iv_instance( i_instance ), iv_accessLevel( i_accessLevel )
58 {}
59
60 private: // Instance variables
61
62 /** The type of chip associated with register. */
63 const ChipType_t iv_chipType;
64
65 /** The unique ID for this register. */
66 const RegisterId_t iv_id;
67
68 /** A register may have multiple instances. All of which will have the same
69 * ID. This variable is used to distinguish between each instance of the
70 * register. */
71 const RegisterInstance_t iv_instance;
72
73 /** The hardware access level of this register (read/write, read-only,
74 * write-only, etc.). */
75 const RegisterAccessLevel_t iv_accessLevel;
76
77 public: // Accessor functions
78
79 /** @return The type of chip associated with this register. */
80 ChipType_t getChipType() const { return iv_chipType; }
81
82 /* @return The unique ID for this register. */
83 RegisterId_t getId() const { return iv_id; }
84
85 /* @return The instance of this register. */
86 RegisterInstance_t getInstance() const { return iv_instance; }
87
88 /** @return The hardware access level of this register. */
89 RegisterAccessLevel_t getAccessLevel() const { return iv_accessLevel; }
90
91 // NOTE: The following are determined by child classes.
92
93 /** @return This register's type. */
94 virtual RegisterType_t getRegisterType() const = 0;
95
96 /** @return The address of this register. */
97 virtual RegisterAddress_t getAddress() const = 0;
98
99 /** @return The size (in bytes) of this register. */
100 virtual size_t getSize() const = 0;
101
Zane Shelley75e68e92019-10-18 16:16:23 -0500102 public: // Operators
103
104 /** @brief Equals operator. */
105 bool operator==( const HardwareRegister & i_r ) const
106 {
107 // Comparing register type, chip type, and address should be sufficient.
108 return ( getRegisterType() == i_r.getRegisterType() ) &&
109 ( getChipType() == i_r.getChipType() ) &&
110 ( getAddress() == i_r.getAddress() );
111 }
112
113 /** @brief Less than operator. */
114 bool operator<( const HardwareRegister & i_r ) const
115 {
116 // Comparing register type, chip type, and address should be sufficient.
117 if ( getRegisterType() < i_r.getRegisterType() )
118 {
119 return true;
120 }
121 else if ( getRegisterType() == i_r.getRegisterType() )
122 {
123 if ( getChipType() < i_r.getChipType() )
124 {
125 return true;
126 }
127 else if ( getChipType() == i_r.getChipType() )
128 {
129 return ( getAddress() < i_r.getAddress() );
130 }
131 }
132
133 return false;
134 }
135
Zane Shelley8deb0902019-10-14 15:52:27 -0500136 public:
137
Zane Shelley65ed96a2019-10-14 13:06:11 -0500138 /** Function overloaded from parent Register class. */
Zane Shelleyafa669a2019-10-15 13:23:17 -0500139 const BitString * getBitString( const Chip & i_chip ) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500140
Zane Shelley65ed96a2019-10-14 13:06:11 -0500141#if 0
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500142 /**
143 * @brief Updates bit string contents associated with register
144 * @param i_bs poiner to bit string
145 * @return Nil
146 */
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500147 virtual void setBitString(const BitString * i_bs) ;
Zane Shelley61565dc2019-09-18 21:57:10 -0500148#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500149
150 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500151 * @brief Reads a register from hardware via the user interface APIs.
Zane Shelley53efc352019-10-03 21:46:39 -0500152 * @param i_chip The target chip in which this register belongs.
Zane Shelley61565dc2019-09-18 21:57:10 -0500153 * @param i_force When false, this function will only read from hardware if
154 * an entry for this instance does not already exist in the
155 * register cache. When true, the entry in the register
156 * cache is flushed, if it exists. Then this function will
157 * read from hardware and update the cache.
158 * @return See the return code from the registerRead() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500159 */
Zane Shelley53efc352019-10-03 21:46:39 -0500160 ReturnCode read( const Chip & i_chip, bool i_force = false ) const;
Zane Shelley61565dc2019-09-18 21:57:10 -0500161
162 #ifndef __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500163
164 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500165 * @brief Writes the value stored in the register cache to hardware via the
166 * user interface APIs.
Zane Shelley53efc352019-10-03 21:46:39 -0500167 * @param i_chip The target chip in which this register belongs.
Zane Shelley61565dc2019-09-18 21:57:10 -0500168 * @return See the return code from the registerWrite() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500169 */
Zane Shelley53efc352019-10-03 21:46:39 -0500170 ReturnCode write( const Chip & i_chip ) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500171
Zane Shelley61565dc2019-09-18 21:57:10 -0500172 #endif // __HEI_READ_ONLY
173
Zane Shelleyafa669a2019-10-15 13:23:17 -0500174 protected:
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500175
176 /**
Zane Shelleyafa669a2019-10-15 13:23:17 -0500177 * @brief Provides access to this register's BitString.
178 *
179 * WARNING: Allowing public access to this function may be dangerous. For
180 * now it should be left as protected.
181 *
Zane Shelley53efc352019-10-03 21:46:39 -0500182 * @param i_chip The target chip in which this register belongs.
Zane Shelleyafa669a2019-10-15 13:23:17 -0500183 * @return A reference to the BitString.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500184 */
Zane Shelleyafa669a2019-10-15 13:23:17 -0500185 BitString & accessBitString( const Chip & i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -0500186
Zane Shelley61565dc2019-09-18 21:57:10 -0500187 private: // Hardware accessor management functions.
188
Zane Shelley53efc352019-10-03 21:46:39 -0500189 /** @brief Asserts this register belongs on the target accessor chip. */
190 void verifyAccessorChip( const Chip & i_chip ) const
Zane Shelley61565dc2019-09-18 21:57:10 -0500191 {
Zane Shelley53efc352019-10-03 21:46:39 -0500192 HEI_ASSERT( getChipType() == i_chip.getType() );
Zane Shelley61565dc2019-09-18 21:57:10 -0500193 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500194
195 private: // Register cache class variable
196
197 /**
198 * @brief Caches the contents of registers read from hardware.
199 *
200 * The goal is to create a snapshot of the hardware register contents as
201 * close to the reported attention as possible. This snapshot is then used
202 * for additional analysis/debug when needed.
203 */
204 class Cache
205 {
206 public:
207
208 /** @brief Default constructor. */
209 Cache() = default;
210
211 /** @brief Destructor. */
212 ~Cache() = default;
213
214 /** @brief Copy constructor. */
215 Cache( const Cache & ) = delete;
216
217 /** @brief Assignment operator. */
218 Cache & operator=( const Cache & ) = delete;
219
220 /**
221 * @brief Queries if a specific entry exists in the cache.
222 * @param i_chip The target chip.
223 * @param i_hwReg The target register.
224 * @return True if the entry exists, false otherwise.
225 */
226 bool query( const Chip & i_chip,
227 const HardwareRegister * i_hwReg ) const;
228
229 /**
230 * @brief Returns the data buffer for the given chip and register.
231 * @param i_chip The target chip.
232 * @param i_hwReg The target register.
233 * @return A reference to the BitString containing the register data.
234 * @note If an entry does not exist in the cache, an entry will be
235 * created and the BitString will be initialized to 0.
236 */
237 BitString & access( const Chip & i_chip,
238 const HardwareRegister * i_hwReg );
239
240 /** @brief Flushes entire contents from cache. */
241 void flush();
242
243 /**
244 * @brief Removes a single register from the cache.
245 * @param i_chip The target chip.
246 * @param i_hwReg The target register.
247 */
248 void flush( const Chip & i_chip, const HardwareRegister * i_hwReg );
249
250 private:
251
252 /**
253 * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
254 *
255 * The HardwareRegister keys will just be pointers to the isolation
256 * objects created in the main initialize() API. Those should exist
257 * until the main uninitialize() API is called. It is important that the
258 * cache is flushed at the beginning of the uninitialize() API before
259 * the rest of the isolation objects are deleted.
260 *
261 * The Chip keys are copies of the objects passed to the isolator
262 * because the user application is responsible for storage of the
263 * objects passed to the isolator. We don't want to chance a Chip was
264 * created as a local variable that goes out of scope, or other similar
265 * situations.
266 */
267 std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
268 };
269
270 /** This allows all HardwareRegister objects access to the cache. */
271 static Cache cv_cache;
272
273 public: // Register cache management functions.
274
275 /** @brief Flushes the entire register cache. */
276 static void flushAll() { cv_cache.flush(); }
277
Zane Shelley53efc352019-10-03 21:46:39 -0500278 /**
279 * @brief Flushes this register from the cache.
280 * @param i_chip The target chip in which this register belongs.
281 */
282 void flush( const Chip & i_chip ) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500283 {
Zane Shelley53efc352019-10-03 21:46:39 -0500284 cv_cache.flush( i_chip, this );
Zane Shelleyd0af3582019-09-19 10:48:59 -0500285 }
286
Zane Shelley53efc352019-10-03 21:46:39 -0500287 private: // Register cache management functions.
288
289 /**
290 * @param i_chip The target chip in which this register belongs.
291 * @return True if an entry for this register exist in this cache.
292 */
293 bool queryCache( const Chip & i_chip ) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500294 {
Zane Shelley53efc352019-10-03 21:46:39 -0500295 return cv_cache.query( i_chip, this );
296 }
297
298 /**
299 * @param i_chip The target chip in which this register belongs.
300 * @return A reference to this register's BitString in cache.
301 */
302 BitString & accessCache( const Chip & i_chip ) const
303 {
304 return cv_cache.access( i_chip, this );
Zane Shelleyd0af3582019-09-19 10:48:59 -0500305 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500306};
307
Zane Shelley871adec2019-07-30 11:01:39 -0500308} // end namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500309