24class Bus :
public TBusParticipant... {
26 using ExcTrig = TExceptionTrigger;
28 explicit Bus(
const TBusParticipant &...participant) : TBusParticipant(participant)... {}
39 Bus(
const Bus &r_src) =
default;
51 Bus(Bus &&r_src) =
default;
59 template <
typename T>
Result<T> Read(TCpuAccessor &cpua, me_adr_t vadr)
const {
60 auto read_result = ForwardRead<T, TBusParticipant...>(cpua, vadr);
61 switch (read_result.status_code) {
62 case ReadStatusCode::kOk: {
63 return Ok<T>(read_result.content);
65 case ReadStatusCode::kReadNotAllowed: {
77 Result<T> ReadOrRaise(TCpuAccessor &cpua, me_adr_t vadr, BusExceptionType exc_type)
const {
78 auto read_res = ForwardRead<T, TBusParticipant...>(cpua, vadr);
80 if (read_res.status_code == ReadStatusCode::kOk) {
81 return Ok(read_res.content);
85 case BusExceptionType::kRaiseNoException: {
86 return Ok(read_res.content);
88 case BusExceptionType::kRaiseStkerr: {
92 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
94 cfsr |= CfsrBusFault::kStkerrMsk;
95 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
98 return Ok(read_res.content);
100 case BusExceptionType::kRaiseUnstkerr: {
104 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
106 cfsr |= CfsrBusFault::kUnstkerrMsk;
107 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
110 return Ok(read_res.content);
112 case BusExceptionType::kRaiseImpreciseDataBusError: {
115 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
117 cfsr |= CfsrBusFault::kImpreciseErrMsk;
118 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
121 return Ok(read_res.content);
123 case BusExceptionType::kRaisePreciseDataBusError: {
124 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
126 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
127 cfsr |= CfsrBusFault::kBfarValidMsk;
128 cfsr |= CfsrBusFault::kPreciseErrMsk;
129 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
132 return Ok(read_res.content);
134 case BusExceptionType::kRaiseInstructionBusError: {
136 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
138 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
140 cfsr |= CfsrBusFault::kIbuErrMsk;
141 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
144 return Ok(read_res.content);
151 template <
typename T> Result<void> Write(TCpuAccessor &cpua, me_adr_t vadr, T value)
const {
153 auto write_res = ForwardWrite<T, TBusParticipant...>(cpua, vadr, value);
154 switch (write_res.status_code) {
155 case WriteStatusCode::kOk: {
158 case WriteStatusCode::kWriteNotAllowed: {
169 template <
typename T>
170 Result<void> WriteOrRaise(TCpuAccessor &cpua, me_adr_t vadr, T value,
171 BusExceptionType exc_type)
const {
172 auto write_res = ForwardWrite<T, TBusParticipant...>(cpua, vadr, value);
173 if (write_res.status_code == WriteStatusCode::kOk) {
178 case BusExceptionType::kRaiseNoException: {
181 case BusExceptionType::kRaiseStkerr: {
182 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
184 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
185 cfsr |= CfsrBusFault::kBfarValidMsk;
186 cfsr |= CfsrBusFault::kStkerrMsk;
188 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
192 case BusExceptionType::kRaiseUnstkerr: {
193 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
196 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
197 cfsr |= CfsrBusFault::kBfarValidMsk;
198 cfsr |= CfsrBusFault::kUnstkerrMsk;
200 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
203 case BusExceptionType::kRaiseImpreciseDataBusError: {
204 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
207 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
208 cfsr |= CfsrBusFault::kBfarValidMsk;
209 cfsr |= CfsrBusFault::kImpreciseErrMsk;
211 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
214 case BusExceptionType::kRaisePreciseDataBusError: {
215 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
218 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
219 cfsr |= CfsrBusFault::kBfarValidMsk;
220 cfsr |= CfsrBusFault::kPreciseErrMsk;
222 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
225 case BusExceptionType::kRaiseInstructionBusError: {
226 cpua.template WriteSpecialRegister<SpecialRegisterId::kBfar>(vadr);
229 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
230 cfsr |= CfsrBusFault::kBfarValidMsk;
231 cfsr |= CfsrBusFault::kIbuErrMsk;
233 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
242 template <
typename T,
typename TAct,
typename... Rest>
243 ReadResult<T> ForwardRead(TCpuAccessor &cpua, me_adr_t vadr)
const {
244 if (!TAct::IsVAdrInRange(vadr)) {
245 return ForwardRead<T, Rest...>(cpua, vadr);
247 const auto read_result = TAct::template Read<T>(cpua, vadr);
251 template <
typename T> ReadResult<T> ForwardRead(TCpuAccessor &cpua, me_adr_t vadr)
const {
252 static_cast<void>(vadr);
253 static_cast<void>(cpua);
254 return ReadResult<T>{T{}, ReadStatusCode::kReadNotAllowed};
268 template <
typename T,
typename TAct,
typename... Rest,
269 typename std::enable_if_t<TAct::kReadOnly, T> = 0>
270 WriteResult<T> ForwardWrite(TCpuAccessor &cpua, me_adr_t vadr, T value)
const {
271 if (!TAct::IsVAdrInRange(vadr)) {
272 return ForwardWrite<T, Rest...>(cpua, vadr, value);
274 return WriteResult<T>{WriteStatusCode::kWriteNotAllowed};
288 template <
typename T,
typename TAct,
typename... Rest,
289 typename std::enable_if_t<!TAct::kReadOnly, T> = 0>
290 WriteResult<T> ForwardWrite(TCpuAccessor &cpua, me_adr_t vadr, T value)
const {
291 if (!TAct::IsVAdrInRange(vadr)) {
292 return ForwardWrite<T, Rest...>(cpua, vadr, value);
294 const auto write_res = TAct::template Write<T>(cpua, vadr, value);
298 template <
typename T>
299 WriteResult<T> ForwardWrite(TCpuAccessor &cpua, me_adr_t vadr, T value)
const {
300 static_cast<void>(vadr);
301 static_cast<void>(value);
302 static_cast<void>(cpua);
303 return WriteResult<T>{WriteStatusCode::kWriteNotAllowed};