<commit_before>#include "physics/transforms.hpp"

#include <limits>

#include "geometry/frame.hpp"
#include "base/not_null.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "physics/degrees_of_freedom.hpp"
#include "physics/massive_body.hpp"
#include "physics/massless_body.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"
#include "serialization/geometry.pb.h"
#include "testing_utilities/almost_equals.hpp"
#include "testing_utilities/componentwise.hpp"
#include "testing_utilities/vanishes_before.hpp"

namespace principia {

using base::make_not_null_unique;
using geometry::Frame;
using quantities::Length;
using quantities::Mass;
using quantities::SIUnit;
using quantities::Speed;
using quantities::Time;
using testing_utilities::AlmostEquals;
using testing_utilities::Componentwise;
using testing_utilities::VanishesBefore;
using ::testing::Eq;
using ::testing::Lt;

namespace physics {

namespace {
const int kNumberOfPoints = 20;
}  // namespace

class TransformsTest : public testing::Test {
 protected:
  using From = Frame<serialization::Frame::TestTag,
                     serialization::Frame::FROM, true>;
  using Through = Frame<serialization::Frame::TestTag,
                        serialization::Frame::THROUGH, false>;
  using To = Frame<serialization::Frame::TestTag,
                   serialization::Frame::TO, true>;

  TransformsTest()
      : body1_(MassiveBody(1 * SIUnit<Mass>())),
        body2_(MassiveBody(3 * SIUnit<Mass>())),
        body1_from_(make_not_null_unique<Trajectory<From>>(&body1_)),
        body2_from_(make_not_null_unique<Trajectory<From>>(&body2_)),
        body1_to_(make_not_null_unique<Trajectory<To>>(&body1_)),
        body2_to_(make_not_null_unique<Trajectory<To>>(&body2_)),
        satellite_from_(make_not_null_unique<Trajectory<From>>(&satellite_)) {
    body1_from_fn_ =
        [this]() -> Trajectory<From> const& { return *this->body1_from_; };
    body2_from_fn_ =
        [this]() -> Trajectory<From> const& { return *this->body2_from_; };
    body1_to_fn_ =
        [this]() -> Trajectory<To> const& { return *this->body1_to_; };
    body2_to_fn_ =
        [this]() -> Trajectory<To> const& { return *this->body2_to_; };

    // The various bodies move have both a position and a velocity that
    // increases linearly with time.  This is not a situation that's physically
    // possible, but we don't care, all we want is to make sure that the
    // transforms are properly performed: |Transforms| doesn't know anything
    // about physics.  Also, the trajectories were chosen so that we are not in
    // any "special case" with respect to the positions or the velocities.
    for (int i = 1; i <= kNumberOfPoints; ++i) {
      body1_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({1 * i * SIUnit<Length>(),
                                              2 * i * SIUnit<Length>(),
                                              3 * i * SIUnit<Length>()})),
                      Velocity<From>({4 * i * SIUnit<Speed>(),
                                      8 * i * SIUnit<Speed>(),
                                      16 * i * SIUnit<Speed>()})));
      body2_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({-1 * i * SIUnit<Length>(),
                                              -2 * i * SIUnit<Length>(),
                                              3 * i * SIUnit<Length>()})),
                      Velocity<From>({-4 * i * SIUnit<Speed>(),
                                      8 * i * SIUnit<Speed>(),
                                      -16 * i * SIUnit<Speed>()})));
      satellite_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({10 * i * SIUnit<Length>(),
                                              -20 * i * SIUnit<Length>(),
                                              30 * i * SIUnit<Length>()})),
                      Velocity<From>({40 * i * SIUnit<Speed>(),
                                      -80 * i * SIUnit<Speed>(),
                                      160 * i * SIUnit<Speed>()})));
    }
  }

  MassiveBody body1_;
  MassiveBody body2_;
  MasslessBody satellite_;
  not_null<std::unique_ptr<Trajectory<From>>> body1_from_;
  not_null<std::unique_ptr<Trajectory<From>>> body2_from_;
  not_null<std::unique_ptr<Trajectory<To>>> body1_to_;
  not_null<std::unique_ptr<Trajectory<To>>> body2_to_;
  not_null<std::unique_ptr<Trajectory<From>>> satellite_from_;
  Transforms<From, Through, To>::LazyTrajectory<From> body1_from_fn_;
  Transforms<From, Through, To>::LazyTrajectory<From> body2_from_fn_;
  Transforms<From, Through, To>::LazyTrajectory<To> body1_to_fn_;
  Transforms<From, Through, To>::LazyTrajectory<To> body2_to_fn_;
};

// This transform is simple enough that we can compute its effect by hand.  This
// test verifies that we get the expected result both in |Through| and in |To|.
TEST_F(TransformsTest, BodyCentredNonRotating) {
  auto const transforms = Transforms<From, Through, To>::BodyCentredNonRotating(
                    body1_from_fn_, body1_to_fn_);
  Trajectory<Through> body1_through(&body1_);

  int i = 1;
  for (auto it = transforms->first(*satellite_from_);
       !it.at_end();
       ++it, ++i) {
    DegreesOfFreedom<Through> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom,
                Componentwise(
                    Eq(Through::origin +
                       Displacement<Through>({9 * i * SIUnit<Length>(),
                                              -22 * i * SIUnit<Length>(),
                                              27 * i * SIUnit<Length>()})),
                    Eq(Velocity<Through>({36 * i * SIUnit<Speed>(),
                                          -88 * i * SIUnit<Speed>(),
                                          144 * i * SIUnit<Speed>()})))) << i;
    body1_through.Append(Instant(i * SIUnit<Time>()), degrees_of_freedom);
  }

  i = 1;
  for (auto it = transforms->second(body1_through);
       !it.at_end();
       ++it, ++i) {
    body1_to_->Append(
        Instant(i * SIUnit<Time>()),
                DegreesOfFreedom<To>(
                    Position<To>(
                        Displacement<To>({3 * i * SIUnit<Length>(),
                                          1 * i * SIUnit<Length>(),
                                          2 * i * SIUnit<Length>()})),
                    Velocity<To>({16 * i * SIUnit<Speed>(),
                                  4 * i * SIUnit<Speed>(),
                                  8 * i * SIUnit<Speed>()})));

    DegreesOfFreedom<To> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom,
                Componentwise(
                    Eq(To::origin +
                        Displacement<To>({12 * i * SIUnit<Length>(),
                                          -21 * i * SIUnit<Length>(),
                                          29 * i * SIUnit<Length>()})),
                    Eq(Velocity<To>({36 * i * SIUnit<Speed>(),
                                      -88 * i * SIUnit<Speed>(),
                                      144 * i * SIUnit<Speed>()})))) << i;
  }
}

