blob: fe71c75564a1314f911be07d057b8387b0a82296 [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:
Zane Shelley8deb0902019-10-14 15:52:27 -050040 /** @brief Pure virtual destructor. */
41 virtual ~HardwareRegister() = 0;
42
43 protected:
Zane Shelley8deb0902019-10-14 15:52:27 -050044 /**
45 * @brief Constructor from components.
Zane Shelley7667b712020-05-11 20:45:40 -050046 * @param i_chipType Type of chip associated with this register.
47 * @param i_id Unique ID for this register.
48 * @param i_instance Instance of this register
49 * @param i_flags Attribute flags for this register.
Zane Shelley8deb0902019-10-14 15:52:27 -050050 */
Zane Shelley83da2452019-10-25 15:45:34 -050051 HardwareRegister(ChipType_t i_chipType, RegisterId_t i_id,
Zane Shelley7667b712020-05-11 20:45:40 -050052 Instance_t i_instance, RegisterAttributeFlags_t i_flags) :
Zane Shelley7f7a42d2019-10-28 13:28:31 -050053 Register(),
54 iv_chipType(i_chipType), iv_id(i_id), iv_instance(i_instance),
Zane Shelley7667b712020-05-11 20:45:40 -050055 iv_flags(i_flags)
Zane Shelley8deb0902019-10-14 15:52:27 -050056 {}
57
58 private: // Instance variables
Zane Shelley8deb0902019-10-14 15:52:27 -050059 /** The type of chip associated with register. */
60 const ChipType_t iv_chipType;
61
62 /** The unique ID for this register. */
63 const RegisterId_t iv_id;
64
65 /** A register may have multiple instances. All of which will have the same
66 * ID. This variable is used to distinguish between each instance of the
67 * register. */
Zane Shelley13b182b2020-05-07 20:23:45 -050068 const Instance_t iv_instance;
Zane Shelley8deb0902019-10-14 15:52:27 -050069
70 /** The hardware access level of this register (read/write, read-only,
71 * write-only, etc.). */
Zane Shelley7667b712020-05-11 20:45:40 -050072 const RegisterAttributeFlags_t iv_flags;
Zane Shelley8deb0902019-10-14 15:52:27 -050073
74 public: // Accessor functions
Zane Shelley8deb0902019-10-14 15:52:27 -050075 /** @return The type of chip associated with this register. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050076 ChipType_t getChipType() const
77 {
78 return iv_chipType;
79 }
Zane Shelley8deb0902019-10-14 15:52:27 -050080
81 /* @return The unique ID for this register. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050082 RegisterId_t getId() const
83 {
84 return iv_id;
85 }
Zane Shelley8deb0902019-10-14 15:52:27 -050086
87 /* @return The instance of this register. */
Zane Shelley13b182b2020-05-07 20:23:45 -050088 Instance_t getInstance() const
Zane Shelley7f7a42d2019-10-28 13:28:31 -050089 {
90 return iv_instance;
91 }
Zane Shelley8deb0902019-10-14 15:52:27 -050092
Zane Shelley7667b712020-05-11 20:45:40 -050093 /** @return True if given flag is enabled, false if disabled. */
94 bool queryAttrFlag(RegisterAttributeFlags_t i_flag) const
Zane Shelley7f7a42d2019-10-28 13:28:31 -050095 {
Zane Shelley7667b712020-05-11 20:45:40 -050096 return (0 != (iv_flags & i_flag));
Zane Shelley7f7a42d2019-10-28 13:28:31 -050097 }
Zane Shelley8deb0902019-10-14 15:52:27 -050098
99 // NOTE: The following are determined by child classes.
100
101 /** @return This register's type. */
102 virtual RegisterType_t getRegisterType() const = 0;
103
104 /** @return The address of this register. */
105 virtual RegisterAddress_t getAddress() const = 0;
106
107 /** @return The size (in bytes) of this register. */
108 virtual size_t getSize() const = 0;
109
Zane Shelley75e68e92019-10-18 16:16:23 -0500110 public: // Operators
Zane Shelley75e68e92019-10-18 16:16:23 -0500111 /** @brief Equals operator. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500112 bool operator==(const HardwareRegister& i_r) const
Zane Shelley75e68e92019-10-18 16:16:23 -0500113 {
114 // Comparing register type, chip type, and address should be sufficient.
Zane Shelley83da2452019-10-25 15:45:34 -0500115 return (getRegisterType() == i_r.getRegisterType()) &&
Zane Shelley7c8faa12019-10-28 22:26:28 -0500116 (getChipType() == i_r.getChipType()) &&
117 (getAddress() == i_r.getAddress());
Zane Shelley75e68e92019-10-18 16:16:23 -0500118 }
119
120 /** @brief Less than operator. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500121 bool operator<(const HardwareRegister& i_r) const
Zane Shelley75e68e92019-10-18 16:16:23 -0500122 {
123 // Comparing register type, chip type, and address should be sufficient.
Zane Shelley83da2452019-10-25 15:45:34 -0500124 if (getRegisterType() < i_r.getRegisterType())
Zane Shelley75e68e92019-10-18 16:16:23 -0500125 {
126 return true;
127 }
Zane Shelley83da2452019-10-25 15:45:34 -0500128 else if (getRegisterType() == i_r.getRegisterType())
Zane Shelley75e68e92019-10-18 16:16:23 -0500129 {
Zane Shelley83da2452019-10-25 15:45:34 -0500130 if (getChipType() < i_r.getChipType())
Zane Shelley75e68e92019-10-18 16:16:23 -0500131 {
132 return true;
133 }
Zane Shelley83da2452019-10-25 15:45:34 -0500134 else if (getChipType() == i_r.getChipType())
Zane Shelley75e68e92019-10-18 16:16:23 -0500135 {
Zane Shelley83da2452019-10-25 15:45:34 -0500136 return (getAddress() < i_r.getAddress());
Zane Shelley75e68e92019-10-18 16:16:23 -0500137 }
138 }
139
140 return false;
141 }
142
Zane Shelley8deb0902019-10-14 15:52:27 -0500143 public:
Zane Shelley65ed96a2019-10-14 13:06:11 -0500144 /** Function overloaded from parent Register class. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500145 const BitString* getBitString(const Chip& i_chip) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500146
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500147 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500148 * @brief Reads a register from hardware via the user interface APIs.
Zane Shelley53efc352019-10-03 21:46:39 -0500149 * @param i_chip The target chip in which this register belongs.
Zane Shelley61565dc2019-09-18 21:57:10 -0500150 * @param i_force When false, this function will only read from hardware if
151 * an entry for this instance does not already exist in the
152 * register cache. When true, the entry in the register
153 * cache is flushed, if it exists. Then this function will
154 * read from hardware and update the cache.
155 * @return See the return code from the registerRead() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500156 */
Zane Shelley2f4aa912020-05-08 14:28:18 -0500157 bool read(const Chip& i_chip, bool i_force = false) const;
Zane Shelley61565dc2019-09-18 21:57:10 -0500158
Ben Tyner7b3420b2020-05-11 10:52:07 -0500159#ifdef __HEI_ENABLE_HW_WRITE
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500160
161 /**
Zane Shelley61565dc2019-09-18 21:57:10 -0500162 * @brief Writes the value stored in the register cache to hardware via the
163 * user interface APIs.
Zane Shelley53efc352019-10-03 21:46:39 -0500164 * @param i_chip The target chip in which this register belongs.
Zane Shelley61565dc2019-09-18 21:57:10 -0500165 * @return See the return code from the registerWrite() user interface API.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500166 */
Zane Shelley2f4aa912020-05-08 14:28:18 -0500167 bool write(const Chip& i_chip) const;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500168
Ben Tyner7b3420b2020-05-11 10:52:07 -0500169#endif // __HEI_ENABLE_HW_WRITE
Zane Shelley61565dc2019-09-18 21:57:10 -0500170
Zane Shelleyafa669a2019-10-15 13:23:17 -0500171 protected:
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500172 /**
Zane Shelleyafa669a2019-10-15 13:23:17 -0500173 * @brief Provides access to this register's BitString.
174 *
175 * WARNING: Allowing public access to this function may be dangerous. For
176 * now it should be left as protected.
177 *
Zane Shelley53efc352019-10-03 21:46:39 -0500178 * @param i_chip The target chip in which this register belongs.
Zane Shelleyafa669a2019-10-15 13:23:17 -0500179 * @return A reference to the BitString.
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500180 */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500181 BitString& accessBitString(const Chip& i_chip);
Zane Shelley61565dc2019-09-18 21:57:10 -0500182
Zane Shelley61565dc2019-09-18 21:57:10 -0500183 private: // Hardware accessor management functions.
Zane Shelley53efc352019-10-03 21:46:39 -0500184 /** @brief Asserts this register belongs on the target accessor chip. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500185 void verifyAccessorChip(const Chip& i_chip) const
Zane Shelley61565dc2019-09-18 21:57:10 -0500186 {
Zane Shelley83da2452019-10-25 15:45:34 -0500187 HEI_ASSERT(getChipType() == i_chip.getType());
Zane Shelley61565dc2019-09-18 21:57:10 -0500188 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500189
190 private: // Register cache class variable
Zane Shelleyd0af3582019-09-19 10:48:59 -0500191 /**
192 * @brief Caches the contents of registers read from hardware.
193 *
194 * The goal is to create a snapshot of the hardware register contents as
195 * close to the reported attention as possible. This snapshot is then used
196 * for additional analysis/debug when needed.
197 */
198 class Cache
199 {
200 public:
Zane Shelleyd0af3582019-09-19 10:48:59 -0500201 /** @brief Default constructor. */
202 Cache() = default;
203
204 /** @brief Destructor. */
205 ~Cache() = default;
206
207 /** @brief Copy constructor. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500208 Cache(const Cache&) = delete;
Zane Shelleyd0af3582019-09-19 10:48:59 -0500209
210 /** @brief Assignment operator. */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500211 Cache& operator=(const Cache&) = delete;
Zane Shelleyd0af3582019-09-19 10:48:59 -0500212
213 /**
214 * @brief Queries if a specific entry exists in the cache.
215 * @param i_chip The target chip.
216 * @param i_hwReg The target register.
217 * @return True if the entry exists, false otherwise.
218 */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500219 bool query(const Chip& i_chip, const HardwareRegister* i_hwReg) const;
Zane Shelleyd0af3582019-09-19 10:48:59 -0500220
221 /**
222 * @brief Returns the data buffer for the given chip and register.
223 * @param i_chip The target chip.
224 * @param i_hwReg The target register.
225 * @return A reference to the BitString containing the register data.
226 * @note If an entry does not exist in the cache, an entry will be
227 * created and the BitString will be initialized to 0.
228 */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500229 BitString& access(const Chip& i_chip, const HardwareRegister* i_hwReg);
Zane Shelleyd0af3582019-09-19 10:48:59 -0500230
231 /** @brief Flushes entire contents from cache. */
232 void flush();
233
234 /**
235 * @brief Removes a single register from the cache.
236 * @param i_chip The target chip.
237 * @param i_hwReg The target register.
238 */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500239 void flush(const Chip& i_chip, const HardwareRegister* i_hwReg);
Zane Shelleyd0af3582019-09-19 10:48:59 -0500240
241 private:
Zane Shelleyd0af3582019-09-19 10:48:59 -0500242 /**
243 * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
244 *
245 * The HardwareRegister keys will just be pointers to the isolation
246 * objects created in the main initialize() API. Those should exist
247 * until the main uninitialize() API is called. It is important that the
248 * cache is flushed at the beginning of the uninitialize() API before
249 * the rest of the isolation objects are deleted.
250 *
251 * The Chip keys are copies of the objects passed to the isolator
252 * because the user application is responsible for storage of the
253 * objects passed to the isolator. We don't want to chance a Chip was
254 * created as a local variable that goes out of scope, or other similar
255 * situations.
256 */
257 std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
258 };
259
260 /** This allows all HardwareRegister objects access to the cache. */
261 static Cache cv_cache;
262
263 public: // Register cache management functions.
Zane Shelleyd0af3582019-09-19 10:48:59 -0500264 /** @brief Flushes the entire register cache. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500265 static void flushAll()
266 {
267 cv_cache.flush();
268 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500269
Zane Shelley53efc352019-10-03 21:46:39 -0500270 /**
271 * @brief Flushes this register from the cache.
272 * @param i_chip The target chip in which this register belongs.
273 */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500274 void flush(const Chip& i_chip) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500275 {
Zane Shelley83da2452019-10-25 15:45:34 -0500276 cv_cache.flush(i_chip, this);
Zane Shelleyd0af3582019-09-19 10:48:59 -0500277 }
278
Zane Shelley53efc352019-10-03 21:46:39 -0500279 private: // Register cache management functions.
Zane Shelley53efc352019-10-03 21:46:39 -0500280 /**
281 * @param i_chip The target chip in which this register belongs.
282 * @return True if an entry for this register exist in this cache.
283 */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500284 bool queryCache(const Chip& i_chip) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500285 {
Zane Shelley83da2452019-10-25 15:45:34 -0500286 return cv_cache.query(i_chip, this);
Zane Shelley53efc352019-10-03 21:46:39 -0500287 }
288
289 /**
290 * @param i_chip The target chip in which this register belongs.
291 * @return A reference to this register's BitString in cache.
292 */
Zane Shelleyfe27b652019-10-28 11:33:07 -0500293 BitString& accessCache(const Chip& i_chip) const
Zane Shelley53efc352019-10-03 21:46:39 -0500294 {
Zane Shelley83da2452019-10-25 15:45:34 -0500295 return cv_cache.access(i_chip, this);
Zane Shelleyd0af3582019-09-19 10:48:59 -0500296 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500297};
298
Zane Shelley871adec2019-07-30 11:01:39 -0500299} // end namespace libhei