blob: a1de6844e83f2bbcbfd7d68506f37dc18601e2b4 [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
Paul Greenwood6574f6e2019-09-17 09:43:22 -050025const BitString * HardwareRegister::getBitString() const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050026{
Paul Greenwood6574f6e2019-09-17 09:43:22 -050027 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050028 // entry has at been synched with hardware at least once. Note that we
29 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050030 // will be created in the cache, if it does not exist, when the cache is
31 // read below.
32
Paul Greenwood6574f6e2019-09-17 09:43:22 -050033 if ( ( REG_ACCESS_NONE != getAccessLevel() ) &&
34 ( REG_ACCESS_WO != getAccessLevel() ) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050035 {
Paul Greenwood6574f6e2019-09-17 09:43:22 -050036 read();
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050037 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050038
39 return &( accessCache() );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050040}
41
42//------------------------------------------------------------------------------
43
Paul Greenwood6574f6e2019-09-17 09:43:22 -050044#if 0
45BitString & HardwareRegister::accessBitString()
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050046{
Paul Greenwood6574f6e2019-09-17 09:43:22 -050047 // Calling read() will ensure that an entry exists in the cache and the
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050048 // entry has at been synched with hardware at least once. Note that we
49 // cannot read hardware for write-only registers. In this case, an entry
Zane Shelleyd0af3582019-09-19 10:48:59 -050050 // will be created in the cache, if it does not exist, when the cache is
51 // read below.
52
Paul Greenwood6574f6e2019-09-17 09:43:22 -050053 if ( ( REG_ACCESS_NONE != getAccessLevel() ) &&
54 ( REG_ACCESS_WO != getAccessLevel() ) )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050055 {
Paul Greenwood6574f6e2019-09-17 09:43:22 -050056 read();
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050057 }
58
Zane Shelleyd0af3582019-09-19 10:48:59 -050059 return accessCache();
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050060}
Zane Shelley61565dc2019-09-18 21:57:10 -050061#endif
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050062
63//------------------------------------------------------------------------------
64
Zane Shelley61565dc2019-09-18 21:57:10 -050065ReturnCode HardwareRegister::read( bool i_force ) const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050066{
Zane Shelley61565dc2019-09-18 21:57:10 -050067 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050068
Zane Shelley61565dc2019-09-18 21:57:10 -050069 // Read from hardware only if the read is forced or the entry for this
70 // instance does not exist in the cache.
71 if ( i_force || !queryCache() )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050072 {
Zane Shelley61565dc2019-09-18 21:57:10 -050073 // This register must be readable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -050074 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
75 ( REG_ACCESS_WO != getAccessLevel() ) );
Zane Shelley61565dc2019-09-18 21:57:10 -050076
77 // Get the buffer from the register cache.
Zane Shelleyd0af3582019-09-19 10:48:59 -050078 BitString & bs = accessCache();
Zane Shelley61565dc2019-09-18 21:57:10 -050079
80 // Get the byte size of the buffer.
81 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
82
83 // Read this register from hardware.
84 rc = registerRead( getAccessorChip().getChip(), bs.getBufAddr(),
85 sz_buffer, getRegisterType(), getAddress() );
86 if ( RC_SUCCESS != rc )
87 {
88 // The read failed and we can't trust what was put in the register
89 // cache. So remove this instance's entry from the cache.
Zane Shelleyd0af3582019-09-19 10:48:59 -050090 cv_cache.flush( getAccessorChip(), this );
Zane Shelley61565dc2019-09-18 21:57:10 -050091 }
92 else
93 {
94 // Sanity check. The returned size of the data written to the buffer
95 // should match the register size.
96 HEI_ASSERT( getSize() == sz_buffer );
97 }
Zane Shelleyd0af3582019-09-19 10:48:59 -050098 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -050099
Zane Shelley61565dc2019-09-18 21:57:10 -0500100 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500101}
102
103//------------------------------------------------------------------------------
104
Zane Shelley61565dc2019-09-18 21:57:10 -0500105#ifndef __HEI_READ_ONLY
106
107ReturnCode HardwareRegister::write() const
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500108{
Zane Shelley61565dc2019-09-18 21:57:10 -0500109 ReturnCode rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500110
Zane Shelley61565dc2019-09-18 21:57:10 -0500111 // This register must be writable.
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500112 HEI_ASSERT( ( REG_ACCESS_NONE != getAccessLevel() ) &&
113 ( REG_ACCESS_RO != getAccessLevel() ) );
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500114
Zane Shelley61565dc2019-09-18 21:57:10 -0500115 // An entry for this register must exist in the cache.
116 HEI_ASSERT( queryCache() );
117
118 // Get the buffer from the register cache.
Zane Shelleyd0af3582019-09-19 10:48:59 -0500119 BitString & bs = accessCache();
Zane Shelley61565dc2019-09-18 21:57:10 -0500120
121 // Get the byte size of the buffer.
122 size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
123
124 // Write to this register to hardware.
125 rc = registerWrite( getAccessorChip().getChip(), bs.getBufAddr(),
126 sz_buffer, getRegisterType(), getAddress() );
127
128 if ( RC_SUCCESS == rc )
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500129 {
Zane Shelley61565dc2019-09-18 21:57:10 -0500130 // Sanity check. The returned size of the data written to the buffer
131 // should match the register size.
132 HEI_ASSERT( getSize() == sz_buffer );
133 }
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500134
Zane Shelley61565dc2019-09-18 21:57:10 -0500135 return rc;
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500136}
137
Zane Shelley61565dc2019-09-18 21:57:10 -0500138#endif // __HEI_READ_ONLY
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500139
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -0500140//------------------------------------------------------------------------------
141
Zane Shelley61565dc2019-09-18 21:57:10 -0500142HardwareRegister::Accessor * HardwareRegister::cv_accessor = nullptr;
143
144//------------------------------------------------------------------------------
145
Zane Shelleyd0af3582019-09-19 10:48:59 -0500146HardwareRegister::Cache HardwareRegister::cv_cache {};
147
148//------------------------------------------------------------------------------
149
150bool HardwareRegister::Cache::query( const Chip & i_chip,
151 const HardwareRegister * i_hwReg ) const
152{
153 // Does i_chip exist in the cache?
154 auto chipPairItr = iv_cache.find( i_chip );
155 if ( iv_cache.end() != chipPairItr )
156 {
157 auto & hwRegMap = chipPairItr->second; // for ease of use
158
159 // Does i_hwReg exist in the cache?
160 auto hwRegPairItr = hwRegMap.find( i_hwReg );
161 if ( hwRegMap.end() != hwRegPairItr )
162 {
163 return true;
164 }
165 }
166
167 return false;
168}
169
170//------------------------------------------------------------------------------
171
172BitString & HardwareRegister::Cache::access( const Chip & i_chip,
173 const HardwareRegister * i_hwReg )
174{
175 // If the entry does not exist, create a new entry.
176 if ( !query(i_chip, i_hwReg) )
177 {
Paul Greenwood6574f6e2019-09-17 09:43:22 -0500178 BitString * bs = new BitStringBuffer { i_hwReg->getSize() * 8 };
Zane Shelleyd0af3582019-09-19 10:48:59 -0500179 iv_cache[i_chip][i_hwReg] = bs;
180 }
181
182 // Return a reference to the target entry.
183 return *(iv_cache[i_chip][i_hwReg]);
184}
185
186//------------------------------------------------------------------------------
187
188void HardwareRegister::Cache::flush()
189{
190 // Delete all of the BitStrings.
191 for ( auto & chipPair : iv_cache )
192 {
193 for ( auto & hwRegPair : chipPair.second )
194 {
195 delete hwRegPair.second;
196 }
197 }
198
199 // !!! Do not delete the HardwareRegisters !!!
200 // Those are deleted when the main uninitialize() API is called.
201
202 // Flush the rest of the cache.
203 iv_cache.clear();
204}
205
206//------------------------------------------------------------------------------
207
208void HardwareRegister::Cache::flush( const Chip & i_chip,
209 const HardwareRegister * i_hwReg )
210{
211 // Does i_chip exist in the cache?
212 auto chipPairItr = iv_cache.find( i_chip );
213 if ( iv_cache.end() != chipPairItr )
214 {
215 auto & hwRegMap = chipPairItr->second; // for ease of use
216
217 // Does i_hwReg exist in the cache?
218 auto hwRegPairItr = hwRegMap.find( i_hwReg );
219 if ( hwRegMap.end() != hwRegPairItr )
220 {
221 delete hwRegPairItr->second; // delete the BitString
222 hwRegMap.erase(i_hwReg); // remove the entry for this register
223 }
224
225 // If i_hwReg was the only entry for i_chip, we can remove i_chip from
226 // the cache.
227 if ( hwRegMap.empty() )
228 {
229 iv_cache.erase(i_chip);
230 }
231 }
232}
233
234//------------------------------------------------------------------------------
235
Zane Shelley871adec2019-07-30 11:01:39 -0500236} // end namespace libhei
237