blob: b990fc92aad7ff5717dab796418a30adc0798dae [file] [log] [blame]
Zane Shelley61565dc2019-09-18 21:57:10 -05001#include <hei_user_interface.hpp>
Zane Shelley52cb1a92019-08-21 14:38:31 -05002#include <register/hei_hardware_register.hpp>
Zane Shelley995be6c2021-02-24 15:48:55 -06003#include <util/hei_bit_string.hpp>
Zane Shelleyd5073512021-01-14 12:51:18 -06004#include <util/hei_includes.hpp>
Zane Shelley52cb1a92019-08-21 14:38:31 -05005
Zane Shelley871adec2019-07-30 11:01:39 -05006namespace libhei
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05007{
8
Zane Shelley8deb0902019-10-14 15:52:27 -05009//------------------------------------------------------------------------------
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050010
Zane Shelley8deb0902019-10-14 15:52:27 -050011HardwareRegister::~HardwareRegister() {}
12
13//------------------------------------------------------------------------------
14
Zane Shelleyfe27b652019-10-28 11:33:07 -050015const BitString* HardwareRegister::getBitString(const Chip& i_chip) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050016{
Paul Greenwood6574f6e2019-09-17 09:43:22 -050017 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050018 // entry has at been synched with hardware at least once. Note that we
19 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050020 // will be created in the cache, if it does not exist, when the cache is
Zane Shelley53efc352019-10-03 21:46:39 -050021 // accessed below.
Zane Shelleyd0af3582019-09-19 10:48:59 -050022
Zane Shelley7667b712020-05-11 20:45:40 -050023 if (queryAttrFlag(REG_ATTR_ACCESS_READ))
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050024 {
Zane Shelley83da2452019-10-25 15:45:34 -050025 read(i_chip);
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050026 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050027
Zane Shelley83da2452019-10-25 15:45:34 -050028 return &(accessCache(i_chip));
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050029}
30
31//------------------------------------------------------------------------------
32
Zane Shelleyfe27b652019-10-28 11:33:07 -050033BitString& HardwareRegister::accessBitString(const Chip& i_chip)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050034{
Paul Greenwood6574f6e2019-09-17 09:43:22 -050035 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050036 // entry has at been synched with hardware at least once. Note that we
37 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050038 // will be created in the cache, if it does not exist, when the cache is
Zane Shelley53efc352019-10-03 21:46:39 -050039 // accessed below.
Zane Shelleyd0af3582019-09-19 10:48:59 -050040
Zane Shelley7667b712020-05-11 20:45:40 -050041 if (queryAttrFlag(REG_ATTR_ACCESS_READ))
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050042 {
Zane Shelley83da2452019-10-25 15:45:34 -050043 read(i_chip);
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050044 }
45
Zane Shelley83da2452019-10-25 15:45:34 -050046 return accessCache(i_chip);
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050047}
48
49//------------------------------------------------------------------------------
50
Zane Shelley2f4aa912020-05-08 14:28:18 -050051bool HardwareRegister::read(const Chip& i_chip, bool i_force) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050052{
Zane Shelley2f4aa912020-05-08 14:28:18 -050053 bool accessFailure = false;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050054
Zane Shelley2d4981a2020-06-04 14:32:45 -050055 // This register must be readable.
56 HEI_ASSERT(queryAttrFlag(REG_ATTR_ACCESS_READ));
57
Zane Shelley61565dc2019-09-18 21:57:10 -050058 // Read from hardware only if the read is forced or the entry for this
59 // instance does not exist in the cache.
Zane Shelley83da2452019-10-25 15:45:34 -050060 if (i_force || !queryCache(i_chip))
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050061 {
Zane Shelley61565dc2019-09-18 21:57:10 -050062 // Read this register from hardware.
Patrick Williams2f7537d2023-05-10 07:51:39 -050063 uint64_t val = 0;
Zane Shelley2d4981a2020-06-04 14:32:45 -050064 accessFailure = registerRead(i_chip, getType(), getAddress(), val);
65 if (!accessFailure)
Zane Shelley61565dc2019-09-18 21:57:10 -050066 {
Zane Shelley2d4981a2020-06-04 14:32:45 -050067 // Get the buffer from the register cache.
68 BitString& bs = accessCache(i_chip);
69
70 // Set this value in the bit string buffer.
71 bs.setFieldRight(0, bs.getBitLen(), val);
Zane Shelley61565dc2019-09-18 21:57:10 -050072 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050073 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050074
Zane Shelley2f4aa912020-05-08 14:28:18 -050075 return accessFailure;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050076}
77
78//------------------------------------------------------------------------------
79
Ben Tyner7b3420b2020-05-11 10:52:07 -050080#ifdef __HEI_ENABLE_HW_WRITE
Zane Shelley61565dc2019-09-18 21:57:10 -050081
Zane Shelley2f4aa912020-05-08 14:28:18 -050082bool HardwareRegister::write(const Chip& i_chip) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050083{
Zane Shelley61565dc2019-09-18 21:57:10 -050084 // This register must be writable.
Zane Shelley7667b712020-05-11 20:45:40 -050085 HEI_ASSERT(queryAttrFlag(REG_ATTR_ACCESS_WRITE));
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050086
Zane Shelley61565dc2019-09-18 21:57:10 -050087 // An entry for this register must exist in the cache.
Zane Shelley83da2452019-10-25 15:45:34 -050088 HEI_ASSERT(queryCache(i_chip));
Zane Shelley61565dc2019-09-18 21:57:10 -050089
90 // Get the buffer from the register cache.
Zane Shelleyfe27b652019-10-28 11:33:07 -050091 BitString& bs = accessCache(i_chip);
Zane Shelley61565dc2019-09-18 21:57:10 -050092
Zane Shelley2d4981a2020-06-04 14:32:45 -050093 // Set this value from the bit string buffer.
94 uint64_t val = bs.getFieldRight(0, bs.getBitLen());
Zane Shelley61565dc2019-09-18 21:57:10 -050095
96 // Write to this register to hardware.
Zane Shelley2d4981a2020-06-04 14:32:45 -050097 return registerWrite(i_chip, getType(), getAddress(), val);
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050098}
99
Ben Tyner7b3420b2020-05-11 10:52:07 -0500100#endif // __HEI_ENABLE_HW_WRITE
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500101
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500102//------------------------------------------------------------------------------
103
Caleb Palmere4ad4e32024-08-07 09:48:14 -0500104void HardwareRegister::setBit(const Chip& i_chip, uint64_t i_pos) const
105{
106 // Get the buffer from the register cache.
107 BitString& bs = accessCache(i_chip);
108 bs.setBit(i_pos);
109}
110
111//------------------------------------------------------------------------------
112
113void HardwareRegister::setAllBits(const Chip& i_chip) const
114{
115 // Get the buffer from the register cache.
116 BitString& bs = accessCache(i_chip);
117 bs.setAll();
118}
119
120//------------------------------------------------------------------------------
121
122void HardwareRegister::clearBit(const Chip& i_chip, uint64_t i_pos) const
123{
124 // Get the buffer from the register cache.
125 BitString& bs = accessCache(i_chip);
126 bs.clearBit(i_pos);
127}
128
129//------------------------------------------------------------------------------
130
131void HardwareRegister::clearAllBits(const Chip& i_chip) const
132{
133 // Get the buffer from the register cache.
134 BitString& bs = accessCache(i_chip);
135 bs.clearAll();
136}
137
138//------------------------------------------------------------------------------
139
Zane Shelleyc4771992019-10-28 22:01:49 -0500140HardwareRegister::Cache HardwareRegister::cv_cache{};
Zane Shelleyd0af3582019-09-19 10:48:59 -0500141
142//------------------------------------------------------------------------------
143
Zane Shelleyfe27b652019-10-28 11:33:07 -0500144bool HardwareRegister::Cache::query(const Chip& i_chip,
145 const HardwareRegister* i_hwReg) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500146{
147 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500148 auto chipPairItr = iv_cache.find(i_chip);
149 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500150 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500151 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500152
153 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500154 auto hwRegPairItr = hwRegMap.find(i_hwReg);
155 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500156 {
157 return true;
158 }
159 }
160
161 return false;
162}
163
164//------------------------------------------------------------------------------
165
Zane Shelleyfe27b652019-10-28 11:33:07 -0500166BitString& HardwareRegister::Cache::access(const Chip& i_chip,
Zane Shelleyc4771992019-10-28 22:01:49 -0500167 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500168{
169 // If the entry does not exist, create a new entry.
Zane Shelley83da2452019-10-25 15:45:34 -0500170 if (!query(i_chip, i_hwReg))
Zane Shelleyd0af3582019-09-19 10:48:59 -0500171 {
Zane Shelleyc4771992019-10-28 22:01:49 -0500172 BitString* bs = new BitStringBuffer{i_hwReg->getSize() * 8};
Zane Shelley7c8faa12019-10-28 22:26:28 -0500173
Zane Shelleyd0af3582019-09-19 10:48:59 -0500174 iv_cache[i_chip][i_hwReg] = bs;
175 }
176
177 // Return a reference to the target entry.
178 return *(iv_cache[i_chip][i_hwReg]);
179}
180
181//------------------------------------------------------------------------------
182
183void HardwareRegister::Cache::flush()
184{
185 // Delete all of the BitStrings.
Zane Shelley5a78fa82022-09-16 16:49:58 -0500186 for (const auto& chipPair : iv_cache)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500187 {
Zane Shelley5a78fa82022-09-16 16:49:58 -0500188 for (const auto& hwRegPair : chipPair.second)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500189 {
190 delete hwRegPair.second;
191 }
192 }
193
194 // !!! Do not delete the HardwareRegisters !!!
195 // Those are deleted when the main uninitialize() API is called.
196
197 // Flush the rest of the cache.
198 iv_cache.clear();
199}
200
201//------------------------------------------------------------------------------
202
Zane Shelleyfe27b652019-10-28 11:33:07 -0500203void HardwareRegister::Cache::flush(const Chip& i_chip,
204 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500205{
206 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500207 auto chipPairItr = iv_cache.find(i_chip);
208 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500209 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500210 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500211
212 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500213 auto hwRegPairItr = hwRegMap.find(i_hwReg);
214 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500215 {
216 delete hwRegPairItr->second; // delete the BitString
217 hwRegMap.erase(i_hwReg); // remove the entry for this register
218 }
219
220 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
221 // the cache.
Zane Shelley83da2452019-10-25 15:45:34 -0500222 if (hwRegMap.empty())
Zane Shelleyd0af3582019-09-19 10:48:59 -0500223 {
224 iv_cache.erase(i_chip);
225 }
226 }
227}
228
229//------------------------------------------------------------------------------
230
Zane Shelley871adec2019-07-30 11:01:39 -0500231} // end namespace libhei