// Check that the computations we do match those done using Mathematica.
TEST_F(TransformsTest, SatelliteBarycentricRotating) {
  auto const transforms = Transforms<From, Through, To>::BarycentricRotating(
                              body1_from_fn_, body1_to_fn_,
                              body2_from_fn_, body2_to_fn_);
  Trajectory<Through> satellite_through(&satellite_);

  int i = 1;
  for (auto it = transforms->first(*satellite_from_);
       !it.at_end();
       ++it, ++i) {
    DegreesOfFreedom<Through> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom.position() - Position<Through>(),
                AlmostEquals(Displacement<Through>(
                    {-5.5 * sqrt(5.0) * i * SIUnit<Length>(),
                     62.0 * sqrt(5.0 / 21.0) * i * SIUnit<Length>(),
                     53.0 / sqrt(21.0) * i * SIUnit<Length>()}),
                    1, 8)) << i;
    EXPECT_THAT(degrees_of_freedom.velocity(),
                AlmostEquals(Velocity<Through>(
                    {(362.0 / sqrt(5.0)) * i * SIUnit<Speed>(),
                     (2776.0 / sqrt(105.0)) * i * SIUnit<Speed>(),
                     176.0 / sqrt(21.0) * i * SIUnit<Speed>()}),
                    1, 10)) << i;
    satellite_through.Append(Instant(i * SIUnit<Time>()), degrees_of_freedom);
  }

  i = 1;
  for (auto it = transforms->second(satellite_through);
       !it.at_end();
       ++it, ++i) {
      body1_to_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<To>(
                      Position<To>(
                          Displacement<To>({3 * i * SIUnit<Length>(),
                                            1 * i * SIUnit<Length>(),
                                            2 * i * SIUnit<Length>()})),
                      Velocity<To>({16 * i * SIUnit<Speed>(),
                                    4 * i * SIUnit<Speed>(),
                                    8 * i * SIUnit<Speed>()})));
      body2_to_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<To>(
                      Position<To>(
                          Displacement<To>({3 * i * SIUnit<Length>(),
                                           -1 * i * SIUnit<Length>(),
                                           -2 * i * SIUnit<Length>()})),
                      Velocity<To>({-16 * i * SIUnit<Speed>(),
                                    4 * i * SIUnit<Speed>(),
                                    8 * i * SIUnit<Speed>()})));

    DegreesOfFreedom<To> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom.position() - To::origin,
                AlmostEquals(Displacement<To>(
                    {(3.0 + 62.0 * sqrt(5.0 / 21.0)) * i * SIUnit<Length>(),
                     (-6.0 + 106.0 / sqrt(105.0)) * i * SIUnit<Length>(),
                     (-12.0 - 53.0 / sqrt(105.0)) * i * SIUnit<Length>()}),
                    3, 21))
        << i;
    EXPECT_THAT(degrees_of_freedom.velocity(),
                AlmostEquals(Velocity<To>(
                    {2776.0 / sqrt(105.0) * i * SIUnit<Speed>(),
                     (72.4 + 352.0 / sqrt(105.0)) * i * SIUnit<Speed>(),
                     (144.8 - 176.0 / sqrt(105.0)) * i * SIUnit<Speed>()}),
                    1, 8)) << i;
  }
}

// Check that the bodies remain on the invariant line and at the right distance
// from each other and from the barycentre, and that the barycentre is the
// centre of the coordinates.
TEST_F(TransformsTest, BodiesBarycentricRotating) {
  auto const transforms = Transforms<From, Through, To>::BarycentricRotating(
                              body1_from_fn_, body1_to_fn_,
                              body2_from_fn_, body2_to_fn_);
  Trajectory<Through> body1_through(&body1_);
  Trajectory<Through> body2_through(&body2_);

  int i = 1;
  for (auto it1 = transforms->first(*body1_from_),
            it2 = transforms->first(*body2_from_);
       !it1.at_end() && !it2.at_end();
       ++it1, ++it2, ++i) {
    Length const l = i * SIUnit<Length>();
    Speed const s = i * SIUnit<Speed>();
    DegreesOfFreedom<Through> const degrees_of_freedom1 =
        it1.degrees_of_freedom();
    DegreesOfFreedom<Through> const degrees_of_freedom2 =
        it2.degrees_of_freedom();

    EXPECT_THAT(degrees_of_freedom1.position() - Through::origin,
                Componentwise(AlmostEquals(1.5 * sqrt(5.0) * l, 0, 1),
                              VanishesBefore(l, 0, 4),
                              VanishesBefore(l, 0, 2)));
    EXPECT_THAT(degrees_of_freedom2.position() - Through::origin,
                Componentwise(AlmostEquals(-0.5 * sqrt(5.0) * l, 0, 2),
                              VanishesBefore(l, 0, 2),
                              VanishesBefore(l, 0, 1)));
    EXPECT_THAT(degrees_of_freedom1.velocity(),
                Componentwise(AlmostEquals(6.0 / sqrt(5.0) * s, 0, 7),
                              VanishesBefore(s, 0, 34),
                              VanishesBefore(s, 0, 2)));
    EXPECT_THAT(degrees_of_freedom2.velocity(),
                Componentwise(AlmostEquals(-2.0 / sqrt(5.0) * s, 0, 14),
                              VanishesBefore(s, 0, 16),
                              VanishesBefore(s, 0, 1)));

    DegreesOfFreedom<Through> const barycentre_degrees_of_freedom =
        Barycentre<Through, Mass>({degrees_of_freedom1, degrees_of_freedom2},
                                  {body1_.mass(), body2_.mass()});
    EXPECT_THAT(barycentre_degrees_of_freedom.position() - Through::origin,
                Componentwise(VanishesBefore(l, 0, 1),
                              VanishesBefore(l, 0, 2),
                              VanishesBefore(l, 0, 1)));
    EXPECT_THAT(barycentre_degrees_of_freedom.velocity(),
                Componentwise(VanishesBefore(s, 0, 14),
                              VanishesBefore(s, 0, 7),
                              VanishesBefore(s, 0, 1)));

    Length const length = (degrees_of_freedom1.position() -
                           degrees_of_freedom2.position()).Norm();
    EXPECT_THAT(length,
                AlmostEquals(2.0 * sqrt(5.0) * i * SIUnit<Length>(), 0, 2));
  }
}

}  // namespace physics
}  // namespace principia
<commit_msg>Test.<commit_after>#include "physics/transforms.hpp"

#include <limits>

#include "geometry/frame.hpp"
#include "base/not_null.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "physics/degrees_of_freedom.hpp"
#include "physics/massive_body.hpp"
#include "physics/massless_body.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"
#include "serialization/geometry.pb.h"
#include "testing_utilities/almost_equals.hpp"
#include "testing_utilities/componentwise.hpp"
#include "testing_utilities/vanishes_before.hpp"

namespace principia {

using base::make_not_null_unique;
using geometry::Frame;
using quantities::Length;
using quantities::Mass;
using quantities::SIUnit;
using quantities::Speed;
using quantities::Time;
using testing_utilities::AlmostEquals;
using testing_utilities::Componentwise;
using testing_utilities::VanishesBefore;
using ::testing::Eq;
using ::testing::Lt;

namespace physics {

namespace {
const int kNumberOfPoints = 20;
}  // namespace

class TransformsTest : public testing::Test {
 protected:
  using From = Frame<serialization::Frame::TestTag,
                     serialization::Frame::FROM, true>;
  using Through = Frame<serialization::Frame::TestTag,
                        serialization::Frame::THROUGH, false>;
  using To = Frame<serialization::Frame::TestTag,
                   serialization::Frame::TO, true>;

  struct Functors {
    Trajectory<From> const& from_trajectory() const;
    Trajectory<Through> const& through_trajectory() const;
    Trajectory<To> const& to_trajectory() const;

    Trajectory<From>* from;
    Trajectory<Through>* through;
    Trajectory<To>* to;
  };

  TransformsTest()
      : body1_(MassiveBody(1 * SIUnit<Mass>())),
        body2_(MassiveBody(3 * SIUnit<Mass>())),
        body1_from_(make_not_null_unique<Trajectory<From>>(&body1_)),
        body2_from_(make_not_null_unique<Trajectory<From>>(&body2_)),
        body1_to_(make_not_null_unique<Trajectory<To>>(&body1_)),
        body2_to_(make_not_null_unique<Trajectory<To>>(&body2_)),
        satellite_from_(make_not_null_unique<Trajectory<From>>(&satellite_)),
        body1_fn_({body1_from_.get(), nullptr, body1_to_.get()}),
        body2_fn_({body2_from_.get(), nullptr, body2_to_.get()}),
        satellite_fn_({satellite_from_.get(), nullptr, nullptr}) {

    // The various bodies move have both a position and a velocity that
    // increases linearly with time.  This is not a situation that's physically
    // possible, but we don't care, all we want is to make sure that the
    // transforms are properly performed: |Transforms| doesn't know anything
    // about physics.  Also, the trajectories were chosen so that we are not in
    // any "special case" with respect to the positions or the velocities.
    for (int i = 1; i <= kNumberOfPoints; ++i) {
      body1_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({1 * i * SIUnit<Length>(),
                                              2 * i * SIUnit<Length>(),
                                              3 * i * SIUnit<Length>()})),
                      Velocity<From>({4 * i * SIUnit<Speed>(),
                                      8 * i * SIUnit<Speed>(),
                                      16 * i * SIUnit<Speed>()})));
      body2_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({-1 * i * SIUnit<Length>(),
                                              -2 * i * SIUnit<Length>(),
                                              3 * i * SIUnit<Length>()})),
                      Velocity<From>({-4 * i * SIUnit<Speed>(),
                                      8 * i * SIUnit<Speed>(),
                                      -16 * i * SIUnit<Speed>()})));
      satellite_from_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<From>(
                      Position<From>(
                          Displacement<From>({10 * i * SIUnit<Length>(),
                                              -20 * i * SIUnit<Length>(),
                                              30 * i * SIUnit<Length>()})),
                      Velocity<From>({40 * i * SIUnit<Speed>(),
                                      -80 * i * SIUnit<Speed>(),
                                      160 * i * SIUnit<Speed>()})));
    }
  }

  MassiveBody body1_;
  MassiveBody body2_;
  MasslessBody satellite_;
  not_null<std::unique_ptr<Trajectory<From>>> body1_from_;
  not_null<std::unique_ptr<Trajectory<From>>> body2_from_;
  not_null<std::unique_ptr<Trajectory<To>>> body1_to_;
  not_null<std::unique_ptr<Trajectory<To>>> body2_to_;
  not_null<std::unique_ptr<Trajectory<From>>> satellite_from_;
  Functors body1_fn_;
  Functors body2_fn_;
  Functors satellite_fn_;
};

