fsm/src/fm10k/FM10K.h
DataHoarder 704df5b09d
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Implement data-driven YAML switch/port/vlan configuration
Implemented extra missing fields, added VPD hash match

Add extra configuration required for external port tagging, maybe do it via config
2021-11-13 00:18:13 +01:00

137 lines
4.8 KiB
C++

#pragma once
#include <cstdint>
#include <cfloat>
#include <algorithm>
#include <memory>
#include <vector>
#include "device/Device.h"
#include "registers/MGMT.h"
#include "Constants.h"
#include "Port.h"
#define FM10K_GET_REGISTER(i, t) i.getType<t>(t::ADDRESS)
#define FM10K_MAP_REGISTER(i, t) i.mapType<t>(t::ADDRESS)
#define FM10K_SET_REGISTER(i, t, v) i.setType<t>(t::ADDRESS, v)
#define FM10K_SET_REGISTER_FIELD(i, t, f, v) \
auto __f = FM10K_MAP_REGISTER(i, t); \
__f->fields. f = v
#define FM10K_GET_REGISTER_OFFSET(i, t, o) i.getType<t>(t::ADDRESS + o)
#define FM10K_MAP_REGISTER_OFFSET(i, t, o) i.mapType<t>(t::ADDRESS + o)
#define FM10K_SET_REGISTER_OFFSET(i, t, o, v) i.setType<t>(t::ADDRESS + o, v)
#define FM10K_SET_REGISTER_FIELD_OFFSET(i, t, o, f, v) \
auto __f = FM10K_MAP_REGISTER(i, t, o); \
__f->fields. f = v
namespace c4::yml {
class Tree;
}
namespace FM10K{
class FM10K {
public:
explicit FM10K(std::unique_ptr<Device> device);
bool valid() const{
return m_device->valid();
}
template<typename T> volatile T* mapType(uint32_t address) const {
return reinterpret_cast<volatile T*>(m_device->map32(address));
}
template<typename T> volatile T* mapRegister(uint32_t offset = 0) const{
return FM10K_MAP_REGISTER_OFFSET((*this), T, offset);
}
template<typename T> T getType(uint32_t address) const {
static_assert(sizeof(T) == 4 || sizeof(T) == 8, "Invalid type for FM10K::getType");
T t;
if(sizeof(T) == 4){
t.value = m_device->get32(address);
}else if(sizeof(T) == 8){
t = reinterpret_cast<T>(m_device->get64(address));
}
return std::move(t);
}
template<typename T> void setType(uint32_t address, const T& t) const {
static_assert(sizeof(T) == 4 || sizeof(T) == 8, "Invalid type for FM10K::setType");
if(sizeof(T) == 4){
m_device->set32(address, t.value);
}else if(sizeof(T) == 8){
m_device->set64(address, reinterpret_cast<uint64_t>(t));
}
return std::move(t);
}
uint32_t getValue(uint32_t address) const {
return m_device->get32(address);
}
void setValue(uint32_t address, uint32_t value) const {
m_device->set32(address, value);
}
struct HardwareInformation{
enum class Family{
FM10000 = 0xAE21
};
enum class Model{
// FMxppbb, x = series number, pp = Number of PCIe data ports, bb = Ethernet port bandwidth
//
// +- Max Ethernet Port Usage -+- PCIe Data -+- Estimated -+-----+--------------------------+
// | 100G | 40G | 10G | SGMII | Ports | WC Power | ROM | Use Cases |
// +-------+-----+-----+-------+-------------+-------------+-----+--------------------------+
FM10840 = 0, // | 4 | 9 | 36 | 36 | 8x4, 4x8 | 50 W | Yes | High perf compute fabric |
FM10420 = 1, // | 2 | 2 | 8 | 8 | 4x4, 2x8 | 38 W | Yes | Low cost compute fabric |
FM10824 = 2, // | 0 | 6 | 24 | 36 | 8x4, 4x8 | 43 W | No | 10G/40G/100GbE NIC |
FM10064 = 3, // | 6 | 9 | 36 | 36 | 0 | 47 W | No | Microserver switch |
FM10036 = 4 // | 0 | 0 | 0 | 0 | 0 | 39 W | No | Low cost 10GbE switch |
// +-------+-----+-----+-------+-------------+-------------+-----+--------------------------+
};
enum class ChipVersion{
A0 = 0,
B0 = 1
};
Family family;
Model model;
ChipVersion chipVersion;
};
const HardwareInformation& getHardwareInformation() const;
std::string getHardwareInformationString() const;
static void wait(uint32_t microseconds);
static void wait_ns(uint32_t nanoseconds);
Port& addPort(uint32_t logicalPort, uint32_t physicalPort){
m_ports.emplace_back(m_ports.size(), logicalPort, physicalPort);
return m_ports.back();
}
Port* getPort(uint32_t portIndex){
return portIndex < m_ports.size() ? &m_ports.back() : nullptr;
}
bool initialize(const c4::yml::Tree& tree) const;
bool isPEPEnabled(uint8_t pep) const;
protected:
private:
std::unique_ptr<Device> m_device;
HardwareInformation m_hwInfo{};
std::vector<Port> m_ports;
};
}