blob: 2d2167e752213972c8df47dc161b2338a3b99a34 [file] [log] [blame]
Zane Shelley52cb1a92019-08-21 14:38:31 -05001#include <hei_includes.hpp>
Zane Shelley61565dc2019-09-18 21:57:10 -05002#include <hei_user_interface.hpp>
Zane Shelley52cb1a92019-08-21 14:38:31 -05003#include <register/hei_hardware_register.hpp>
4#include <util/hei_bit_string.hpp>
5
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 Shelley61565dc2019-09-18 21:57:10 -050055 // Read from hardware only if the read is forced or the entry for this
56 // instance does not exist in the cache.
Zane Shelley83da2452019-10-25 15:45:34 -050057 if (i_force || !queryCache(i_chip))
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050058 {
Zane Shelley61565dc2019-09-18 21:57:10 -050059 // This register must be readable.
Zane Shelley7667b712020-05-11 20:45:40 -050060 HEI_ASSERT(queryAttrFlag(REG_ATTR_ACCESS_READ));
Zane Shelley61565dc2019-09-18 21:57:10 -050061
62 // Get the buffer from the register cache.
Zane Shelleyfe27b652019-10-28 11:33:07 -050063 BitString& bs = accessCache(i_chip);
Zane Shelley61565dc2019-09-18 21:57:10 -050064
65 // Get the byte size of the buffer.
Zane Shelley83da2452019-10-25 15:45:34 -050066 size_t sz_buffer = BitString::getMinBytes(bs.getBitLen());
Zane Shelley61565dc2019-09-18 21:57:10 -050067
68 // Read this register from hardware.
Zane Shelley2f4aa912020-05-08 14:28:18 -050069 accessFailure = registerRead(i_chip, bs.getBufAddr(), sz_buffer,
Zane Shelley5ec88102020-05-11 21:08:25 -050070 getType(), getAddress());
Zane Shelley2f4aa912020-05-08 14:28:18 -050071 if (accessFailure)
Zane Shelley61565dc2019-09-18 21:57:10 -050072 {
73 // The read failed and we can't trust what was put in the register
74 // cache. So remove this instance's entry from the cache.
Zane Shelley83da2452019-10-25 15:45:34 -050075 flush(i_chip);
Zane Shelley61565dc2019-09-18 21:57:10 -050076 }
77 else
78 {
79 // Sanity check. The returned size of the data written to the buffer
80 // should match the register size.
Zane Shelley83da2452019-10-25 15:45:34 -050081 HEI_ASSERT(getSize() == sz_buffer);
Zane Shelley61565dc2019-09-18 21:57:10 -050082 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050083 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050084
Zane Shelley2f4aa912020-05-08 14:28:18 -050085 return accessFailure;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050086}
87
88//------------------------------------------------------------------------------
89
Ben Tyner7b3420b2020-05-11 10:52:07 -050090#ifdef __HEI_ENABLE_HW_WRITE
Zane Shelley61565dc2019-09-18 21:57:10 -050091
Zane Shelley2f4aa912020-05-08 14:28:18 -050092bool HardwareRegister::write(const Chip& i_chip) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050093{
Zane Shelley2f4aa912020-05-08 14:28:18 -050094 bool accessFailure = false;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050095
Zane Shelley61565dc2019-09-18 21:57:10 -050096 // This register must be writable.
Zane Shelley7667b712020-05-11 20:45:40 -050097 HEI_ASSERT(queryAttrFlag(REG_ATTR_ACCESS_WRITE));
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050098
Zane Shelley61565dc2019-09-18 21:57:10 -050099 // An entry for this register must exist in the cache.
Zane Shelley83da2452019-10-25 15:45:34 -0500100 HEI_ASSERT(queryCache(i_chip));
Zane Shelley61565dc2019-09-18 21:57:10 -0500101
102 // Get the buffer from the register cache.
Zane Shelleyfe27b652019-10-28 11:33:07 -0500103 BitString& bs = accessCache(i_chip);
Zane Shelley61565dc2019-09-18 21:57:10 -0500104
105 // Get the byte size of the buffer.
Zane Shelley83da2452019-10-25 15:45:34 -0500106 size_t sz_buffer = BitString::getMinBytes(bs.getBitLen());
Zane Shelley61565dc2019-09-18 21:57:10 -0500107
108 // Write to this register to hardware.
Zane Shelley5ec88102020-05-11 21:08:25 -0500109 accessFailure = registerWrite(i_chip, bs.getBufAddr(), sz_buffer, getType(),
110 getAddress());
Zane Shelley61565dc2019-09-18 21:57:10 -0500111
Zane Shelley2f4aa912020-05-08 14:28:18 -0500112 if (accessFailure)
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500113 {
Zane Shelley61565dc2019-09-18 21:57:10 -0500114 // Sanity check. The returned size of the data written to the buffer
115 // should match the register size.
Zane Shelley83da2452019-10-25 15:45:34 -0500116 HEI_ASSERT(getSize() == sz_buffer);
Zane Shelley61565dc2019-09-18 21:57:10 -0500117 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500118
Zane Shelley2f4aa912020-05-08 14:28:18 -0500119 return accessFailure;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500120}
121
Ben Tyner7b3420b2020-05-11 10:52:07 -0500122#endif // __HEI_ENABLE_HW_WRITE
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500123
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500124//------------------------------------------------------------------------------
125
Zane Shelleyc4771992019-10-28 22:01:49 -0500126HardwareRegister::Cache HardwareRegister::cv_cache{};
Zane Shelleyd0af3582019-09-19 10:48:59 -0500127
128//------------------------------------------------------------------------------
129
Zane Shelleyfe27b652019-10-28 11:33:07 -0500130bool HardwareRegister::Cache::query(const Chip& i_chip,
131 const HardwareRegister* i_hwReg) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500132{
133 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500134 auto chipPairItr = iv_cache.find(i_chip);
135 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500136 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500137 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500138
139 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500140 auto hwRegPairItr = hwRegMap.find(i_hwReg);
141 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500142 {
143 return true;
144 }
145 }
146
147 return false;
148}
149
150//------------------------------------------------------------------------------
151
Zane Shelleyfe27b652019-10-28 11:33:07 -0500152BitString& HardwareRegister::Cache::access(const Chip& i_chip,
Zane Shelleyc4771992019-10-28 22:01:49 -0500153 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500154{
155 // If the entry does not exist, create a new entry.
Zane Shelley83da2452019-10-25 15:45:34 -0500156 if (!query(i_chip, i_hwReg))
Zane Shelleyd0af3582019-09-19 10:48:59 -0500157 {
Zane Shelleyc4771992019-10-28 22:01:49 -0500158 BitString* bs = new BitStringBuffer{i_hwReg->getSize() * 8};
Zane Shelley7c8faa12019-10-28 22:26:28 -0500159
Zane Shelleyd0af3582019-09-19 10:48:59 -0500160 iv_cache[i_chip][i_hwReg] = bs;
161 }
162
163 // Return a reference to the target entry.
164 return *(iv_cache[i_chip][i_hwReg]);
165}
166
167//------------------------------------------------------------------------------
168
169void HardwareRegister::Cache::flush()
170{
171 // Delete all of the BitStrings.
Zane Shelleyfe27b652019-10-28 11:33:07 -0500172 for (auto& chipPair : iv_cache)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500173 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500174 for (auto& hwRegPair : chipPair.second)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500175 {
176 delete hwRegPair.second;
177 }
178 }
179
180 // !!! Do not delete the HardwareRegisters !!!
181 // Those are deleted when the main uninitialize() API is called.
182
183 // Flush the rest of the cache.
184 iv_cache.clear();
185}
186
187//------------------------------------------------------------------------------
188
Zane Shelleyfe27b652019-10-28 11:33:07 -0500189void HardwareRegister::Cache::flush(const Chip& i_chip,
190 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500191{
192 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500193 auto chipPairItr = iv_cache.find(i_chip);
194 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500195 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500196 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500197
198 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500199 auto hwRegPairItr = hwRegMap.find(i_hwReg);
200 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500201 {
202 delete hwRegPairItr->second; // delete the BitString
203 hwRegMap.erase(i_hwReg); // remove the entry for this register
204 }
205
206 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
207 // the cache.
Zane Shelley83da2452019-10-25 15:45:34 -0500208 if (hwRegMap.empty())
Zane Shelleyd0af3582019-09-19 10:48:59 -0500209 {
210 iv_cache.erase(i_chip);
211 }
212 }
213}
214
215//------------------------------------------------------------------------------
216
Zane Shelley871adec2019-07-30 11:01:39 -0500217} // end namespace libhei