// This transform is simple enough that we can compute its effect by hand.  This
// test verifies that we get the expected result both in |Through| and in |To|.
TEST_F(TransformsTest, BodyCentredNonRotating) {
  auto const transforms =
      Transforms<Functors, From, Through, To>::BodyCentredNonRotating(
          body1_fn_, &Functors::to_trajectory);
  Trajectory<Through> body1_through(&body1_);

  int i = 1;
  for (auto it = transforms->first(satellite_fn_, &Functors::from_trajectory);
       !it.at_end();
       ++it, ++i) {
    DegreesOfFreedom<Through> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom,
                Componentwise(
                    Eq(Through::origin +
                       Displacement<Through>({9 * i * SIUnit<Length>(),
                                              -22 * i * SIUnit<Length>(),
                                              27 * i * SIUnit<Length>()})),
                    Eq(Velocity<Through>({36 * i * SIUnit<Speed>(),
                                          -88 * i * SIUnit<Speed>(),
                                          144 * i * SIUnit<Speed>()})))) << i;
    body1_through.Append(Instant(i * SIUnit<Time>()), degrees_of_freedom);
  }
  body1_fn_.through = &body1_through;

  i = 1;
  for (auto it = transforms->second(body1_fn_, &Functors::through_trajectory);
       !it.at_end();
       ++it, ++i) {
    body1_to_->Append(
        Instant(i * SIUnit<Time>()),
                DegreesOfFreedom<To>(
                    Position<To>(
                        Displacement<To>({3 * i * SIUnit<Length>(),
                                          1 * i * SIUnit<Length>(),
                                          2 * i * SIUnit<Length>()})),
                    Velocity<To>({16 * i * SIUnit<Speed>(),
                                  4 * i * SIUnit<Speed>(),
                                  8 * i * SIUnit<Speed>()})));

    DegreesOfFreedom<To> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom,
                Componentwise(
                    Eq(To::origin +
                        Displacement<To>({12 * i * SIUnit<Length>(),
                                          -21 * i * SIUnit<Length>(),
                                          29 * i * SIUnit<Length>()})),
                    Eq(Velocity<To>({36 * i * SIUnit<Speed>(),
                                      -88 * i * SIUnit<Speed>(),
                                      144 * i * SIUnit<Speed>()})))) << i;
  }
}

// Check that the computations we do match those done using Mathematica.
TEST_F(TransformsTest, SatelliteBarycentricRotating) {
  auto const transforms =
      Transforms<Functors, From, Through, To>::BarycentricRotating(
          body1_fn_, body2_fn_, &Functors::to_trajectory);
  Trajectory<Through> satellite_through(&satellite_);

  int i = 1;
  for (auto it = transforms->first(satellite_fn_, &Functors::from_trajectory);
       !it.at_end();
       ++it, ++i) {
    DegreesOfFreedom<Through> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom.position() - Position<Through>(),
                AlmostEquals(Displacement<Through>(
                    {-5.5 * sqrt(5.0) * i * SIUnit<Length>(),
                     62.0 * sqrt(5.0 / 21.0) * i * SIUnit<Length>(),
                     53.0 / sqrt(21.0) * i * SIUnit<Length>()}),
                    1, 8)) << i;
    EXPECT_THAT(degrees_of_freedom.velocity(),
                AlmostEquals(Velocity<Through>(
                    {(362.0 / sqrt(5.0)) * i * SIUnit<Speed>(),
                     (2776.0 / sqrt(105.0)) * i * SIUnit<Speed>(),
                     176.0 / sqrt(21.0) * i * SIUnit<Speed>()}),
                    1, 10)) << i;
    satellite_through.Append(Instant(i * SIUnit<Time>()), degrees_of_freedom);
  }
  satellite_fn_.through = &satellite_through;

  i = 1;
  for (auto it = transforms->second(satellite_fn_,
                                    &Functors::through_trajectory);
       !it.at_end();
       ++it, ++i) {
      body1_to_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<To>(
                      Position<To>(
                          Displacement<To>({3 * i * SIUnit<Length>(),
                                            1 * i * SIUnit<Length>(),
                                            2 * i * SIUnit<Length>()})),
                      Velocity<To>({16 * i * SIUnit<Speed>(),
                                    4 * i * SIUnit<Speed>(),
                                    8 * i * SIUnit<Speed>()})));
      body2_to_->Append(
          Instant(i * SIUnit<Time>()),
                  DegreesOfFreedom<To>(
                      Position<To>(
                          Displacement<To>({3 * i * SIUnit<Length>(),
                                           -1 * i * SIUnit<Length>(),
                                           -2 * i * SIUnit<Length>()})),
                      Velocity<To>({-16 * i * SIUnit<Speed>(),
                                    4 * i * SIUnit<Speed>(),
                                    8 * i * SIUnit<Speed>()})));

    DegreesOfFreedom<To> const degrees_of_freedom =
        it.degrees_of_freedom();
    EXPECT_THAT(degrees_of_freedom.position() - To::origin,
                AlmostEquals(Displacement<To>(
                    {(3.0 + 62.0 * sqrt(5.0 / 21.0)) * i * SIUnit<Length>(),
                     (-6.0 + 106.0 / sqrt(105.0)) * i * SIUnit<Length>(),
                     (-12.0 - 53.0 / sqrt(105.0)) * i * SIUnit<Length>()}),
                    3, 21))
        << i;
    EXPECT_THAT(degrees_of_freedom.velocity(),
                AlmostEquals(Velocity<To>(
                    {2776.0 / sqrt(105.0) * i * SIUnit<Speed>(),
                     (72.4 + 352.0 / sqrt(105.0)) * i * SIUnit<Speed>(),
                     (144.8 - 176.0 / sqrt(105.0)) * i * SIUnit<Speed>()}),
                    1, 8)) << i;
  }
}

