mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
fix fomatting in core.cpp
Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
parent
64d5a6ba42
commit
bd1f32da7b
1 changed files with 228 additions and 238 deletions
|
@ -5,8 +5,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <villas/exceptions.hpp>
|
||||
|
@ -15,11 +15,12 @@
|
|||
#include <villas/utils.hpp>
|
||||
|
||||
#include <villas/fpga/card.hpp>
|
||||
#include <villas/fpga/utils.hpp>
|
||||
#include <villas/fpga/vlnv.hpp>
|
||||
|
||||
#include <villas/fpga/core.hpp>
|
||||
#include <villas/fpga/ips/pcie.hpp>
|
||||
#include <villas/fpga/ips/intc.hpp>
|
||||
#include <villas/fpga/ips/pcie.hpp>
|
||||
#include <villas/fpga/ips/switch.hpp>
|
||||
|
||||
using namespace villas::fpga;
|
||||
|
@ -28,303 +29,292 @@ using namespace villas::fpga::ip;
|
|||
// Special IPs that have to be initialized first. Will be initialized in the
|
||||
// same order as they appear in this list, i.e. first here will be initialized
|
||||
// first.
|
||||
static std::list<Vlnv>
|
||||
vlnvInitializationOrder = {
|
||||
static std::list<Vlnv> vlnvInitializationOrder = {
|
||||
Vlnv("xilinx.com:ip:axi_pcie:"),
|
||||
Vlnv("xilinx.com:module_ref:axi_pcie_intc:"),
|
||||
Vlnv("xilinx.com:ip:axis_switch:"),
|
||||
};
|
||||
|
||||
std::list<std::shared_ptr<Core>> CoreFactory::make(Card* card, json_t *json_ips)
|
||||
{
|
||||
// We only have this logger until we know the factory to build an IP with
|
||||
auto loggerStatic = getStaticLogger();
|
||||
std::list<std::shared_ptr<Core>> CoreFactory::make(Card *card,
|
||||
json_t *json_ips) {
|
||||
// We only have this logger until we know the factory to build an IP with
|
||||
auto loggerStatic = getStaticLogger();
|
||||
|
||||
std::list<IpIdentifier> allIps; // All IPs available in config
|
||||
std::list<IpIdentifier> orderedIps; // IPs ordered in initialization order
|
||||
std::list<IpIdentifier> allIps; // All IPs available in config
|
||||
std::list<IpIdentifier> orderedIps; // IPs ordered in initialization order
|
||||
|
||||
std::list<std::shared_ptr<Core>> configuredIps; // Successfully configured IPs
|
||||
std::list<std::shared_ptr<Core>> initializedIps; // Initialized, i.e. ready-to-use IPs
|
||||
std::list<std::shared_ptr<Core>> configuredIps; // Successfully configured IPs
|
||||
std::list<std::shared_ptr<Core>>
|
||||
initializedIps; // Initialized, i.e. ready-to-use IPs
|
||||
|
||||
// Parse all IP instance names and their VLNV into list `allIps`
|
||||
const char* ipName;
|
||||
json_t* json_ip;
|
||||
json_object_foreach(json_ips, ipName, json_ip) {
|
||||
const char* vlnv;
|
||||
// Parse all IP instance names and their VLNV into list `allIps`
|
||||
const char *ipName;
|
||||
json_t *json_ip;
|
||||
json_object_foreach(json_ips, ipName, json_ip) {
|
||||
const char *vlnv;
|
||||
|
||||
json_error_t err;
|
||||
int ret = json_unpack_ex(json_ip, &err, 0, "{ s: s }",
|
||||
"vlnv", &vlnv
|
||||
);
|
||||
if (ret != 0)
|
||||
throw ConfigError(json_ip, err, "", "IP {} has no VLNV", ipName);
|
||||
json_error_t err;
|
||||
int ret = json_unpack_ex(json_ip, &err, 0, "{ s: s }", "vlnv", &vlnv);
|
||||
if (ret != 0)
|
||||
throw ConfigError(json_ip, err, "", "IP {} has no VLNV", ipName);
|
||||
|
||||
allIps.push_back({vlnv, ipName});
|
||||
}
|
||||
allIps.push_back({vlnv, ipName});
|
||||
}
|
||||
|
||||
// Pick out IPs to be initialized first.
|
||||
//
|
||||
// Reverse walktrough, because we push to the
|
||||
// front of the output list, so that the first element will also be the
|
||||
// first to be initialized.
|
||||
for (auto viIt = vlnvInitializationOrder.rbegin(); viIt != vlnvInitializationOrder.rend(); ++viIt) {
|
||||
// Iterate over IPs, if VLNV matches, push to front and remove from list
|
||||
for (auto it = allIps.begin(); it != allIps.end(); ++it) {
|
||||
if (*viIt == it->getVlnv()) {
|
||||
orderedIps.push_front(*it);
|
||||
it = allIps.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pick out IPs to be initialized first.
|
||||
//
|
||||
// Reverse walktrough, because we push to the
|
||||
// front of the output list, so that the first element will also be the
|
||||
// first to be initialized.
|
||||
for (auto viIt = vlnvInitializationOrder.rbegin();
|
||||
viIt != vlnvInitializationOrder.rend(); ++viIt) {
|
||||
// Iterate over IPs, if VLNV matches, push to front and remove from list
|
||||
for (auto it = allIps.begin(); it != allIps.end(); ++it) {
|
||||
if (*viIt == it->getVlnv()) {
|
||||
orderedIps.push_front(*it);
|
||||
it = allIps.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert all other IPs at the end
|
||||
orderedIps.splice(orderedIps.end(), allIps);
|
||||
// Insert all other IPs at the end
|
||||
orderedIps.splice(orderedIps.end(), allIps);
|
||||
|
||||
loggerStatic->debug("IP initialization order:");
|
||||
for (auto &id : orderedIps) {
|
||||
loggerStatic->debug(" " CLR_BLD("{}"), id.getName());
|
||||
}
|
||||
loggerStatic->debug("IP initialization order:");
|
||||
for (auto &id : orderedIps) {
|
||||
loggerStatic->debug(" " CLR_BLD("{}"), id.getName());
|
||||
}
|
||||
|
||||
// Configure all IPs
|
||||
for (auto &id : orderedIps) {
|
||||
loggerStatic->info("Configuring {}", id);
|
||||
// Configure all IPs
|
||||
for (auto &id : orderedIps) {
|
||||
loggerStatic->info("Configuring {}", id);
|
||||
|
||||
// Find the appropriate factory that can create the specified VLNV
|
||||
// Note:
|
||||
// This is the magic part! Factories automatically register as a
|
||||
// plugin as soon as they are instantiated. If there are multiple
|
||||
// candidates, the first suitable factory will be used.
|
||||
auto* f = lookup(id.getVlnv());
|
||||
if (f == nullptr) {
|
||||
loggerStatic->warn("No plugin found to handle {}", id.getVlnv());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
loggerStatic->debug("Using {} for IP {}", f->getName(), id.getVlnv());
|
||||
// Find the appropriate factory that can create the specified VLNV
|
||||
// Note:
|
||||
// This is the magic part! Factories automatically register as a
|
||||
// plugin as soon as they are instantiated. If there are multiple
|
||||
// candidates, the first suitable factory will be used.
|
||||
auto *f = lookup(id.getVlnv());
|
||||
if (f == nullptr) {
|
||||
loggerStatic->warn("No plugin found to handle {}", id.getVlnv());
|
||||
continue;
|
||||
} else
|
||||
loggerStatic->debug("Using {} for IP {}", f->getName(), id.getVlnv());
|
||||
|
||||
auto logger = f->getLogger();
|
||||
auto logger = f->getLogger();
|
||||
|
||||
// Create new IP instance. Since this function is virtual, it will
|
||||
// construct the right, specialized type without knowing it here
|
||||
// because we have already picked the right factory.
|
||||
// If something goes wrong with initialization, the shared_ptr will
|
||||
// take care to desctruct the Core again as it is not pushed to
|
||||
// the list and will run out of scope.
|
||||
auto ip = std::unique_ptr<Core>(f->make());
|
||||
// Create new IP instance. Since this function is virtual, it will
|
||||
// construct the right, specialized type without knowing it here
|
||||
// because we have already picked the right factory.
|
||||
// If something goes wrong with initialization, the shared_ptr will
|
||||
// take care to desctruct the Core again as it is not pushed to
|
||||
// the list and will run out of scope.
|
||||
auto ip = std::unique_ptr<Core>(f->make());
|
||||
|
||||
if (ip == nullptr) {
|
||||
logger->warn("Cannot create an instance of {}", f->getName());
|
||||
continue;
|
||||
}
|
||||
if (ip == nullptr) {
|
||||
logger->warn("Cannot create an instance of {}", f->getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setup generic IP type properties
|
||||
ip->card = card;
|
||||
ip->id = id;
|
||||
ip->logger = villas::logging.get(id.getName());
|
||||
// Setup generic IP type properties
|
||||
ip->card = card;
|
||||
ip->id = id;
|
||||
ip->logger = villas::logging.get(id.getName());
|
||||
|
||||
json_t* json_ip = json_object_get(json_ips, id.getName().c_str());
|
||||
json_t *json_ip = json_object_get(json_ips, id.getName().c_str());
|
||||
|
||||
json_t* json_irqs = json_object_get(json_ip, "irqs");
|
||||
if (json_is_object(json_irqs)) {
|
||||
logger->debug("Parse IRQs of {}", *ip);
|
||||
json_t *json_irqs = json_object_get(json_ip, "irqs");
|
||||
if (json_is_object(json_irqs)) {
|
||||
logger->debug("Parse IRQs of {}", *ip);
|
||||
|
||||
const char* irqName;
|
||||
json_t* json_irq;
|
||||
json_object_foreach(json_irqs, irqName, json_irq) {
|
||||
const char* irqEntry = json_string_value(json_irq);
|
||||
const char *irqName;
|
||||
json_t *json_irq;
|
||||
json_object_foreach(json_irqs, irqName, json_irq) {
|
||||
const char *irqEntry = json_string_value(json_irq);
|
||||
|
||||
auto tokens = utils::tokenize(irqEntry, ":");
|
||||
if (tokens.size() != 2) {
|
||||
logger->warn("Cannot parse IRQ '{}' of " CLR_BLD("{}"),
|
||||
irqEntry, id.getName());
|
||||
continue;
|
||||
}
|
||||
auto tokens = utils::tokenize(irqEntry, ":");
|
||||
if (tokens.size() != 2) {
|
||||
logger->warn("Cannot parse IRQ '{}' of " CLR_BLD("{}"), irqEntry,
|
||||
id.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string &irqControllerName = tokens[0];
|
||||
InterruptController* intc = nullptr;
|
||||
const std::string &irqControllerName = tokens[0];
|
||||
InterruptController *intc = nullptr;
|
||||
|
||||
for (auto &configuredIp : configuredIps) {
|
||||
if (*configuredIp == irqControllerName) {
|
||||
intc = dynamic_cast<InterruptController*>(configuredIp.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto &configuredIp : configuredIps) {
|
||||
if (*configuredIp == irqControllerName) {
|
||||
intc = dynamic_cast<InterruptController *>(configuredIp.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (intc == nullptr) {
|
||||
logger->error("Interrupt Controller {} for IRQ {} not found",
|
||||
irqControllerName, irqName);
|
||||
continue;
|
||||
}
|
||||
if (intc == nullptr) {
|
||||
logger->error("Interrupt Controller {} for IRQ {} not found",
|
||||
irqControllerName, irqName);
|
||||
continue;
|
||||
}
|
||||
|
||||
int num;
|
||||
try {
|
||||
num = std::stoi(tokens[1]);
|
||||
} catch (const std::invalid_argument&) {
|
||||
logger->warn("IRQ number is not an integer: '{}'", irqEntry);
|
||||
continue;
|
||||
}
|
||||
logger->debug("IRQ: {} -> {}:{}", irqName, irqControllerName, num);
|
||||
ip->irqs[irqName] = {num, intc, ""};
|
||||
}
|
||||
}
|
||||
int num;
|
||||
try {
|
||||
num = std::stoi(tokens[1]);
|
||||
} catch (const std::invalid_argument &) {
|
||||
logger->warn("IRQ number is not an integer: '{}'", irqEntry);
|
||||
continue;
|
||||
}
|
||||
logger->debug("IRQ: {} -> {}:{}", irqName, irqControllerName, num);
|
||||
ip->irqs[irqName] = {num, intc, ""};
|
||||
}
|
||||
}
|
||||
|
||||
json_t* json_memory_view = json_object_get(json_ip, "memory-view");
|
||||
if (json_is_object(json_memory_view)) {
|
||||
logger->debug("Parse memory view of {}", *ip);
|
||||
json_t *json_memory_view = json_object_get(json_ip, "memory-view");
|
||||
if (json_is_object(json_memory_view)) {
|
||||
logger->debug("Parse memory view of {}", *ip);
|
||||
|
||||
// Now find all slave address spaces this master can access
|
||||
const char* bus_name;
|
||||
json_t* json_bus;
|
||||
json_object_foreach(json_memory_view, bus_name, json_bus) {
|
||||
// Now find all slave address spaces this master can access
|
||||
const char *bus_name;
|
||||
json_t *json_bus;
|
||||
json_object_foreach(json_memory_view, bus_name, json_bus) {
|
||||
|
||||
// This IP has a memory view => it is a bus master somewhere
|
||||
// This IP has a memory view => it is a bus master somewhere
|
||||
|
||||
// Assemble name for master address space
|
||||
const std::string myAddrSpaceName =
|
||||
MemoryManager::getMasterAddrSpaceName(ip->getInstanceName(),
|
||||
bus_name);
|
||||
// Create a master address space
|
||||
const MemoryManager::AddressSpaceId myAddrSpaceId =
|
||||
MemoryManager::get().getOrCreateAddressSpace(myAddrSpaceName);
|
||||
// Assemble name for master address space
|
||||
const std::string myAddrSpaceName =
|
||||
MemoryManager::getMasterAddrSpaceName(ip->getInstanceName(),
|
||||
bus_name);
|
||||
// Create a master address space
|
||||
const MemoryManager::AddressSpaceId myAddrSpaceId =
|
||||
MemoryManager::get().getOrCreateAddressSpace(myAddrSpaceName);
|
||||
|
||||
ip->busMasterInterfaces[bus_name] = myAddrSpaceId;
|
||||
ip->busMasterInterfaces[bus_name] = myAddrSpaceId;
|
||||
|
||||
const char* instance_name;
|
||||
json_t* json_instance;
|
||||
json_object_foreach(json_bus, instance_name, json_instance) {
|
||||
const char *instance_name;
|
||||
json_t *json_instance;
|
||||
json_object_foreach(json_bus, instance_name, json_instance) {
|
||||
|
||||
const char* block_name;
|
||||
json_t* json_block;
|
||||
json_object_foreach(json_instance, block_name, json_block) {
|
||||
const char *block_name;
|
||||
json_t *json_block;
|
||||
json_object_foreach(json_instance, block_name, json_block) {
|
||||
|
||||
json_int_t base, high, size;
|
||||
json_error_t err;
|
||||
int ret = json_unpack_ex(json_block, &err, 0, "{ s: I, s: I, s: I }",
|
||||
"baseaddr", &base,
|
||||
"highaddr", &high,
|
||||
"size", &size
|
||||
);
|
||||
if (ret != 0)
|
||||
throw ConfigError(json_block, err, "", "Cannot parse address block {}/{}/{}/{}",
|
||||
ip->getInstanceName(),
|
||||
bus_name, instance_name, block_name);
|
||||
json_int_t base, high, size;
|
||||
json_error_t err;
|
||||
int ret = json_unpack_ex(json_block, &err, 0,
|
||||
"{ s: I, s: I, s: I }", "baseaddr", &base,
|
||||
"highaddr", &high, "size", &size);
|
||||
if (ret != 0)
|
||||
throw ConfigError(
|
||||
json_block, err, "", "Cannot parse address block {}/{}/{}/{}",
|
||||
ip->getInstanceName(), bus_name, instance_name, block_name);
|
||||
|
||||
// Get or create the slave address space
|
||||
const std::string slaveAddrSpace =
|
||||
MemoryManager::getSlaveAddrSpaceName(instance_name, block_name);
|
||||
// Get or create the slave address space
|
||||
const std::string slaveAddrSpace =
|
||||
MemoryManager::getSlaveAddrSpaceName(instance_name, block_name);
|
||||
|
||||
const MemoryManager::AddressSpaceId slaveAddrSpaceId =
|
||||
MemoryManager::get().getOrCreateAddressSpace(slaveAddrSpace);
|
||||
const MemoryManager::AddressSpaceId slaveAddrSpaceId =
|
||||
MemoryManager::get().getOrCreateAddressSpace(slaveAddrSpace);
|
||||
|
||||
// Create a new mapping to the slave address space
|
||||
MemoryManager::get().createMapping(static_cast<uintptr_t>(base),
|
||||
0,
|
||||
static_cast<uintptr_t>(size),
|
||||
bus_name,
|
||||
myAddrSpaceId,
|
||||
slaveAddrSpaceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create a new mapping to the slave address space
|
||||
MemoryManager::get().createMapping(
|
||||
static_cast<uintptr_t>(base), 0, static_cast<uintptr_t>(size),
|
||||
bus_name, myAddrSpaceId, slaveAddrSpaceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IP-specific setup via JSON config
|
||||
f->parse(*ip, json_ip);
|
||||
// IP-specific setup via JSON config
|
||||
f->parse(*ip, json_ip);
|
||||
|
||||
// Set polling mode
|
||||
f->configurePollingMode(*ip, (card->polling ? PollingMode::POLL : PollingMode::IRQ));
|
||||
// Set polling mode
|
||||
f->configurePollingMode(
|
||||
*ip, (card->polling ? PollingMode::POLL : PollingMode::IRQ));
|
||||
|
||||
// IP has been configured now
|
||||
configuredIps.push_back(std::move(ip));
|
||||
}
|
||||
// IP has been configured now
|
||||
configuredIps.push_back(std::move(ip));
|
||||
}
|
||||
|
||||
// Start and check IPs now
|
||||
for (auto &ip : configuredIps) {
|
||||
loggerStatic->info("Initializing {}", *ip);
|
||||
// Start and check IPs now
|
||||
for (auto &ip : configuredIps) {
|
||||
loggerStatic->info("Initializing {}", *ip);
|
||||
|
||||
// Translate all memory blocks that the IP needs to be accessible from
|
||||
// the process and cache in the instance, so this has not to be done at
|
||||
// runtime.
|
||||
for (auto &memoryBlock : ip->getMemoryBlocks()) {
|
||||
// Construct the global name of this address block
|
||||
const auto addrSpaceName =
|
||||
MemoryManager::getSlaveAddrSpaceName(ip->getInstanceName(),
|
||||
memoryBlock);
|
||||
// Translate all memory blocks that the IP needs to be accessible from
|
||||
// the process and cache in the instance, so this has not to be done at
|
||||
// runtime.
|
||||
for (auto &memoryBlock : ip->getMemoryBlocks()) {
|
||||
// Construct the global name of this address block
|
||||
const auto addrSpaceName = MemoryManager::getSlaveAddrSpaceName(
|
||||
ip->getInstanceName(), memoryBlock);
|
||||
|
||||
// Retrieve its address space identifier
|
||||
const auto addrSpaceId =
|
||||
MemoryManager::get().findAddressSpace(addrSpaceName);
|
||||
// Retrieve its address space identifier
|
||||
const auto addrSpaceId =
|
||||
MemoryManager::get().findAddressSpace(addrSpaceName);
|
||||
|
||||
// ... and save it in IP
|
||||
ip->slaveAddressSpaces.emplace(memoryBlock, addrSpaceId);
|
||||
// ... and save it in IP
|
||||
ip->slaveAddressSpaces.emplace(memoryBlock, addrSpaceId);
|
||||
|
||||
// Get the translation to the address space
|
||||
const auto &translation =
|
||||
MemoryManager::get().getTranslationFromProcess(addrSpaceId);
|
||||
// Get the translation to the address space
|
||||
const auto &translation =
|
||||
MemoryManager::get().getTranslationFromProcess(addrSpaceId);
|
||||
|
||||
// Cache it in the IP instance only with local name
|
||||
ip->addressTranslations.emplace(memoryBlock, translation);
|
||||
}
|
||||
// Cache it in the IP instance only with local name
|
||||
ip->addressTranslations.emplace(memoryBlock, translation);
|
||||
}
|
||||
|
||||
if (not ip->init()) {
|
||||
loggerStatic->error("Cannot start IP {}", *ip);
|
||||
continue;
|
||||
}
|
||||
if (not ip->init()) {
|
||||
throw RuntimeError("Failed to initialize IP {}", *ip);
|
||||
}
|
||||
|
||||
if (not ip->check()) {
|
||||
loggerStatic->error("Checking failed for IP {}", *ip);
|
||||
continue;
|
||||
}
|
||||
if (not ip->check()) {
|
||||
throw RuntimeError("Failed to check IP {}", *ip);
|
||||
}
|
||||
|
||||
// Will only be reached if the IP successfully was initialized
|
||||
initializedIps.push_back(std::move(ip));
|
||||
}
|
||||
// Will only be reached if the IP successfully was initialized
|
||||
initializedIps.push_back(std::move(ip));
|
||||
}
|
||||
|
||||
loggerStatic->debug("Initialized IPs:");
|
||||
for (auto &ip : initializedIps) {
|
||||
loggerStatic->debug(" {}", *ip);
|
||||
}
|
||||
loggerStatic->debug("Initialized IPs:");
|
||||
for (auto &ip : initializedIps) {
|
||||
loggerStatic->debug(" {}", *ip);
|
||||
}
|
||||
|
||||
return initializedIps;
|
||||
return initializedIps;
|
||||
}
|
||||
|
||||
void Core::dump()
|
||||
{
|
||||
logger->info("IP: {}", *this);
|
||||
for (auto& [num, irq] : irqs) {
|
||||
logger->info(" IRQ {}: {}:{}",
|
||||
num, irq.irqController->getInstanceName(), irq.num);
|
||||
}
|
||||
void Core::dump() {
|
||||
logger->info("IP: {}", *this);
|
||||
for (auto &[num, irq] : irqs) {
|
||||
logger->info(" IRQ {}: {}:{}", num, irq.irqController->getInstanceName(),
|
||||
irq.num);
|
||||
}
|
||||
|
||||
for (auto& [block, translation] : addressTranslations) {
|
||||
logger->info(" Memory {}: {}", block, translation);
|
||||
}
|
||||
for (auto &[block, translation] : addressTranslations) {
|
||||
logger->info(" Memory {}: {}", block, translation);
|
||||
}
|
||||
}
|
||||
|
||||
CoreFactory* CoreFactory::lookup(const Vlnv &vlnv)
|
||||
{
|
||||
for (auto &ip : plugin::registry->lookup<CoreFactory>()) {
|
||||
if (ip->getCompatibleVlnv() == vlnv)
|
||||
return ip;
|
||||
}
|
||||
CoreFactory *CoreFactory::lookup(const Vlnv &vlnv) {
|
||||
for (auto &ip : plugin::registry->lookup<CoreFactory>()) {
|
||||
if (ip->getCompatibleVlnv() == vlnv)
|
||||
return ip;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uintptr_t Core::getLocalAddr(const MemoryBlockName &block, uintptr_t address) const
|
||||
{
|
||||
// Throws exception if block not present
|
||||
auto &translation = addressTranslations.at(block);
|
||||
uintptr_t Core::getLocalAddr(const MemoryBlockName &block,
|
||||
uintptr_t address) const {
|
||||
// Throws exception if block not present
|
||||
auto &translation = addressTranslations.at(block);
|
||||
|
||||
return translation.getLocalAddr(address);
|
||||
return translation.getLocalAddr(address);
|
||||
}
|
||||
|
||||
InterruptController* Core::getInterruptController(const std::string &interruptName) const
|
||||
{
|
||||
try {
|
||||
const IrqPort irq = irqs.at(interruptName);
|
||||
return irq.irqController;
|
||||
} catch (const std::out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
InterruptController *
|
||||
Core::getInterruptController(const std::string &interruptName) const {
|
||||
try {
|
||||
const IrqPort irq = irqs.at(interruptName);
|
||||
return irq.irqController;
|
||||
} catch (const std::out_of_range &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue