blob: 78e92a9780a243d854a1bab40ac3eb57e03c0292 [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.
Zane Shelley2d4981a2020-06-04 14:32:45 -050063 uint64_t val = 0;
64 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
Zane Shelleyc4771992019-10-28 22:01:49 -0500104HardwareRegister::Cache HardwareRegister::cv_cache{};
Zane Shelleyd0af3582019-09-19 10:48:59 -0500105
106//------------------------------------------------------------------------------
107
Zane Shelleyfe27b652019-10-28 11:33:07 -0500108bool HardwareRegister::Cache::query(const Chip& i_chip,
109 const HardwareRegister* i_hwReg) const
Zane Shelleyd0af3582019-09-19 10:48:59 -0500110{
111 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500112 auto chipPairItr = iv_cache.find(i_chip);
113 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500114 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500115 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500116
117 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500118 auto hwRegPairItr = hwRegMap.find(i_hwReg);
119 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500120 {
121 return true;
122 }
123 }
124
125 return false;
126}
127
128//------------------------------------------------------------------------------
129
Zane Shelleyfe27b652019-10-28 11:33:07 -0500130BitString& HardwareRegister::Cache::access(const Chip& i_chip,
Zane Shelleyc4771992019-10-28 22:01:49 -0500131 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500132{
133 // If the entry does not exist, create a new entry.
Zane Shelley83da2452019-10-25 15:45:34 -0500134 if (!query(i_chip, i_hwReg))
Zane Shelleyd0af3582019-09-19 10:48:59 -0500135 {
Zane Shelleyc4771992019-10-28 22:01:49 -0500136 BitString* bs = new BitStringBuffer{i_hwReg->getSize() * 8};
Zane Shelley7c8faa12019-10-28 22:26:28 -0500137
Zane Shelleyd0af3582019-09-19 10:48:59 -0500138 iv_cache[i_chip][i_hwReg] = bs;
139 }
140
141 // Return a reference to the target entry.
142 return *(iv_cache[i_chip][i_hwReg]);
143}
144
145//------------------------------------------------------------------------------
146
147void HardwareRegister::Cache::flush()
148{
149 // Delete all of the BitStrings.
Zane Shelleyfe27b652019-10-28 11:33:07 -0500150 for (auto& chipPair : iv_cache)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500151 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500152 for (auto& hwRegPair : chipPair.second)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500153 {
154 delete hwRegPair.second;
155 }
156 }
157
158 // !!! Do not delete the HardwareRegisters !!!
159 // Those are deleted when the main uninitialize() API is called.
160
161 // Flush the rest of the cache.
162 iv_cache.clear();
163}
164
165//------------------------------------------------------------------------------
166
Zane Shelleyfe27b652019-10-28 11:33:07 -0500167void HardwareRegister::Cache::flush(const Chip& i_chip,
168 const HardwareRegister* i_hwReg)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500169{
170 // Does i_chip exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500171 auto chipPairItr = iv_cache.find(i_chip);
172 if (iv_cache.end() != chipPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500173 {
Zane Shelleyfe27b652019-10-28 11:33:07 -0500174 auto& hwRegMap = chipPairItr->second; // for ease of use
Zane Shelleyd0af3582019-09-19 10:48:59 -0500175
176 // Does i_hwReg exist in the cache?
Zane Shelley83da2452019-10-25 15:45:34 -0500177 auto hwRegPairItr = hwRegMap.find(i_hwReg);
178 if (hwRegMap.end() != hwRegPairItr)
Zane Shelleyd0af3582019-09-19 10:48:59 -0500179 {
180 delete hwRegPairItr->second; // delete the BitString
181 hwRegMap.erase(i_hwReg); // remove the entry for this register
182 }
183
184 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
185 // the cache.
Zane Shelley83da2452019-10-25 15:45:34 -0500186 if (hwRegMap.empty())
Zane Shelleyd0af3582019-09-19 10:48:59 -0500187 {
188 iv_cache.erase(i_chip);
189 }
190 }
191}
192
193//------------------------------------------------------------------------------
194
Zane Shelley871adec2019-07-30 11:01:39 -0500195} // end namespace libhei