blob: d3c5dd0fa1baeabe55887d55bb4233f7392d9eee [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
15#if 0
Paul Greenwood6574f6e2019-09-17 09:43:22 -050016void HardwareRegister::setBitString( const BitString *bs )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050017{
Paul Greenwood6574f6e2019-09-17 09:43:22 -050018 BitString & l_string = accessBitString();
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050019 l_string.setString(*bs);
20}
Paul Greenwood6574f6e2019-09-17 09:43:22 -050021#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050022
23//------------------------------------------------------------------------------
24
Zane Shelley53efc352019-10-03 21:46:39 -050025const BitString * HardwareRegister::getBitString( const Chip & i_chip ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050026{
Zane Shelley53efc352019-10-03 21:46:39 -050027 // Verify this register belongs on i_chip.
28 verifyAccessorChip( i_chip );
29
Paul Greenwood6574f6e2019-09-17 09:43:22 -050030 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050031 // entry has at been synched with hardware at least once. Note that we
32 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050033 // will be created in the cache, if it does not exist, when the cache is
Zane Shelley53efc352019-10-03 21:46:39 -050034 // accessed below.
Zane Shelleyd0af3582019-09-19 10:48:59 -050035
Paul Greenwood6574f6e2019-09-17 09:43:22 -050036 if ( ( REG_ACCESS_NONE != getAccessLevel() ) &&
37 ( REG_ACCESS_WO != getAccessLevel() ) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050038 {
Zane Shelley53efc352019-10-03 21:46:39 -050039 read( i_chip );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050040 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050041
Zane Shelley53efc352019-10-03 21:46:39 -050042 return &( accessCache(i_chip) );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050043}
44
45//------------------------------------------------------------------------------
46
Paul Greenwood6574f6e2019-09-17 09:43:22 -050047#if 0
Zane Shelley53efc352019-10-03 21:46:39 -050048BitString & HardwareRegister::accessBitString( const Chip & i_chip )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050049{
Zane Shelley53efc352019-10-03 21:46:39 -050050 // Verify this register belongs on i_chip.
51 verifyAccessorChip( i_chip );
52
Paul Greenwood6574f6e2019-09-17 09:43:22 -050053 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050054 // entry has at been synched with hardware at least once. Note that we
55 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050056 // will be created in the cache, if it does not exist, when the cache is
Zane Shelley53efc352019-10-03 21:46:39 -050057 // accessed below.
Zane Shelleyd0af3582019-09-19 10:48:59 -050058
Paul Greenwood6574f6e2019-09-17 09:43:22 -050059 if ( ( REG_ACCESS_NONE != getAccessLevel() ) &&
60 ( REG_ACCESS_WO != getAccessLevel() ) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050061 {
Zane Shelley53efc352019-10-03 21:46:39 -050062 read( i_chip );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050063 }
64
Zane Shelley53efc352019-10-03 21:46:39 -050065 return accessCache( i_chip );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050066}
Zane Shelley61565dc2019-09-18 21:57:10 -050067#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050068
69//------------------------------------------------------------------------------
70
Zane Shelley53efc352019-10-03 21:46:39 -050071ReturnCode HardwareRegister::read( const Chip & i_chip, bool i_force ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050072{
Zane Shelley61565dc2019-09-18 21:57:10 -050073 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050074
Zane Shelley53efc352019-10-03 21:46:39 -050075 // Verify this register belongs on i_chip.
76 verifyAccessorChip( i_chip );
77
Zane Shelley61565dc2019-09-18 21:57:10 -050078 // Read from hardware only if the read is forced or the entry for this
79 // instance does not exist in the cache.
Zane Shelley53efc352019-10-03 21:46:39 -050080 if ( i_force || !queryCache(i_chip) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050081 {
Zane Shelley61565dc2019-09-18 21:57:10 -050082 // This register must be readable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -050083 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
84 ( REG_ACCESS_WO != getAccessLevel() ) );
Zane Shelley61565dc2019-09-18 21:57:10 -050085
86 // Get the buffer from the register cache.
Zane Shelley53efc352019-10-03 21:46:39 -050087 BitString & bs = accessCache( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -050088
89 // Get the byte size of the buffer.
90 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
91
92 // Read this register from hardware.
Zane Shelley53efc352019-10-03 21:46:39 -050093 rc = registerRead( i_chip.getChip(), bs.getBufAddr(),
Zane Shelley61565dc2019-09-18 21:57:10 -050094 sz_buffer, getRegisterType(), getAddress() );
95 if ( RC_SUCCESS != rc )
96 {
97 // The read failed and we can't trust what was put in the register
98 // cache. So remove this instance's entry from the cache.
Zane Shelley53efc352019-10-03 21:46:39 -050099 flush( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -0500100 }
101 else
102 {
103 // Sanity check. The returned size of the data written to the buffer
104 // should match the register size.
105 HEI_ASSERT( getSize() == sz_buffer );
106 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500107 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500108
Zane Shelley61565dc2019-09-18 21:57:10 -0500109 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500110}
111
112//------------------------------------------------------------------------------
113
Zane Shelley61565dc2019-09-18 21:57:10 -0500114#ifndef __HEI_READ_ONLY
115
Zane Shelley53efc352019-10-03 21:46:39 -0500116ReturnCode HardwareRegister::write( const Chip & i_chip ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500117{
Zane Shelley61565dc2019-09-18 21:57:10 -0500118 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500119
Zane Shelley53efc352019-10-03 21:46:39 -0500120 // Verify this register belongs on i_chip.
121 verifyAccessorChip( i_chip );
122
Zane Shelley61565dc2019-09-18 21:57:10 -0500123 // This register must be writable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500124 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
125 ( REG_ACCESS_RO != getAccessLevel() ) );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500126
Zane Shelley61565dc2019-09-18 21:57:10 -0500127 // An entry for this register must exist in the cache.
Zane Shelley53efc352019-10-03 21:46:39 -0500128 HEI_ASSERT( queryCache(i_chip) );
Zane Shelley61565dc2019-09-18 21:57:10 -0500129
130 // Get the buffer from the register cache.
Zane Shelley53efc352019-10-03 21:46:39 -0500131 BitString & bs = accessCache( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -0500132
133 // Get the byte size of the buffer.
134 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
135
136 // Write to this register to hardware.
Zane Shelley53efc352019-10-03 21:46:39 -0500137 rc = registerWrite( i_chip.getChip(), bs.getBufAddr(),
Zane Shelley61565dc2019-09-18 21:57:10 -0500138 sz_buffer, getRegisterType(), getAddress() );
139
140 if ( RC_SUCCESS == rc )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500141 {
Zane Shelley61565dc2019-09-18 21:57:10 -0500142 // Sanity check. The returned size of the data written to the buffer
143 // should match the register size.
144 HEI_ASSERT( getSize() == sz_buffer );
145 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500146
Zane Shelley61565dc2019-09-18 21:57:10 -0500147 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500148}
149
Zane Shelley61565dc2019-09-18 21:57:10 -0500150#endif // __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500151
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500152//------------------------------------------------------------------------------
153
Zane Shelleyd0af3582019-09-19 10:48:59 -0500154HardwareRegister::Cache HardwareRegister::cv_cache {};
155
156//------------------------------------------------------------------------------
157
158bool HardwareRegister::Cache::query( const Chip & i_chip,
159 const HardwareRegister * i_hwReg ) const
160{
161 // Does i_chip exist in the cache?
162 auto chipPairItr = iv_cache.find( i_chip );
163 if ( iv_cache.end() != chipPairItr )
164 {
165 auto & hwRegMap = chipPairItr->second; // for ease of use
166
167 // Does i_hwReg exist in the cache?
168 auto hwRegPairItr = hwRegMap.find( i_hwReg );
169 if ( hwRegMap.end() != hwRegPairItr )
170 {
171 return true;
172 }
173 }
174
175 return false;
176}
177
178//------------------------------------------------------------------------------
179
180BitString & HardwareRegister::Cache::access( const Chip & i_chip,
181 const HardwareRegister * i_hwReg )
182{
183 // If the entry does not exist, create a new entry.
184 if ( !query(i_chip, i_hwReg) )
185 {
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500186 BitString * bs = new BitStringBuffer { i_hwReg->getSize() * 8 };
Zane Shelleyd0af3582019-09-19 10:48:59 -0500187 iv_cache[i_chip][i_hwReg] = bs;
188 }
189
190 // Return a reference to the target entry.
191 return *(iv_cache[i_chip][i_hwReg]);
192}
193
194//------------------------------------------------------------------------------
195
196void HardwareRegister::Cache::flush()
197{
198 // Delete all of the BitStrings.
199 for ( auto & chipPair : iv_cache )
200 {
201 for ( auto & hwRegPair : chipPair.second )
202 {
203 delete hwRegPair.second;
204 }
205 }
206
207 // !!! Do not delete the HardwareRegisters !!!
208 // Those are deleted when the main uninitialize() API is called.
209
210 // Flush the rest of the cache.
211 iv_cache.clear();
212}
213
214//------------------------------------------------------------------------------
215
216void HardwareRegister::Cache::flush( const Chip & i_chip,
217 const HardwareRegister * i_hwReg )
218{
219 // Does i_chip exist in the cache?
220 auto chipPairItr = iv_cache.find( i_chip );
221 if ( iv_cache.end() != chipPairItr )
222 {
223 auto & hwRegMap = chipPairItr->second; // for ease of use
224
225 // Does i_hwReg exist in the cache?
226 auto hwRegPairItr = hwRegMap.find( i_hwReg );
227 if ( hwRegMap.end() != hwRegPairItr )
228 {
229 delete hwRegPairItr->second; // delete the BitString
230 hwRegMap.erase(i_hwReg); // remove the entry for this register
231 }
232
233 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
234 // the cache.
235 if ( hwRegMap.empty() )
236 {
237 iv_cache.erase(i_chip);
238 }
239 }
240}
241
242//------------------------------------------------------------------------------
243
Zane Shelley871adec2019-07-30 11:01:39 -0500244} // end namespace libhei
245