Program Listing for File trickle.cpp
↰ Return to documentation for file (trickle/trickle.cpp)
#include "trickle.hpp"
#include "config.hpp"
namespace trickle {
template <class Config, class Device, class Buffer>
void Trickle<Config, Device, Buffer>::start()
{
ERS_INFO(std::format("Number of PCIe endpoints to serve {}", cfg->get_number_devices()));
int tot_elinks{0};
for (const auto & dev : devices){
//Get DMA ID
const int dev_no = dev->get_device_number();
constexpr static auto no_lock_mask = 0u;
if(dev->open_device(no_lock_mask) != 0 ){
ers::error(felix_log::trickle_issue(ERS_HERE, std::format("Trickle - cannot open device {} ", dev_no)));
continue;
};
const int dmaid = dev->get_trickle_dmaid();
dev->close_device();
ERS_INFO(std::format("Opening PCIe endpoint {}", dev_no));
const unsigned int lock_mask = dev->make_dma_lock_mask({dmaid});
if(dev->open_device(lock_mask) != 0 ){
ers::error(felix_log::trickle_issue(ERS_HERE, std::format("Trickle - cannot open device {} ", dev_no)));
continue;
};
//Initialize bus and DMA buffers
auto dma_buf = dma_buffers.at(dev_no);
dma_buf->set_dmaid(dmaid);
const auto data_format = dev->get_fromhost_data_format();
dma_buf->set_encoder_data_format(data_format);
m_bus_map.try_emplace(dev_no, cfg->network.bus_dir, cfg->network.bus_groupname, dmaid, cfg->network.verbose_bus);
const std::string dma_name = std::format("trickle-d{}-{}", dev_no, dmaid);
ERS_INFO(std::format("Allocating DMA buffer {} of size {} MB (PCIe endpoint {}, DMAID {})", dma_name, cfg->resource.cmem_buffersize/1024/1024, dev_no, dmaid));
dma_buf->allocate_buffer(cfg->resource.cmem_buffersize, dma_name, cfg->vmem, cfg->resource.free_previous_cmem);
const std::vector<Elink> elinks = dma_buf->get_elinks();
const auto base_port = cfg->network.ports.at(dev_no);
const auto computed_port = base_port == 0 ? base_port : base_port + 1000u * dev_no;
if (computed_port > std::numeric_limits<uint16_t>::max()) {
ers::warning(felix_log::trickle_issue(std::format("Port {} number overflow! Starting port is too big", computed_port)));
}
const uint16_t port = static_cast<uint16_t>(computed_port);
const std::string trickle_info = std::format("d{}Trkl", dev_no);
m_trickle_managers[dev_no].emplace_back(dma_buf, network::utility::create_unbuffered_receiver(NetworkMode::tcp,
cfg->network.ip,
port,
cfg->network.netio_pages,
cfg->network.netio_pagesize,
trickle_info));
const uint16_t actual_port = m_trickle_managers.at(dev_no).back().get_receiver_port();
std::vector<felixbus::FelixBusElinkInfo> bus_info{};
std::ranges::transform(elinks, std::back_inserter(bus_info), [this, &actual_port](const Elink& e) {
return felixbus::FelixBusElinkInfo{
.fid = e.fid,
.ip = cfg->network.ip,
.port = actual_port,
.unbuffered = true,
.pubsub = false,
.tcp = true,
.stream = e.has_streams,
.netio_pages = cfg->network.netio_pages,
.netio_pagesize = cfg->network.netio_pagesize,
};
});
m_bus_map.at(dev_no).publish(bus_info);
ERS_INFO(std::format("PCIe endpoint {}, DMA {} receiving data on port {}", dev_no, dmaid, actual_port));
for(const auto & e : elinks) {
ERS_INFO(std::format("E-link {}: {:#5x} {:#18x} (channel {} egroup {} epath {})",
tot_elinks, e.lid, e.fid,
dev->get_channel(e.lid),
dev->get_egroup(e.lid),
dev->get_epath(e.lid)));
++tot_elinks;
}
}
}
template <class Config, class Device, class Buffer>
void Trickle<Config, Device, Buffer>::stop()
{
for (auto& dma : dma_buffers) {
dma.second->stop();
}
}
} // namespace trickle
// Explicit instantiations for the specific template combinations used
namespace trickle {
template class Trickle<ConfigTrickle, FlxDevice, FlxFromHostBuffer>;
template class Trickle<ConfigTrickleToFile, FileDevice, FileFromHostBuffer>;
}