// Check that the bodies remain on the invariant line and at the right distance
// from each other and from the barycentre, and that the barycentre is the
// centre of the coordinates.
TEST_F(TransformsTest, BodiesBarycentricRotating) {
  auto const transforms =
      Transforms<Functors, From, Through, To>::BarycentricRotating(
          body1_fn_, body2_fn_, &Functors::to_trajectory);
  Trajectory<Through> body1_through(&body1_);
  Trajectory<Through> body2_through(&body2_);

  int i = 1;
  for (auto it1 = transforms->first(body1_fn_, &Functors::from_trajectory),
            it2 = transforms->first(body2_fn_, &Functors::from_trajectory);
       !it1.at_end() && !it2.at_end();
       ++it1, ++it2, ++i) {
    Length const l = i * SIUnit<Length>();
    Speed const s = i * SIUnit<Speed>();
    DegreesOfFreedom<Through> const degrees_of_freedom1 =
        it1.degrees_of_freedom();
    DegreesOfFreedom<Through> const degrees_of_freedom2 =
        it2.degrees_of_freedom();

    EXPECT_THAT(degrees_of_freedom1.position() - Through::origin,
                Componentwise(AlmostEquals(1.5 * sqrt(5.0) * l, 0, 1),
                              VanishesBefore(l, 0, 4),
                              VanishesBefore(l, 0, 2)));
    EXPECT_THAT(degrees_of_freedom2.position() - Through::origin,
                Componentwise(AlmostEquals(-0.5 * sqrt(5.0) * l, 0, 2),
                              VanishesBefore(l, 0, 2),
                              VanishesBefore(l, 0, 1)));
    EXPECT_THAT(degrees_of_freedom1.velocity(),
                Componentwise(AlmostEquals(6.0 / sqrt(5.0) * s, 0, 7),
                              VanishesBefore(s, 0, 34),
                              VanishesBefore(s, 0, 2)));
    EXPECT_THAT(degrees_of_freedom2.velocity(),
                Componentwise(AlmostEquals(-2.0 / sqrt(5.0) * s, 0, 14),
                              VanishesBefore(s, 0, 16),
                              VanishesBefore(s, 0, 1)));

    DegreesOfFreedom<Through> const barycentre_degrees_of_freedom =
        Barycentre<Through, Mass>({degrees_of_freedom1, degrees_of_freedom2},
                                  {body1_.mass(), body2_.mass()});
    EXPECT_THAT(barycentre_degrees_of_freedom.position() - Through::origin,
                Componentwise(VanishesBefore(l, 0, 1),
                              VanishesBefore(l, 0, 2),
                              VanishesBefore(l, 0, 1)));
    EXPECT_THAT(barycentre_degrees_of_freedom.velocity(),
                Componentwise(VanishesBefore(s, 0, 14),
                              VanishesBefore(s, 0, 7),
                              VanishesBefore(s, 0, 1)));

    Length const length = (degrees_of_freedom1.position() -
                           degrees_of_freedom2.position()).Norm();
    EXPECT_THAT(length,
                AlmostEquals(2.0 * sqrt(5.0) * i * SIUnit<Length>(), 0, 2));
  }
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/vulkan/vulkan_window.h"

#include <memory>
#include <string>

#include "flutter/vulkan/vulkan_application.h"
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_native_surface.h"
#include "flutter/vulkan/vulkan_surface.h"
#include "flutter/vulkan/vulkan_swapchain.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/vk/GrVkInterface.h"

namespace vulkan {

VulkanWindow::VulkanWindow(fxl::RefPtr<VulkanProcTable> proc_table,
                           std::unique_ptr<VulkanNativeSurface> native_surface)
    : valid_(false), vk(std::move(proc_table)) {
  if (!vk || !vk->HasAcquiredMandatoryProcAddresses()) {
    FXL_DLOG(INFO) << "Proc table has not acquired mandatory proc addresses.";
    return;
  }

  if (native_surface == nullptr || !native_surface->IsValid()) {
    FXL_DLOG(INFO) << "Native surface is invalid.";
    return;
  }

  // Create the application instance.

  std::vector<std::string> extensions = {
      VK_KHR_SURFACE_EXTENSION_NAME,      // parent extension
      native_surface->GetExtensionName()  // child extension
  };

  application_ = std::make_unique<VulkanApplication>(*vk, "Flutter",
                                                     std::move(extensions));

  if (!application_->IsValid() || !vk->AreInstanceProcsSetup()) {
    // Make certain the application instance was created and it setup the
    // instance proc table entries.
    FXL_DLOG(INFO) << "Instance proc addresses have not been setup.";
    return;
  }

  // Create the device.

  logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();

  if (logical_device_ == nullptr || !logical_device_->IsValid() ||
      !vk->AreDeviceProcsSetup()) {
    // Make certain the device was created and it setup the device proc table
    // entries.
    FXL_DLOG(INFO) << "Device proc addresses have not been setup.";
    return;
  }

  // Create the logical surface from the native platform surface.

  surface_ = std::make_unique<VulkanSurface>(*vk, *application_,
                                             std::move(native_surface));

  if (!surface_->IsValid()) {
    FXL_DLOG(INFO) << "Vulkan surface is invalid.";
    return;
  }

  // Create the Skia GrContext.

  if (!CreateSkiaGrContext()) {
    FXL_DLOG(INFO) << "Could not create Skia context.";
    return;
  }

  // Create the swapchain.

  if (!RecreateSwapchain()) {
    FXL_DLOG(INFO) << "Could not setup the swapchain initially.";
    return;
  }

  valid_ = true;
}

VulkanWindow::~VulkanWindow() = default;

bool VulkanWindow::IsValid() const {
  return valid_;
}

GrContext* VulkanWindow::GetSkiaGrContext() {
  return skia_gr_context_.get();
}

bool VulkanWindow::CreateSkiaGrContext() {
  auto backend_context = CreateSkiaBackendContext();

  if (backend_context == nullptr) {
    return false;
  }

  sk_sp<GrContext> context = GrContext::MakeVulkan(backend_context);

  if (context == nullptr) {
    return false;
  }

  context->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);

  skia_vk_backend_context_ = backend_context;
  skia_gr_context_ = context;

  return true;
}

sk_sp<GrVkBackendContext> VulkanWindow::CreateSkiaBackendContext() {
  auto interface = vk->CreateSkiaInterface();

  if (interface == nullptr || !interface->validate(0)) {
    return nullptr;
  }

  uint32_t skia_features = 0;
  if (!logical_device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
    return nullptr;
  }

  // The Skia backend context takes ownership of the device and the instance.
  // Make sure we release our ownership now.
  logical_device_->ReleaseDeviceOwnership();
  application_->ReleaseInstanceOwnership();

  auto context = sk_make_sp<GrVkBackendContext>();
  context->fInstance = application_->GetInstance();
  context->fPhysicalDevice = logical_device_->GetPhysicalDeviceHandle();
  context->fDevice = logical_device_->GetHandle();
  context->fQueue = logical_device_->GetQueueHandle();
  context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex();
  context->fMinAPIVersion = application_->GetAPIVersion();
  context->fExtensions = kKHR_surface_GrVkExtensionFlag |
                         kKHR_swapchain_GrVkExtensionFlag |
                         surface_->GetNativeSurface().GetSkiaExtensionName();
  context->fFeatures = skia_features;
  context->fInterface.reset(interface.release());
  return context;
}

sk_sp<SkSurface> VulkanWindow::AcquireSurface() {
  if (!IsValid()) {
    FXL_DLOG(INFO) << "Surface is invalid.";
    return nullptr;
  }

  auto surface_size = surface_->GetSize();

  // This check is theoretically unnecessary as the swapchain should report that
  // the surface is out-of-date and perform swapchain recreation at the new
  // configuration. However, on Android, the swapchain never reports that it is
  // of date. Hence this extra check. Platforms that don't have this issue, or,
  // cant report this information (which is optional anyway), report a zero
  // size.
  if (surface_size != SkISize::Make(0, 0) &&
      surface_size != swapchain_->GetSize()) {
    FXL_DLOG(INFO) << "Swapchain and surface sizes are out of sync. Recreating "
                      "swapchain.";
    if (!RecreateSwapchain()) {
      FXL_DLOG(INFO) << "Could not recreate swapchain.";
      valid_ = false;
      return nullptr;
    }
  }

  while (true) {
    sk_sp<SkSurface> surface;
    auto acquire_result = VulkanSwapchain::AcquireStatus::ErrorSurfaceLost;

    std::tie(acquire_result, surface) = swapchain_->AcquireSurface();

    if (acquire_result == VulkanSwapchain::AcquireStatus::Success) {
      // Successfully acquired a surface from the swapchain. Nothing more to do.
      return surface;
    }

    if (acquire_result == VulkanSwapchain::AcquireStatus::ErrorSurfaceLost) {
      // Surface is lost. This is an unrecoverable error.
      FXL_DLOG(INFO) << "Swapchain reported surface was lost.";
      return nullptr;
    }

    if (acquire_result ==
        VulkanSwapchain::AcquireStatus::ErrorSurfaceOutOfDate) {
      // Surface out of date. Recreate the swapchain at the new configuration.
      if (RecreateSwapchain()) {
        // Swapchain was recreated, try surface acquisition again.
        continue;
      } else {
        // Could not recreate the swapchain at the new configuration.
        FXL_DLOG(INFO) << "Swapchain reported surface was out of date but "
                          "could not recreate the swapchain at the new "
                          "configuration.";
        valid_ = false;
        return nullptr;
      }
    }

    break;
  }

  FXL_DCHECK(false) << "Unhandled VulkanSwapchain::AcquireResult";
  return nullptr;
}

bool VulkanWindow::SwapBuffers() {
  if (!IsValid()) {
    FXL_DLOG(INFO) << "Window was invalid.";
    return false;
  }

  return swapchain_->Submit();
}

bool VulkanWindow::RecreateSwapchain() {
  // This way, we always lose our reference to the old swapchain. Even if we
  // cannot create a new one to replace it.
  auto old_swapchain = std::move(swapchain_);

  if (!vk->IsValid()) {
    return false;
  }

  if (logical_device_ == nullptr || !logical_device_->IsValid()) {
    return false;
  }

  if (surface_ == nullptr || !surface_->IsValid()) {
    return false;
  }

  if (skia_gr_context_ == nullptr) {
    return false;
  }

  auto swapchain = std::make_unique<VulkanSwapchain>(
      *vk, *logical_device_, *surface_, skia_gr_context_.get(),
      std::move(old_swapchain), logical_device_->GetGraphicsQueueIndex());

  if (!swapchain->IsValid()) {
    return false;
  }

  swapchain_ = std::move(swapchain);
  return true;
}

}  // namespace vulkan
<commit_msg>Update GrVkBackendContext to no longer own the VkInstance and VkDevice (#5457)<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/vulkan/vulkan_window.h"

#include <memory>
#include <string>

#include "flutter/vulkan/vulkan_application.h"
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_native_surface.h"
#include "flutter/vulkan/vulkan_surface.h"
#include "flutter/vulkan/vulkan_swapchain.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/vk/GrVkInterface.h"

namespace vulkan {

VulkanWindow::VulkanWindow(fxl::RefPtr<VulkanProcTable> proc_table,
                           std::unique_ptr<VulkanNativeSurface> native_surface)
    : valid_(false), vk(std::move(proc_table)) {
  if (!vk || !vk->HasAcquiredMandatoryProcAddresses()) {
    FXL_DLOG(INFO) << "Proc table has not acquired mandatory proc addresses.";
    return;
  }

  if (native_surface == nullptr || !native_surface->IsValid()) {
    FXL_DLOG(INFO) << "Native surface is invalid.";
    return;
  }

  // Create the application instance.

  std::vector<std::string> extensions = {
      VK_KHR_SURFACE_EXTENSION_NAME,      // parent extension
      native_surface->GetExtensionName()  // child extension
  };

  application_ = std::make_unique<VulkanApplication>(*vk, "Flutter",
                                                     std::move(extensions));

  if (!application_->IsValid() || !vk->AreInstanceProcsSetup()) {
    // Make certain the application instance was created and it setup the
    // instance proc table entries.
    FXL_DLOG(INFO) << "Instance proc addresses have not been setup.";
    return;
  }

  // Create the device.

  logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();

  if (logical_device_ == nullptr || !logical_device_->IsValid() ||
      !vk->AreDeviceProcsSetup()) {
    // Make certain the device was created and it setup the device proc table
    // entries.
    FXL_DLOG(INFO) << "Device proc addresses have not been setup.";
    return;
  }

  // Create the logical surface from the native platform surface.

  surface_ = std::make_unique<VulkanSurface>(*vk, *application_,
                                             std::move(native_surface));

  if (!surface_->IsValid()) {
    FXL_DLOG(INFO) << "Vulkan surface is invalid.";
    return;
  }

  // Create the Skia GrContext.

  if (!CreateSkiaGrContext()) {
    FXL_DLOG(INFO) << "Could not create Skia context.";
    return;
  }

  // Create the swapchain.

  if (!RecreateSwapchain()) {
    FXL_DLOG(INFO) << "Could not setup the swapchain initially.";
    return;
  }

  valid_ = true;
}

VulkanWindow::~VulkanWindow() = default;

bool VulkanWindow::IsValid() const {
  return valid_;
}

GrContext* VulkanWindow::GetSkiaGrContext() {
  return skia_gr_context_.get();
}

bool VulkanWindow::CreateSkiaGrContext() {
  auto backend_context = CreateSkiaBackendContext();

  if (backend_context == nullptr) {
    return false;
  }

  sk_sp<GrContext> context = GrContext::MakeVulkan(backend_context);

  if (context == nullptr) {
    return false;
  }

  context->setResourceCacheLimits(kGrCacheMaxCount, kGrCacheMaxByteSize);

  skia_vk_backend_context_ = backend_context;
  skia_gr_context_ = context;

  return true;
}

sk_sp<GrVkBackendContext> VulkanWindow::CreateSkiaBackendContext() {
  auto interface = vk->CreateSkiaInterface();

  if (interface == nullptr || !interface->validate(0)) {
    return nullptr;
  }

  uint32_t skia_features = 0;
  if (!logical_device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
    return nullptr;
  }

  auto context = sk_make_sp<GrVkBackendContext>();
  context->fInstance = application_->GetInstance();
  context->fPhysicalDevice = logical_device_->GetPhysicalDeviceHandle();
  context->fDevice = logical_device_->GetHandle();
  context->fQueue = logical_device_->GetQueueHandle();
  context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex();
  context->fMinAPIVersion = application_->GetAPIVersion();
  context->fExtensions = kKHR_surface_GrVkExtensionFlag |
                         kKHR_swapchain_GrVkExtensionFlag |
                         surface_->GetNativeSurface().GetSkiaExtensionName();
  context->fFeatures = skia_features;
  context->fInterface.reset(interface.release());
  context->fOwnsInstanceAndDevice = false;
  return context;
}

sk_sp<SkSurface> VulkanWindow::AcquireSurface() {
  if (!IsValid()) {
    FXL_DLOG(INFO) << "Surface is invalid.";
    return nullptr;
  }

  auto surface_size = surface_->GetSize();

  // This check is theoretically unnecessary as the swapchain should report that
  // the surface is out-of-date and perform swapchain recreation at the new
  // configuration. However, on Android, the swapchain never reports that it is
  // of date. Hence this extra check. Platforms that don't have this issue, or,
  // cant report this information (which is optional anyway), report a zero
  // size.
  if (surface_size != SkISize::Make(0, 0) &&
      surface_size != swapchain_->GetSize()) {
    FXL_DLOG(INFO) << "Swapchain and surface sizes are out of sync. Recreating "
                      "swapchain.";
    if (!RecreateSwapchain()) {
      FXL_DLOG(INFO) << "Could not recreate swapchain.";
      valid_ = false;
      return nullptr;
    }
  }

  while (true) {
    sk_sp<SkSurface> surface;
    auto acquire_result = VulkanSwapchain::AcquireStatus::ErrorSurfaceLost;

    std::tie(acquire_result, surface) = swapchain_->AcquireSurface();

    if (acquire_result == VulkanSwapchain::AcquireStatus::Success) {
      // Successfully acquired a surface from the swapchain. Nothing more to do.
      return surface;
    }

    if (acquire_result == VulkanSwapchain::AcquireStatus::ErrorSurfaceLost) {
      // Surface is lost. This is an unrecoverable error.
      FXL_DLOG(INFO) << "Swapchain reported surface was lost.";
      return nullptr;
    }

    if (acquire_result ==
        VulkanSwapchain::AcquireStatus::ErrorSurfaceOutOfDate) {
      // Surface out of date. Recreate the swapchain at the new configuration.
      if (RecreateSwapchain()) {
        // Swapchain was recreated, try surface acquisition again.
        continue;
      } else {
        // Could not recreate the swapchain at the new configuration.
        FXL_DLOG(INFO) << "Swapchain reported surface was out of date but "
                          "could not recreate the swapchain at the new "
                          "configuration.";
        valid_ = false;
        return nullptr;
      }
    }

    break;
  }

  FXL_DCHECK(false) << "Unhandled VulkanSwapchain::AcquireResult";
  return nullptr;
}

bool VulkanWindow::SwapBuffers() {
  if (!IsValid()) {
    FXL_DLOG(INFO) << "Window was invalid.";
    return false;
  }

  return swapchain_->Submit();
}

bool VulkanWindow::RecreateSwapchain() {
  // This way, we always lose our reference to the old swapchain. Even if we
  // cannot create a new one to replace it.
  auto old_swapchain = std::move(swapchain_);

  if (!vk->IsValid()) {
    return false;
  }

  if (logical_device_ == nullptr || !logical_device_->IsValid()) {
    return false;
  }

  if (surface_ == nullptr || !surface_->IsValid()) {
    return false;
  }

  if (skia_gr_context_ == nullptr) {
    return false;
  }

  auto swapchain = std::make_unique<VulkanSwapchain>(
      *vk, *logical_device_, *surface_, skia_gr_context_.get(),
      std::move(old_swapchain), logical_device_->GetGraphicsQueueIndex());

  if (!swapchain->IsValid()) {
    return false;
  }

  swapchain_ = std::move(swapchain);
  return true;
}

}  // namespace vulkan
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <memory>

#include "variant.hpp"
#include "SemanticalException.hpp"
#include "Context.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Variable.hpp"
#include "Warnings.hpp"
#include "Options.hpp"
#include "VisitorUtils.hpp"
#include "Utils.hpp"

#include "ast/WarningsEngine.hpp"
#include "ast/SourceFile.hpp"
#include "ast/ASTVisitor.hpp"
#include "ast/Position.hpp"
#include "ast/GetTypeVisitor.hpp"
#include "ast/TypeTransformer.hpp"

using namespace eddic;

namespace {

typedef std::unordered_map<std::shared_ptr<Variable>, ast::Position> Positions;

struct Collector : public boost::static_visitor<> {
    public:
        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_STRUCT()
        AUTO_RECURSE_DESTRUCTOR()

        void operator()(ast::FunctionDeclaration& function){
            for(auto& param : function.Content->parameters){
                positions[function.Content->context->getVariable(param.parameterName)] = function.Content->position;
            }

            visit_each(*this, function.Content->instructions);
        }

        void operator()(ast::Constructor& function){
            for(auto& param : function.Content->parameters){
                positions[function.Content->context->getVariable(param.parameterName)] = function.Content->position;
            }

            visit_each(*this, function.Content->instructions);
        }

        void operator()(ast::GlobalVariableDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->variableName)] = declaration.Content->position;
        }

        void operator()(ast::GlobalArrayDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->arrayName)] = declaration.Content->position;
        }

        void operator()(ast::ArrayDeclaration& declaration){
            //If this is null, it means that this an array inside a structure
            if(declaration.Content->context){
                positions[declaration.Content->context->getVariable(declaration.Content->arrayName)] = declaration.Content->position;
            }
        }

        void operator()(ast::VariableDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->variableName)] = declaration.Content->position;
        }

        AUTO_IGNORE_OTHERS()

        const ast::Position& getPosition(std::shared_ptr<Variable> var){
            assert(positions.find(var) != positions.end());

            return positions[var];
        }

    private:
        Positions positions;
};

