blob: 906123224883b65c4e59b94358896637deff0bd9 [file]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_DFF_CONTROLLER_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_DFF_CONTROLLER_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include <nlohmann/json_fwd.hpp>
#include "thermal_config.pb.h"
#include "thermal_controller_specification.pb.h"
#include "tlbmc/thermal/controller/algorithm/dff.h"
#include "tlbmc/thermal/controller/controller.h"
#include "tlbmc/thermal/zone_manager.h"
namespace milotic_tlbmc::thermal {
struct DffControllerParameters {
std::string id;
ZoneManager* absl_nonnull zone_manager ABSL_REQUIRE_EXPLICIT_INIT;
std::unique_ptr<DffThermalLoop> absl_nonnull dff_loop
ABSL_REQUIRE_EXPLICIT_INIT;
std::vector<std::string> input_sensors;
std::vector<std::string> affected_controller_ids;
};
/**
* `DffController` reads a number of, usually, power sensors
* and provides additive setpoints for the fan controllers such as PID fan
* controllers.
*
* Since this type of controllers reads from non-temperature sensors, it picks
* the maximum of all inputs, and performs the DFF thermal loop to derive a
* setpoint.
*
* This class is not thread-safe.
*/
class DffController : public ThermalController {
public:
~DffController() final = default;
static absl::StatusOr<std::unique_ptr<DffController>> Create(
DffControllerParameters params);
void ProcessThermalLoop() final;
double ProcessInput() final;
void ProcessOutput(double output) final;
ZoneManager* GetZoneManager() const { return zone_owner_; }
DffThermalLoop* GetDffLoop() const { return dff_loop_.get(); }
std::string GetId() const final { return id_; }
bool IsFanController() const final { return false; }
bool IsSupportiveController() const final { return true; }
const std::vector<std::string>& GetAffectedControllerIds() const final {
return affected_controller_ids_;
}
// DFF controller has no setpoint to be adjusted.
void AdjustSetpoint([[maybe_unused]] double offset) final {}
double GetLastOutput() const { return dff_loop_->GetLastOutput(); }
nlohmann::json ToJson() const;
// Setters of DFF coefficients for tuning purposes.
void SetCoeffH1(double coeff_h1) { dff_loop_->SetCoeffH1(coeff_h1); }
void SetCoeffH2(double coeff_h2) { dff_loop_->SetCoeffH2(coeff_h2); }
void SetCoeffH3(double coeff_h3) { dff_loop_->SetCoeffH3(coeff_h3); }
void SetCoeffF1(double coeff_f1) { dff_loop_->SetCoeffF1(coeff_f1); }
void SetCoeffF2(double coeff_f2) { dff_loop_->SetCoeffF2(coeff_f2); }
void SetCoeffF3(double coeff_f3) { dff_loop_->SetCoeffF3(coeff_f3); }
void SetReferencePower(double reference_power) {
dff_loop_->SetReferencePower(reference_power);
}
protected:
explicit DffController(absl::string_view id, ZoneManager* zone_manager,
std::unique_ptr<DffThermalLoop> absl_nonnull dff_loop,
std::vector<std::string> input_sensors,
std::vector<std::string> affected_controller_ids)
: ThermalController(),
id_(id),
zone_owner_(zone_manager),
dff_loop_(std::move(dff_loop)),
input_sensors_(std::move(input_sensors)),
affected_controller_ids_(std::move(affected_controller_ids)) {}
private:
const std::string id_;
// Use a raw pointer here to avoid circular dependency, as `ZoneManager`
// depends on `DffController` with `std::unique_ptr`.
// Every `ZoneManager` will be owned by the thermal control collector of
// tlBMC, and will live as long as the thermal control service is on.
ZoneManager* zone_owner_ = nullptr;
// Every `DffThermalLoop` will be owned by its thermal controller, and will
// live as long as the thermal control service is on.
std::unique_ptr<DffThermalLoop> dff_loop_;
std::vector<std::string> input_sensors_;
std::vector<std::string> affected_controller_ids_;
double last_output_ = 0.0;
};
} // namespace milotic_tlbmc::thermal
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_DFF_CONTROLLER_H_