6 #include <nlohmann/json.hpp>
7 #include <unordered_map>
8 #include <unordered_set>
10 #include <boost/bimap.hpp>
32 boost::bimap<std::string, GmidOptionCode>
makeBimap(
33 std::initializer_list<
typename boost::bimap<std::string, GmidOptionCode>::value_type> list) {
34 return {list.begin(), list.end()};
39 static const auto OptionCodeMap =
makeBimap({
65 inline uint32_t
iToMask(
const uint32_t ithInterrupt) {
66 return 0x1U << ithInterrupt;
79 auto it = OptionCodeMap.left.find(opt);
80 if(it != OptionCodeMap.left.end()) {
93 auto it = OptionCodeMap.right.find(optCode);
94 if(it != OptionCodeMap.right.end()) {
98 return "INVALID_OPTION_CODE";
109 static std::map<GmidOptionCode, std::string> mapOptCode2Message= {
110 {
ISR,
"Interrupt Status Register"},
111 {
IER,
"Interrupt Enable Register"},
112 {
MER,
"Master Enable Register"},
113 {
MIE,
"Master Interrupt Enable"},
114 {
GIE,
"Global Interrupt Enable"},
115 {
ICR,
"Interrupt Clear Register"},
116 {
IAR,
"Interrupt Acknowledge Register"},
117 {
IPR,
"Interrupt Pending Register"},
118 {
SIE,
"Set Interrupt Enable"},
119 {
CIE,
"Clear Interrupt Enable"},
121 "Interrupt Mask Register, not to be confused with Interrupt Mode Register"},
123 "Interrupt Mode Register, what AXI INTC v4.1 calls this 'IMR', not to be confused with Interrupt Mask "
124 "Register, which we call 'IMR'"},
125 {
IVR,
"Interrupt Vector Register"},
126 {
ILR,
"Interrupt Level Register"},
127 {
IVAR,
"Interrupt Vector Address Register"},
128 {
IVEAR,
"Interrupt Vector Extended Address Register"},
141 std::string
strSetToStr(
const std::set<std::string>& strSet,
char delimiter =
',') {
143 if(not strSet.empty()) {
144 for(
const auto& str : strSet) {
145 result += str + delimiter;
159 std::string
intVecToStr(
const std::vector<size_t>& intVec,
char delimiter =
',') {
161 if(not intVec.empty()) {
162 for(
const auto& i : intVec) {
190 const std::vector<size_t>& controllerID,
const std::string& descriptionJsonStr) {
203 static const std::vector<std::string> defaultOptionRegisterNames = {
"ISR",
"IER"};
204 std::string registerPath;
205 std::bitset<OPTION_CODE_COUNT> optionRegisterSettings(0);
209 descriptionJson = nlohmann::json::parse(descriptionJsonStr);
211 catch(
const nlohmann::json::parse_error& ex) {
212 std::ostringstream oss;
214 <<
" was unable to parse map file json snippet " << descriptionJsonStr;
219 for(
auto& el : descriptionJson.items()) {
222 std::ostringstream oss;
223 oss <<
"Unknown JSON key '" << el.key() <<
"' provided to map file for GenericMuxedInterruptDistributor "
232 catch(
const nlohmann::json::exception& e) {
233 std::ostringstream oss;
235 <<
"' error for GenericMuxedInterruptDistributor " <<
controllerIDToStr(controllerID) <<
": " << e.what();
243 std::ostringstream oss;
244 oss <<
"GenericMuxedInterruptDistributor " <<
controllerIDToStr(controllerID) <<
" expects a "
251 catch(
const nlohmann::json::exception& e) {
252 std::ostringstream oss;
258 std::vector<std::string> optionRegisterNames;
263 catch(
const nlohmann::json::exception& e) {
264 std::ostringstream oss;
275 std::set<std::string> invalidOptionRegisterNamesEncountered;
276 for(
const auto& orn : optionRegisterNames) {
278 optionRegisterSettings.set(ornCode);
281 invalidOptionRegisterNamesEncountered.insert(orn);
284 if(!invalidOptionRegisterNamesEncountered.empty()) {
285 std::ostringstream oss;
286 oss <<
"Invalid register options " <<
strSetToStr(invalidOptionRegisterNamesEncountered)
292 return std::make_pair(optionRegisterSettings, registerPath);
302 std::bitset<OPTION_CODE_COUNT>
const& optionRegisterSettings, std::vector<size_t>
const& controllerID) {
317 if(optionRegisterSettings.test(
SIE) != optionRegisterSettings.test(
CIE)) {
318 std::ostringstream oss;
320 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
322 <<
" is set, but not both.";
327 if(optionRegisterSettings.test(
IMaskR)) {
328 if(optionRegisterSettings.test(
SIE)) {
329 std::ostringstream oss;
331 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
333 <<
" cannot not both be set.";
336 if(optionRegisterSettings.test(
CIE)) {
337 std::ostringstream oss;
339 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
341 <<
" cannot not both be set.";
347 if(optionRegisterSettings.test(
ICR) and optionRegisterSettings.test(
IAR)) {
348 std::ostringstream oss;
350 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
352 <<
" cannot not both be set.";
357 if(optionRegisterSettings.test(
IMaskR) and optionRegisterSettings.test(
IER)) {
358 std::ostringstream oss;
360 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
362 <<
" cannot not both be set.";
367 if(not(optionRegisterSettings.test(
IMaskR) or optionRegisterSettings.test(
IER))) {
368 std::ostringstream oss;
371 <<
" are set, one of the two is required.";
377 int nMieGieMer =
static_cast<int>(optionRegisterSettings.test(
MIE)) +
378 static_cast<int>(optionRegisterSettings.test(
GIE)) +
static_cast<int>(optionRegisterSettings.test(
MER));
380 std::ostringstream oss;
382 <<
" combination specified in map file json descriptor for GenericMuxedInterruptDistributor "
391 if(optionRegisterSettings.test(
IModeR)) {
392 std::ostringstream oss;
394 <<
" specified in map file json descriptor for GenericMuxedInterruptDistributor "
396 <<
" is a defined options in the AXI IntC v4.1 register space, it is not currently an allowed options in"
397 " the GenericMuxedInterruptDistributor";
401 if(optionRegisterSettings.test(
IVEAR) or optionRegisterSettings.test(
IVAR) or optionRegisterSettings.test(
IVR) or
402 optionRegisterSettings.test(
ILR) or optionRegisterSettings.test(
IModeR)) {
403 std::ostringstream oss;
405 <<
" specified in map file json descriptor for GenericMuxedInterruptDistributor "
408 <<
"are defined options in the AXI IntC v4.1 register space, they are not currently allowed options in the "
409 "GenericMuxedInterruptDistributor";
413 if(optionRegisterSettings.test(
IMaskR)) {
414 std::ostringstream oss;
416 <<
" specified in map file json descriptor for GenericMuxedInterruptDistributor "
418 <<
" is not currently an allowed options in the GenericMuxedInterruptDistributor, but should be supported "
419 "in a later version. ";
424 if(not optionRegisterSettings.test(
ISR)) {
425 std::ostringstream oss;
426 oss <<
explainOptCode(
ISR) <<
" is required but is not enabled for GenericMuxedInterruptDistributor "
438 std::bitset<GmidOptionCode::OPTION_CODE_COUNT> optionRegisterSettings)
441 optionRegisterSettings.set(
ISR);
442 if(not optionRegisterSettings.test(
IMaskR)) {
443 optionRegisterSettings.set(
IER);
460 if(optionRegisterSettings.test(
ICR)) {
463 else if(optionRegisterSettings.test(
IAR)) {
470 _hasMer = optionRegisterSettings.test(
MER) or optionRegisterSettings.test(
MIE) or optionRegisterSettings.test(
GIE);
473 optionRegisterSettings.test(
MIE) ?
MIE : (optionRegisterSettings.test(
GIE) ?
GIE :
MER);
491 auto catalogue =
_backend->getRegisterCatalogue();
493 auto checkRedable = [catalogue](
auto& accessor) {
494 auto description = catalogue.getRegister(accessor->getName());
495 if(!description.isReadable()) {
497 "GenericMuxedInterruptDistributor: Handshake register not readable: " + accessor->getName());
500 auto checkWriteable = [catalogue](
auto& accessor) {
501 auto description = catalogue.getRegister(accessor->getName());
502 if(!description.isWriteable()) {
504 "GenericMuxedInterruptDistributor: Handshake register not writeable: " + accessor->getName());
509 checkWriteable(
_ier);
510 checkWriteable(
_icr);
513 checkWriteable(
_mer);
516 checkWriteable(
_sie);
519 checkWriteable(
_cie);
532 std::cerr <<
"Logic error in ~GenericMuxedInterruptDistributor: " << e.
what() <<
" TERMINATING!" << std::endl;
542 _icr->accessData(0) = mask;
575 _cie->accessData(0) = mask;
641 for(
auto const& [i, subDomainWeakPtr] :
_subDomains) {
644 if(
auto subDomain = subDomainWeakPtr.lock(); subDomain) {
649 subDomain->distribute(
nullptr, version);
673 std::bitset<OPTION_CODE_COUNT> optionRegisterSettings = parseResult.first;
674 std::string registerPath = parseResult.second;
676 return std::make_unique<GenericMuxedInterruptDistributor>(parent, registerPath, optionRegisterSettings);
683 _mer->accessData(0) = 0x00000003;
691 uint32_t activeInterrupts = 0;
692 for(
auto const& [i, subDomainWeakPtr] :
_subDomains) {
694 if(subDomainWeakPtr.lock()) {
695 activeInterrupts |=
iToMask(i);
709 auto subDomain = subDomainIter.second.lock();
711 subDomain->activate(
nullptr, version);
719 auto index = subDomain.
getId().back();
724 subDomain.
activate(
nullptr, version);