struct Inspector : public boost::static_visitor<> {
    private:
        Collector& collector;
        ast::SourceFile& program;

        std::shared_ptr<GlobalContext> context;
        std::shared_ptr<Configuration> configuration;

        bool standard = false;

    public:
        Inspector(Collector& collector, ast::SourceFile& program, std::shared_ptr<GlobalContext> context, std::shared_ptr<Configuration> configuration) :
                collector(collector), program(program), context(context), configuration(configuration) {}

        /* The following constructions can contains instructions with warnings  */
        AUTO_RECURSE_GLOBAL_DECLARATION()
        AUTO_RECURSE_FUNCTION_CALLS()
        AUTO_RECURSE_BUILTIN_OPERATORS()
        AUTO_RECURSE_RETURN_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()
        AUTO_RECURSE_TERNARY()
        AUTO_RECURSE_SWITCH()
        AUTO_RECURSE_COMPOSED_VALUES()

        void check(std::shared_ptr<Context> context){
            if(configuration->option_defined("warning-unused")){
                auto iter = context->begin();
                auto end = context->end();

                for(; iter != end; iter++){
                    auto var = iter->second;

                    if(var->references() == 0){
                        if(var->position().isStack()){
                            warn(collector.getPosition(var), "unused variable '" + var->name() + "'");
                        } else if(var->position().isGlobal()){
                            warn(collector.getPosition(var), "unused global variable '" + var->name() + "'");
                        } else if(var->position().isParameter()){
                            warn(collector.getPosition(var), "unused parameter '" + var->name() + "'");
                        }
                    }
                }
            }
        }

