mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
card: add API to create a single card
this is a preparation for allowing defining the card in the node config rather than separately. Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
parent
ee068621e6
commit
4b7ed781c0
3 changed files with 114 additions and 92 deletions
|
@ -17,8 +17,13 @@ namespace fpga {
|
|||
std::shared_ptr<fpga::Card>
|
||||
setupFpgaCard(const std::string &configFile, const std::string &fpgaName);
|
||||
|
||||
std::shared_ptr<fpga::Card>
|
||||
createCard(json_t *config, std::list<std::shared_ptr<fpga::Card>> &cards,
|
||||
std::filesystem::path &searchPath,
|
||||
std::shared_ptr<kernel::vfio::Container> vfioContainer,
|
||||
std::string card_name = "anonymous Card");
|
||||
int createCards(json_t *config, std::list<std::shared_ptr<fpga::Card>> &cards,
|
||||
std::filesystem::path &searchPath);
|
||||
std::filesystem::path &searchPath, std::shared_ptr<kernel::vfio::Container> vfioContainer = nullptr);
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<fpga::ip::Node>>>
|
||||
getAuroraChannels(std::shared_ptr<fpga::Card> card);
|
||||
|
@ -55,81 +60,82 @@ protected:
|
|||
int dstAsInt;
|
||||
};
|
||||
|
||||
class BufferedSampleFormatter {
|
||||
public:
|
||||
virtual void format(float value) = 0;
|
||||
virtual void output(std::ostream& out)
|
||||
{
|
||||
out << buf.data() << std::flush;
|
||||
clearBuf();
|
||||
}
|
||||
virtual void clearBuf()
|
||||
{
|
||||
for (size_t i = 0; i < bufSamples && buf[i*bufSampleSize] != '\0'; i++) {
|
||||
buf[i*bufSampleSize] = '\0';
|
||||
}
|
||||
currentBufLoc = 0;
|
||||
}
|
||||
protected:
|
||||
std::vector<char> buf;
|
||||
const size_t bufSamples;
|
||||
const size_t bufSampleSize;
|
||||
size_t currentBufLoc;
|
||||
class BufferedSampleFormatter {
|
||||
public:
|
||||
virtual void format(float value) = 0;
|
||||
virtual void output(std::ostream &out) {
|
||||
out << buf.data() << std::flush;
|
||||
clearBuf();
|
||||
}
|
||||
virtual void clearBuf() {
|
||||
for (size_t i = 0; i < bufSamples && buf[i * bufSampleSize] != '\0';
|
||||
i++) {
|
||||
buf[i * bufSampleSize] = '\0';
|
||||
}
|
||||
currentBufLoc = 0;
|
||||
}
|
||||
|
||||
BufferedSampleFormatter(const size_t bufSamples, const size_t bufSampleSize) :
|
||||
buf(bufSamples*bufSampleSize+1), // Leave room for a final `\0'
|
||||
bufSamples(bufSamples),
|
||||
bufSampleSize(bufSampleSize),
|
||||
currentBufLoc(0) {};
|
||||
BufferedSampleFormatter() = delete;
|
||||
BufferedSampleFormatter(const BufferedSampleFormatter&) = delete;
|
||||
virtual char* nextBufPos()
|
||||
{
|
||||
return &buf[(currentBufLoc++)*bufSampleSize];
|
||||
}
|
||||
};
|
||||
protected:
|
||||
std::vector<char> buf;
|
||||
const size_t bufSamples;
|
||||
const size_t bufSampleSize;
|
||||
size_t currentBufLoc;
|
||||
|
||||
class BufferedSampleFormatterShort : public BufferedSampleFormatter {
|
||||
public:
|
||||
BufferedSampleFormatterShort(size_t bufSizeInSamples) :
|
||||
BufferedSampleFormatter(bufSizeInSamples, formatStringSize) {};
|
||||
BufferedSampleFormatter(const size_t bufSamples, const size_t bufSampleSize)
|
||||
: buf(bufSamples * bufSampleSize + 1), // Leave room for a final `\0'
|
||||
bufSamples(bufSamples), bufSampleSize(bufSampleSize),
|
||||
currentBufLoc(0){};
|
||||
BufferedSampleFormatter() = delete;
|
||||
BufferedSampleFormatter(const BufferedSampleFormatter &) = delete;
|
||||
virtual char *nextBufPos() {
|
||||
return &buf[(currentBufLoc++) * bufSampleSize];
|
||||
}
|
||||
};
|
||||
|
||||
virtual void format(float value) override
|
||||
{
|
||||
size_t chars;
|
||||
if ((chars = std::snprintf(nextBufPos(), formatStringSize+1, formatString, value)) > (int)formatStringSize) {
|
||||
throw RuntimeError("Output buffer too small. Expected " + std::to_string(formatStringSize) +
|
||||
" characters, got " + std::to_string(chars));
|
||||
}
|
||||
}
|
||||
class BufferedSampleFormatterShort : public BufferedSampleFormatter {
|
||||
public:
|
||||
BufferedSampleFormatterShort(size_t bufSizeInSamples)
|
||||
: BufferedSampleFormatter(bufSizeInSamples, formatStringSize){};
|
||||
|
||||
protected:
|
||||
static constexpr char formatString[] = "%013.6f\n";
|
||||
static constexpr size_t formatStringSize = 14;
|
||||
};
|
||||
virtual void format(float value) override {
|
||||
size_t chars;
|
||||
if ((chars = std::snprintf(nextBufPos(), formatStringSize + 1,
|
||||
formatString, value)) >
|
||||
(int)formatStringSize) {
|
||||
throw RuntimeError("Output buffer too small. Expected " +
|
||||
std::to_string(formatStringSize) +
|
||||
" characters, got " + std::to_string(chars));
|
||||
}
|
||||
}
|
||||
|
||||
class BufferedSampleFormatterLong : public BufferedSampleFormatter {
|
||||
public:
|
||||
BufferedSampleFormatterLong(size_t bufSizeInSamples) :
|
||||
BufferedSampleFormatter(bufSizeInSamples, formatStringSize),
|
||||
sampleCnt(0) {};
|
||||
protected:
|
||||
static constexpr char formatString[] = "%013.6f\n";
|
||||
static constexpr size_t formatStringSize = 14;
|
||||
};
|
||||
|
||||
virtual void format(float value) override
|
||||
{
|
||||
if (std::snprintf(nextBufPos(), formatStringSize+1, formatString, sampleCnt, value) > (int)formatStringSize) {
|
||||
throw RuntimeError("Output buffer too small");
|
||||
}
|
||||
sampleCnt = (sampleCnt+1) % 100000;
|
||||
}
|
||||
class BufferedSampleFormatterLong : public BufferedSampleFormatter {
|
||||
public:
|
||||
BufferedSampleFormatterLong(size_t bufSizeInSamples)
|
||||
: BufferedSampleFormatter(bufSizeInSamples, formatStringSize),
|
||||
sampleCnt(0){};
|
||||
|
||||
protected:
|
||||
static constexpr char formatString[] = "%05zd: %013.6f\n";
|
||||
static constexpr size_t formatStringSize = 22;
|
||||
size_t sampleCnt;
|
||||
};
|
||||
virtual void format(float value) override {
|
||||
if (std::snprintf(nextBufPos(), formatStringSize + 1, formatString,
|
||||
sampleCnt, value) > (int)formatStringSize) {
|
||||
throw RuntimeError("Output buffer too small");
|
||||
}
|
||||
sampleCnt = (sampleCnt + 1) % 100000;
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr char formatString[] = "%05zd: %013.6f\n";
|
||||
static constexpr size_t formatStringSize = 22;
|
||||
size_t sampleCnt;
|
||||
};
|
||||
|
||||
std::unique_ptr<BufferedSampleFormatter> getBufferedSampleFormatter(const std::string &format, size_t bufSizeInSamples);
|
||||
std::unique_ptr<BufferedSampleFormatter>
|
||||
getBufferedSampleFormatter(const std::string &format,
|
||||
size_t bufSizeInSamples);
|
||||
|
||||
} // namespace fpga
|
||||
} // namespace villas
|
||||
|
|
|
@ -48,7 +48,7 @@ PCIeCardFactory::make(json_t *json_card, std::string card_name,
|
|||
if (ret != 0)
|
||||
throw ConfigError(json_card, err, "", "Failed to parse card");
|
||||
|
||||
auto card = std::unique_ptr<PCIeCard>(make());
|
||||
auto card = std::shared_ptr<PCIeCard>(make());
|
||||
|
||||
// Populate generic properties
|
||||
card->name = std::string(card_name);
|
||||
|
|
|
@ -225,11 +225,46 @@ void fpga::setupColorHandling()
|
|||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<fpga::Card>
|
||||
fpga::createCard(json_t *config, std::list<std::shared_ptr<fpga::Card>> &cards,
|
||||
std::filesystem::path &searchPath,
|
||||
std::shared_ptr<kernel::vfio::Container> vfioContainer,
|
||||
std::string card_name) {
|
||||
auto configDir = std::filesystem::path().parent_path();
|
||||
|
||||
const char *interfaceName;
|
||||
json_error_t err;
|
||||
logger->info("Found config for FPGA card {}", card_name);
|
||||
int ret =
|
||||
json_unpack_ex(config, &err, 0, "{s: s}", "interface", &interfaceName);
|
||||
if (ret) {
|
||||
throw ConfigError(config, err, "interface",
|
||||
"Failed to parse interface name for card {}", card_name);
|
||||
}
|
||||
std::string interfaceNameStr(interfaceName);
|
||||
if (interfaceNameStr == "pcie") {
|
||||
auto card = fpga::PCIeCardFactory::make(config, std::string(card_name),
|
||||
vfioContainer, searchPath);
|
||||
if (card) {
|
||||
cards.push_back(card);
|
||||
return card;
|
||||
}
|
||||
return nullptr;
|
||||
} else if (interfaceNameStr == "platform") {
|
||||
throw RuntimeError("Platform interface not implemented yet");
|
||||
} else {
|
||||
throw RuntimeError("Unknown interface type {}", interfaceNameStr);
|
||||
}
|
||||
}
|
||||
|
||||
int fpga::createCards(json_t *config,
|
||||
std::list<std::shared_ptr<fpga::Card>> &cards,
|
||||
std::filesystem::path &searchPath) {
|
||||
std::filesystem::path &searchPath,
|
||||
std::shared_ptr<kernel::vfio::Container> vfioContainer) {
|
||||
int numFpgas = 0;
|
||||
auto vfioContainer = std::make_shared<kernel::vfio::Container>();
|
||||
if (vfioContainer == nullptr) {
|
||||
vfioContainer = std::make_shared<kernel::vfio::Container>();
|
||||
}
|
||||
auto configDir = std::filesystem::path().parent_path();
|
||||
|
||||
json_t *fpgas = json_object_get(config, "fpgas");
|
||||
|
@ -241,28 +276,9 @@ int fpga::createCards(json_t *config,
|
|||
const char *card_name;
|
||||
json_t *json_card;
|
||||
json_object_foreach(fpgas, card_name, json_card) {
|
||||
const char *interfaceName;
|
||||
json_error_t err;
|
||||
logger->info("Found config for FPGA card {}", card_name);
|
||||
int ret = json_unpack_ex(json_card, &err, 0, "{s: s}", "interface",
|
||||
&interfaceName);
|
||||
if (ret) {
|
||||
throw ConfigError(json_card, err, "interface",
|
||||
"Failed to parse interface name for card {}",
|
||||
card_name);
|
||||
}
|
||||
std::string interfaceNameStr(interfaceName);
|
||||
if (interfaceNameStr == "pcie") {
|
||||
auto card = fpga::PCIeCardFactory::make(json_card, std::string(card_name),
|
||||
vfioContainer, searchPath);
|
||||
if (card) {
|
||||
cards.push_back(std::move(card));
|
||||
numFpgas++;
|
||||
}
|
||||
} else if (interfaceNameStr == "platform") {
|
||||
throw RuntimeError("Platform interface not implemented yet");
|
||||
} else {
|
||||
throw RuntimeError("Unknown interface type {}", interfaceNameStr);
|
||||
if (createCard(json_card, cards, searchPath, vfioContainer, card_name) !=
|
||||
nullptr) {
|
||||
numFpgas++;
|
||||
}
|
||||
}
|
||||
return numFpgas;
|
||||
|
|
Loading…
Add table
Reference in a new issue