blob: 3334662ab5707e238f64a25b543008deee5f6b06 [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
Zane Shelley53efc352019-10-03 21:46:39 -050047BitString & HardwareRegister::accessBitString( const Chip & i_chip )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050048{
Zane Shelley53efc352019-10-03 21:46:39 -050049 // Verify this register belongs on i_chip.
50 verifyAccessorChip( i_chip );
51
Paul Greenwood6574f6e2019-09-17 09:43:22 -050052 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050053 // entry has at been synched with hardware at least once. Note that we
54 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050055 // will be created in the cache, if it does not exist, when the cache is
Zane Shelley53efc352019-10-03 21:46:39 -050056 // accessed below.
Zane Shelleyd0af3582019-09-19 10:48:59 -050057
Paul Greenwood6574f6e2019-09-17 09:43:22 -050058 if ( ( REG_ACCESS_NONE != getAccessLevel() ) &&
59 ( REG_ACCESS_WO != getAccessLevel() ) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050060 {
Zane Shelley53efc352019-10-03 21:46:39 -050061 read( i_chip );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050062 }
63
Zane Shelley53efc352019-10-03 21:46:39 -050064 return accessCache( i_chip );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050065}
66
67//------------------------------------------------------------------------------
68
Zane Shelley53efc352019-10-03 21:46:39 -050069ReturnCode HardwareRegister::read( const Chip & i_chip, bool i_force ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050070{
Zane Shelley61565dc2019-09-18 21:57:10 -050071 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050072
Zane Shelley53efc352019-10-03 21:46:39 -050073 // Verify this register belongs on i_chip.
74 verifyAccessorChip( i_chip );
75
Zane Shelley61565dc2019-09-18 21:57:10 -050076 // Read from hardware only if the read is forced or the entry for this
77 // instance does not exist in the cache.
Zane Shelley53efc352019-10-03 21:46:39 -050078 if ( i_force || !queryCache(i_chip) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050079 {
Zane Shelley61565dc2019-09-18 21:57:10 -050080 // This register must be readable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -050081 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
82 ( REG_ACCESS_WO != getAccessLevel() ) );
Zane Shelley61565dc2019-09-18 21:57:10 -050083
84 // Get the buffer from the register cache.
Zane Shelley53efc352019-10-03 21:46:39 -050085 BitString & bs = accessCache( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -050086
87 // Get the byte size of the buffer.
88 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
89
90 // Read this register from hardware.
Zane Shelley53efc352019-10-03 21:46:39 -050091 rc = registerRead( i_chip.getChip(), bs.getBufAddr(),
Zane Shelley61565dc2019-09-18 21:57:10 -050092 sz_buffer, getRegisterType(), getAddress() );
93 if ( RC_SUCCESS != rc )
94 {
95 // The read failed and we can't trust what was put in the register
96 // cache. So remove this instance's entry from the cache.
Zane Shelley53efc352019-10-03 21:46:39 -050097 flush( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -050098 }
99 else
100 {
101 // Sanity check. The returned size of the data written to the buffer
102 // should match the register size.
103 HEI_ASSERT( getSize() == sz_buffer );
104 }
Zane Shelleyd0af3582019-09-19 10:48:59 -0500105 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500106
Zane Shelley61565dc2019-09-18 21:57:10 -0500107 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500108}
109
110//------------------------------------------------------------------------------
111
Zane Shelley61565dc2019-09-18 21:57:10 -0500112#ifndef __HEI_READ_ONLY
113
Zane Shelley53efc352019-10-03 21:46:39 -0500114ReturnCode HardwareRegister::write( const Chip & i_chip ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500115{
Zane Shelley61565dc2019-09-18 21:57:10 -0500116 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500117
Zane Shelley53efc352019-10-03 21:46:39 -0500118 // Verify this register belongs on i_chip.
119 verifyAccessorChip( i_chip );
120
Zane Shelley61565dc2019-09-18 21:57:10 -0500121 // This register must be writable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500122 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
123 ( REG_ACCESS_RO != getAccessLevel() ) );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500124
Zane Shelley61565dc2019-09-18 21:57:10 -0500125 // An entry for this register must exist in the cache.
Zane Shelley53efc352019-10-03 21:46:39 -0500126 HEI_ASSERT( queryCache(i_chip) );
Zane Shelley61565dc2019-09-18 21:57:10 -0500127
128 // Get the buffer from the register cache.
Zane Shelley53efc352019-10-03 21:46:39 -0500129 BitString & bs = accessCache( i_chip );
Zane Shelley61565dc2019-09-18 21:57:10 -0500130
131 // Get the byte size of the buffer.
132 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
133
134 // Write to this register to hardware.
Zane Shelley53efc352019-10-03 21:46:39 -0500135 rc = registerWrite( i_chip.getChip(), bs.getBufAddr(),
Zane Shelley61565dc2019-09-18 21:57:10 -0500136 sz_buffer, getRegisterType(), getAddress() );
137
138 if ( RC_SUCCESS == rc )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500139 {
Zane Shelley61565dc2019-09-18 21:57:10 -0500140 // Sanity check. The returned size of the data written to the buffer
141 // should match the register size.
142 HEI_ASSERT( getSize() == sz_buffer );
143 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500144
Zane Shelley61565dc2019-09-18 21:57:10 -0500145 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500146}
147
Zane Shelley61565dc2019-09-18 21:57:10 -0500148#endif // __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500149
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500150//------------------------------------------------------------------------------
151
Zane Shelleyd0af3582019-09-19 10:48:59 -0500152HardwareRegister::Cache HardwareRegister::cv_cache {};
153
154//------------------------------------------------------------------------------
155
156bool HardwareRegister::Cache::query( const Chip & i_chip,
157 const HardwareRegister * i_hwReg ) const
158{
159 // Does i_chip exist in the cache?
160 auto chipPairItr = iv_cache.find( i_chip );
161 if ( iv_cache.end() != chipPairItr )
162 {
163 auto & hwRegMap = chipPairItr->second; // for ease of use
164
165 // Does i_hwReg exist in the cache?
166 auto hwRegPairItr = hwRegMap.find( i_hwReg );
167 if ( hwRegMap.end() != hwRegPairItr )
168 {
169 return true;
170 }
171 }
172
173 return false;
174}
175
176//------------------------------------------------------------------------------
177
178BitString & HardwareRegister::Cache::access( const Chip & i_chip,
179 const HardwareRegister * i_hwReg )
180{
181 // If the entry does not exist, create a new entry.
182 if ( !query(i_chip, i_hwReg) )
183 {
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500184 BitString * bs = new BitStringBuffer { i_hwReg->getSize() * 8 };
Zane Shelleyd0af3582019-09-19 10:48:59 -0500185 iv_cache[i_chip][i_hwReg] = bs;
186 }
187
188 // Return a reference to the target entry.
189 return *(iv_cache[i_chip][i_hwReg]);
190}
191
192//------------------------------------------------------------------------------
193
194void HardwareRegister::Cache::flush()
195{
196 // Delete all of the BitStrings.
197 for ( auto & chipPair : iv_cache )
198 {
199 for ( auto & hwRegPair : chipPair.second )
200 {
201 delete hwRegPair.second;
202 }
203 }
204
205 // !!! Do not delete the HardwareRegisters !!!
206 // Those are deleted when the main uninitialize() API is called.
207
208 // Flush the rest of the cache.
209 iv_cache.clear();
210}
211
212//------------------------------------------------------------------------------
213
214void HardwareRegister::Cache::flush( const Chip & i_chip,
215 const HardwareRegister * i_hwReg )
216{
217 // Does i_chip exist in the cache?
218 auto chipPairItr = iv_cache.find( i_chip );
219 if ( iv_cache.end() != chipPairItr )
220 {
221 auto & hwRegMap = chipPairItr->second; // for ease of use
222
223 // Does i_hwReg exist in the cache?
224 auto hwRegPairItr = hwRegMap.find( i_hwReg );
225 if ( hwRegMap.end() != hwRegPairItr )
226 {
227 delete hwRegPairItr->second; // delete the BitString
228 hwRegMap.erase(i_hwReg); // remove the entry for this register
229 }
230
231 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
232 // the cache.
233 if ( hwRegMap.empty() )
234 {
235 iv_cache.erase(i_chip);
236 }
237 }
238}
239
240//------------------------------------------------------------------------------
241
Zane Shelley871adec2019-07-30 11:01:39 -0500242} // end namespace libhei
243