        void operator()(ast::SourceFile& program){
            check(program.Content->context);

            visit_each(*this, program.Content->blocks);
        }

        void check_header(const std::string& file, const ast::Position& position){
            for(auto& block : program.Content->blocks){
                if(auto* ptr = boost::get<ast::FunctionDeclaration>(&block)){
                    if(ptr->Content->header == file){
                        int references = context->referenceCount(ptr->Content->mangledName);

                        if(references > 0){
                            return;
                        }
                    }
                } else if(auto* ptr = boost::get<ast::Struct>(&block)){
                    if(ptr->Content->header == file){
                        auto struct_ = context->get_struct(ptr->Content->struct_type->mangle());

                        if(struct_->get_references() > 0){
                            return;
                        }
                    }
                }
            }

            warn(position, "Useless import: " + file);
        }

        void operator()(ast::StandardImport& import){
            if(configuration->option_defined("warning-includes")){
                check_header(import.header, import.position);
            }
        }

        void operator()(ast::Import& import){
            if(configuration->option_defined("warning-includes")){
                check_header(import.file, import.position);
            }
        }

        void operator()(ast::Struct& declaration){
            standard = declaration.Content->standard;
            visit_each(*this, declaration.Content->blocks);
            standard = false;

            if(!declaration.Content->standard){
                if(configuration->option_defined("warning-unused")){
                    auto struct_ = context->get_struct(declaration.Content->struct_type->mangle());

                    if(struct_->get_references() == 0){
                        warn(declaration.Content->position, "unused structure '" + declaration.Content->name + "'");
                    } else {
                        for(auto& member : struct_->members){
                            if(member->get_references() == 0){
                                warn(declaration.Content->position, "unused member '" + declaration.Content->name + ".'" + member->name);
                            }
                        }
                    }
                }
            }
        }

        void operator()(ast::FunctionDeclaration& declaration){
            check(declaration.Content->context);

            if(!declaration.Content->standard && !standard){
                if(configuration->option_defined("warning-unused")){
                    int references = context->referenceCount(declaration.Content->mangledName);

                    if(references == 0){
                        if(declaration.Content->functionName != "main"){
                            warn(declaration.Content->position, "unused function '" + declaration.Content->functionName + "'");
                        }
                    }
                }

                check_each(declaration.Content->instructions);
            }
        }

        void operator()(ast::Cast& cast){
            if(configuration->option_defined("warning-cast")){
                auto src_type = visit(ast::GetTypeVisitor(), cast.Content->value);
                auto dest_type = visit(ast::TypeTransformer(context), cast.Content->type);

                if(src_type == dest_type){
                    warn(cast.Content->position, "useless cast");
                }
            }
        }

        void operator()(ast::If& if_){
            visit(*this, if_.Content->condition);
            check_each(if_.Content->instructions);
            visit_each_non_variant(*this, if_.Content->elseIfs);
            visit_optional_non_variant(*this, if_.Content->else_);
        }

        void operator()(ast::ElseIf& elseIf){
            visit(*this, elseIf.condition);
            check_each(elseIf.instructions);
        }

        void operator()(ast::For& for_){
            visit_optional(*this, for_.Content->start);
            visit_optional(*this, for_.Content->condition);
            visit_optional(*this, for_.Content->repeat);
            check_each(for_.Content->instructions);
        }

        void operator()(ast::While& while_){
            visit(*this, while_.Content->condition);
            check_each(while_.Content->instructions);
        }

        void operator()(ast::DoWhile& while_){
            visit(*this, while_.Content->condition);
            check_each(while_.Content->instructions);
        }

        void operator()(ast::Else& else_){
            check_each(else_.instructions);
        }

        void operator()(ast::Foreach& foreach_){
            check_each(foreach_.Content->instructions);
        }

        void operator()(ast::ForeachIn& foreach_){
            check_each(foreach_.Content->instructions);
        }

        void operator()(ast::SwitchCase& switch_case){
            visit(*this, switch_case.value);
            check_each(switch_case.instructions);
        }

        void operator()(ast::DefaultCase& default_case){
            check_each(default_case.instructions);
        }

        void check_each(std::vector<ast::Instruction>& instructions){
            for(auto& instruction : instructions){
                if(auto* ptr = boost::get<ast::Expression>(&instruction)){
                    auto& value = *ptr;
                    bool effects = false;

                    for(auto& op : value.Content->operations){
                        if(op.get<0>() == ast::Operator::INC || op.get<0>() == ast::Operator::DEC || op.get<0>() == ast::Operator::CALL){
                            effects = true;
                            break;
                        }
                    }

                    if(!effects){
                        warn(value.Content->position, "Statement without any effect");
                    }
                }

                visit(*this, instruction);
            }
        }

        //No warnings for other types
        AUTO_IGNORE_OTHERS()
};

} //end of anonymous namespace

void ast::WarningsPass::apply_program(ast::SourceFile& program, bool){
    Collector collector;
    visit_non_variant(collector, program);

    Inspector inspector(collector, program, program.Content->context, configuration);
    visit_non_variant(inspector, program);
}

bool ast::WarningsPass::is_simple(){
    return true;
}
<commit_msg>The unused functions will be emitted later on<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <memory>

#include "variant.hpp"
#include "SemanticalException.hpp"
#include "Context.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Variable.hpp"
#include "Warnings.hpp"
#include "Options.hpp"
#include "VisitorUtils.hpp"
#include "Utils.hpp"

#include "ast/WarningsEngine.hpp"
#include "ast/SourceFile.hpp"
#include "ast/ASTVisitor.hpp"
#include "ast/Position.hpp"
#include "ast/GetTypeVisitor.hpp"
#include "ast/TypeTransformer.hpp"

using namespace eddic;

namespace {

typedef std::unordered_map<std::shared_ptr<Variable>, ast::Position> Positions;

struct Collector : public boost::static_visitor<> {
    public:
        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_STRUCT()
        AUTO_RECURSE_DESTRUCTOR()

        void operator()(ast::FunctionDeclaration& function){
            for(auto& param : function.Content->parameters){
                positions[function.Content->context->getVariable(param.parameterName)] = function.Content->position;
            }

            visit_each(*this, function.Content->instructions);
        }

        void operator()(ast::Constructor& function){
            for(auto& param : function.Content->parameters){
                positions[function.Content->context->getVariable(param.parameterName)] = function.Content->position;
            }

            visit_each(*this, function.Content->instructions);
        }

        void operator()(ast::GlobalVariableDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->variableName)] = declaration.Content->position;
        }

        void operator()(ast::GlobalArrayDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->arrayName)] = declaration.Content->position;
        }

        void operator()(ast::ArrayDeclaration& declaration){
            //If this is null, it means that this an array inside a structure
            if(declaration.Content->context){
                positions[declaration.Content->context->getVariable(declaration.Content->arrayName)] = declaration.Content->position;
            }
        }

        void operator()(ast::VariableDeclaration& declaration){
            positions[declaration.Content->context->getVariable(declaration.Content->variableName)] = declaration.Content->position;
        }

        AUTO_IGNORE_OTHERS()

        const ast::Position& getPosition(std::shared_ptr<Variable> var){
            assert(positions.find(var) != positions.end());

            return positions[var];
        }

    private:
        Positions positions;
};

struct Inspector : public boost::static_visitor<> {
    private:
        Collector& collector;
        ast::SourceFile& program;

        std::shared_ptr<GlobalContext> context;
        std::shared_ptr<Configuration> configuration;

        bool standard = false;

    public:
        Inspector(Collector& collector, ast::SourceFile& program, std::shared_ptr<GlobalContext> context, std::shared_ptr<Configuration> configuration) :
                collector(collector), program(program), context(context), configuration(configuration) {}

        /* The following constructions can contains instructions with warnings  */
        AUTO_RECURSE_GLOBAL_DECLARATION()
        AUTO_RECURSE_FUNCTION_CALLS()
        AUTO_RECURSE_BUILTIN_OPERATORS()
        AUTO_RECURSE_RETURN_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()
        AUTO_RECURSE_TERNARY()
        AUTO_RECURSE_SWITCH()
        AUTO_RECURSE_COMPOSED_VALUES()

        void check(std::shared_ptr<Context> context){
            if(configuration->option_defined("warning-unused")){
                auto iter = context->begin();
                auto end = context->end();

                for(; iter != end; iter++){
                    auto var = iter->second;

                    if(var->references() == 0){
                        if(var->position().isStack()){
                            warn(collector.getPosition(var), "unused variable '" + var->name() + "'");
                        } else if(var->position().isGlobal()){
                            warn(collector.getPosition(var), "unused global variable '" + var->name() + "'");
                        } else if(var->position().isParameter()){
                            warn(collector.getPosition(var), "unused parameter '" + var->name() + "'");
                        }
                    }
                }
            }
        }

        void operator()(ast::SourceFile& program){
            check(program.Content->context);

            visit_each(*this, program.Content->blocks);
        }

        void check_header(const std::string& file, const ast::Position& position){
            for(auto& block : program.Content->blocks){
                if(auto* ptr = boost::get<ast::Struct>(&block)){
                    if(ptr->Content->header == file){
                        auto struct_ = context->get_struct(ptr->Content->struct_type->mangle());

                        if(struct_->get_references() > 0){
                            return;
                        }
                    }
                }
            }

            warn(position, "Useless import: " + file);
        }

        void operator()(ast::StandardImport& import){
            if(configuration->option_defined("warning-includes")){
                check_header(import.header, import.position);
            }
        }

        void operator()(ast::Import& import){
            if(configuration->option_defined("warning-includes")){
                check_header(import.file, import.position);
            }
        }

        void operator()(ast::Struct& declaration){
            standard = declaration.Content->standard;
            visit_each(*this, declaration.Content->blocks);
            standard = false;

            if(!declaration.Content->standard){
                if(configuration->option_defined("warning-unused")){
                    auto struct_ = context->get_struct(declaration.Content->struct_type->mangle());

                    if(struct_->get_references() == 0){
                        warn(declaration.Content->position, "unused structure '" + declaration.Content->name + "'");
                    } else {
                        for(auto& member : struct_->members){
                            if(member->get_references() == 0){
                                warn(declaration.Content->position, "unused member '" + declaration.Content->name + ".'" + member->name);
                            }
                        }
                    }
                }
            }
        }

        void operator()(ast::FunctionDeclaration& declaration){
            check(declaration.Content->context);

            if(!declaration.Content->standard && !standard){
                check_each(declaration.Content->instructions);
            }
        }

        void operator()(ast::Cast& cast){
            if(configuration->option_defined("warning-cast")){
                auto src_type = visit(ast::GetTypeVisitor(), cast.Content->value);
                auto dest_type = visit(ast::TypeTransformer(context), cast.Content->type);

                if(src_type == dest_type){
                    warn(cast.Content->position, "useless cast");
                }
            }
        }

        void operator()(ast::If& if_){
            visit(*this, if_.Content->condition);
            check_each(if_.Content->instructions);
            visit_each_non_variant(*this, if_.Content->elseIfs);
            visit_optional_non_variant(*this, if_.Content->else_);
        }

        void operator()(ast::ElseIf& elseIf){
            visit(*this, elseIf.condition);
            check_each(elseIf.instructions);
        }

        void operator()(ast::For& for_){
            visit_optional(*this, for_.Content->start);
            visit_optional(*this, for_.Content->condition);
            visit_optional(*this, for_.Content->repeat);
            check_each(for_.Content->instructions);
        }

        void operator()(ast::While& while_){
            visit(*this, while_.Content->condition);
            check_each(while_.Content->instructions);
        }

        void operator()(ast::DoWhile& while_){
            visit(*this, while_.Content->condition);
            check_each(while_.Content->instructions);
        }

        void operator()(ast::Else& else_){
            check_each(else_.instructions);
        }

        void operator()(ast::Foreach& foreach_){
            check_each(foreach_.Content->instructions);
        }

        void operator()(ast::ForeachIn& foreach_){
            check_each(foreach_.Content->instructions);
        }

        void operator()(ast::SwitchCase& switch_case){
            visit(*this, switch_case.value);
            check_each(switch_case.instructions);
        }

        void operator()(ast::DefaultCase& default_case){
            check_each(default_case.instructions);
        }

        void check_each(std::vector<ast::Instruction>& instructions){
            for(auto& instruction : instructions){
                if(auto* ptr = boost::get<ast::Expression>(&instruction)){
                    auto& value = *ptr;
                    bool effects = false;

                    for(auto& op : value.Content->operations){
                        if(op.get<0>() == ast::Operator::INC || op.get<0>() == ast::Operator::DEC || op.get<0>() == ast::Operator::CALL){
                            effects = true;
                            break;
                        }
                    }

                    if(!effects){
                        warn(value.Content->position, "Statement without any effect");
                    }
                }

                visit(*this, instruction);
            }
        }

        //No warnings for other types
        AUTO_IGNORE_OTHERS()
};

} //end of anonymous namespace

void ast::WarningsPass::apply_program(ast::SourceFile& program, bool){
    Collector collector;
    visit_non_variant(collector, program);

    Inspector inspector(collector, program, program.Content->context, configuration);
    visit_non_variant(inspector, program);
}

bool ast::WarningsPass::is_simple(){
    return true;
}
<|endoftext|>


<commit_before>/* The MIT License:

Copyright (c) 2014 Ivan Gagis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

// Home page: http://aumiks.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#include <ting/types.hpp>

namespace audout{

class AudioFormat {
public:
	struct Frame{
		enum Type{
			MONO = 1,
			STEREO = 2,
			QUADRO = 4,
			FIVE_DOT_ONE = 6,
			SEVEN_DOT_ONE = 8
		} type;

		unsigned NumChannels()throw(){
			return unsigned(this->type);
		}

		Frame(Type type) : type(type) {}
	} frame;

	struct SamplingRate{
		enum Type{
			HZ_11025 = 11025,
			HZ_22050 = 22050,
			HZ_44100 = 44100,
			HZ_48000 = 48000
		} type;

		inline ting::u32 Frequency()throw(){
			return ting::u32(this->type);
		}

		SamplingRate(Type type) : type(type) {}
	} samplingRate;

	AudioFormat(Frame::Type frameType, SamplingRate::Type samplingRateType) :
			frame(frameType),
			samplingRate(samplingRateType)
	{}
private:

};

}//~namespace
<commit_msg>Frame traits<commit_after>/* The MIT License:

Copyright (c) 2014 Ivan Gagis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

// Home page: http://aumiks.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#include <ting/types.hpp>

namespace audout{

class AudioFormat {
public:
	struct Frame{
		enum Type{
			MONO = 1,
			STEREO = 2,
			QUADRO = 4,
			FIVE_DOT_ONE = 6,
			SEVEN_DOT_ONE = 8
		} type;

		unsigned NumChannels()throw(){
			return unsigned(this->type);
		}

		Frame(Type type) : type(type) {}

		template <Type type> struct Traits;
	} frame;

	struct SamplingRate{
		enum Type{
			HZ_11025 = 11025,
			HZ_22050 = 22050,
			HZ_44100 = 44100,
			HZ_48000 = 48000
		} type;

		inline ting::u32 Frequency()throw(){
			return ting::u32(this->type);
		}

		SamplingRate(Type type) : type(type) {}
	} samplingRate;

	AudioFormat(Frame::Type frameType, SamplingRate::Type samplingRateType) :
			frame(frameType),
			samplingRate(samplingRateType)
	{}
private:

};

template <> struct AudioFormat::Frame::Traits<AudioFormat::Frame::MONO>{
	enum NumChannels{
		NUM_CHANNELS = 1
	};
};

template <> struct AudioFormat::Frame::Traits<AudioFormat::Frame::STEREO>{
	enum NumChannels{
		NUM_CHANNELS = 2
	};
};

template <> struct AudioFormat::Frame::Traits<AudioFormat::Frame::QUADRO>{
	enum NumChannels{
		NUM_CHANNELS = 4
	};
};

template <> struct AudioFormat::Frame::Traits<AudioFormat::Frame::FIVE_DOT_ONE>{
	enum NumChannels{
		NUM_CHANNELS = 6
	};
};

template <> struct AudioFormat::Frame::Traits<AudioFormat::Frame::SEVEN_DOT_ONE>{
	enum NumChannels{
		NUM_CHANNELS = 8
	};
};

}//~namespace
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::FAPI2_RC_SUCCESS;
}
<commit_msg>CORE/CACHE: core/cache/l2_stopclocks Level 2<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CORE_STOPCLOCKS_CONSTANTS
{
    CORE_CLK_SYNC_TIMEOUT_IN_MS       = 1,
    CORE_CLK_STOP_TIMEOUT_IN_MS       = 1
};

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    uint32_t                                       l_timeout;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enable;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,       l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
    FAPI_TRY(putScom(l_quad,
                     (l_attr_chip_unit_pos < 2) ?
                     EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                     (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                      BIT64(8 + (l_attr_chip_unit_pos % 2)))));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                p9hcd::CLK_REGION_ALL_BUT_PLL |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                CORE_CLK_STOP_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_CORECLKSTOP_TIMEOUT()
                .set_CORE_TARGET(i_target)
                .set_CORECPLTSTAT(l_data64),
                "Core Clock Stop Timeout");

    FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
    FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                fapi2::PMPROC_CORECLKSTOP_FAILED()
                .set_CORE_TARGET(i_target)
                .set_CORECLKSTAT(l_data64),
                "Core Clock Stop Failed");
    FAPI_DBG("Core clocks stopped now");

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                CORE_CLK_STOP_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    /// @todo RTC158181 add DD1 attribute control
    FAPI_DBG("DD1 only: reset sdis_n(flushing LCBES condition workaround");
    FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, (BIT64(0) | BIT64(13))));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief LRDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card B0 settings
///
// TODO RTC:160116 Fill in valid RCD data for LRDIMM
rcw_settings lrdimm_rc_b0( 0x00, // RC00
                           0x00, // RC01 (C might be the right answer)
                           0x1F, // RC06_7
                           0x00, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6C
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace lrdimm
{

// TODO - RTC:160121 Catch all for adding raw card data for DIMMs
const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    {raw_card_rev::B0, lrdimm_rc_b0},
};

}// lrdimm
}// mss
<commit_msg>L3 work for mss xmls<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief LRDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card B0 settings
///
// TODO RTC:160116 Fill in valid RCD data for LRDIMM
rcw_settings lrdimm_rc_b0( 0x00, // RC00
                           0x00, // RC01 (C might be the right answer)
                           0x1F, // RC06_7
                           0x00, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6C
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace lrdimm
{

// TODO - RTC:160121 Catch all for adding raw card data for DIMMs
const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    {raw_card_rev::B0, lrdimm_rc_b0},
};

}// lrdimm
}// mss
<|endoftext|>