<commit_before>#include "XSCommon/XSCommon.h"
#include "XSCommon/XSFile.h"
#include "XSCommon/XSConsole.h"
#include "XSCommon/XSCvar.h"
#include "XSClient/XSClientGame.h"
#include "XSClient/XSGameObject.h"
#include "XSClient/XSTerrain.h"
#include "XSClient/XSPerlin.h"
#include "XSRenderer/XSRenderer.h"
#include "XSRenderer/XSShaderProgram.h"
#include "XSRenderer/XSMaterial.h"
#include "XSRenderer/XSTexture.h"
#include "XSRenderer/XSModel.h"
#include "XSRenderer/XSMesh.h"
#include "XSRenderer/XSVertexAttributes.h"
#include "XSRenderer/XSImagePNG.h"

namespace XS {

	namespace ClientGame {

		Cvar *cg_terrainPersistence = nullptr;
		Cvar *cg_terrainFrequency = nullptr;
		Cvar *cg_terrainAmplitude = nullptr;
		Cvar *cg_terrainOctaves = nullptr;
		Cvar *cg_terrainDimensions = nullptr;

		Terrain::Terrain( const char *path ) {

			const size_t dimensions = cg_terrainDimensions->GetUInt32();

			Perlin perlin(
				cg_terrainPersistence->GetReal64(), // persistence
				cg_terrainFrequency->GetReal64(), // frequency
				cg_terrainAmplitude->GetReal64(), // amplitude
				cg_terrainOctaves->GetInt32(), // octaves
				rand() // seed
			);

			real32_t *heightmap = new real32_t[dimensions * dimensions];
			std::memset( heightmap, 0, dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				for ( int col = 0; col < dimensions; col++ ) {
					real64_t p = perlin.GetHeight( row, col ); // [-1.0, 1.0]
					real64_t r = (p + 1.0) / 2.0; // [0.0, 1.0]
					heightmap[(row * dimensions) + col] = r;
				}
			}

			gameObj = new GameObject();
			gameObj->renderObject = Renderer::Model::Register( nullptr );
			Renderer::Mesh *mesh = new Renderer::Mesh();
			const real32_t scale = 64.0f;

			// positions
			mesh->vertices.reserve( dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				const float fRow = static_cast<real32_t>( row );
				for ( int col = 0; col < dimensions; col++ ) {
					const float fCol = static_cast<real32_t>( col );
					const real32_t *sample = &heightmap[(row * dimensions) + col];
					vector3 pos;
					pos.x = fRow - (dimensions / 2.0f);
					pos.y = (*sample * scale) - (scale / 1.5f);
					pos.z = fCol - (dimensions / 2.0f);
					mesh->vertices.push_back( pos );

					vector2 uv;
					uv.x = fCol / dimensions;
					uv.y = fRow / dimensions;
					mesh->UVs.push_back( uv );
				}
			}

			delete[] heightmap;

			// normals
			mesh->normals.reserve( dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				for ( int col = 0; col < dimensions; col++ ) {
					//TODO: handle edge cases more gracefully
					vector3 normal;
					if ( row != dimensions - 1 && col != dimensions - 1 ) {
						vector3 a = mesh->vertices[row * dimensions + col];
						vector3 u = vector3( mesh->vertices[(row + 1) * dimensions + col] );
						vector3 v = vector3( mesh->vertices[(row + 1) * dimensions + (col + 1)] );
						normal = vector3::cross( u - a, v - a ) * -1.0f;
					}
					normal.normaliseFast();
					mesh->normals.push_back( normal );
				}
			}

			// indices
			mesh->indices.reserve( (dimensions - 1) * (dimensions - 1) * 6 );
			for ( int row = 0; row < dimensions - 1; row++ ) {
				for ( int col = 0; col < dimensions - 1; col++ ) {
					const int32_t start = (row * dimensions) + col;
					mesh->indices.push_back( start );
					mesh->indices.push_back( start + 1 );
					mesh->indices.push_back( start + dimensions );

					mesh->indices.push_back( start + 1 );
					mesh->indices.push_back( start + 1 + dimensions );
					mesh->indices.push_back( start + dimensions );
				}
			}

			mesh->Upload();

			dynamic_cast<Renderer::Model *>( gameObj->renderObject )->meshes.push_back( mesh );
			AddObject( gameObj );

			// create shader program
			static const Renderer::VertexAttribute attributes[] = {
				{ 0, "in_Position" },
				{ 1, "in_Normal" },
				{ 2, "in_TexCoord" },
			};
			program = new Renderer::ShaderProgram( "terrain", "terrain", attributes, ARRAY_LEN( attributes ) );

			// create material
			material = new Renderer::Material();

			// create textures
			uint32_t outWidth = 0u, outHeight = 0u;

			// grass texture
			uint8_t *grassData = Renderer::LoadPNG( "textures/grass.png", &outWidth, &outHeight );
			grassTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, grassData );
			delete grassData;
			Renderer::Material::SamplerBinding samplerBindingGrass;
			samplerBindingGrass.unit = 0;
			samplerBindingGrass.uniform = "u_grassTexture";
			samplerBindingGrass.texture = grassTexture;
			material->samplerBindings.push_back( samplerBindingGrass );

			// dirt texture
			uint8_t *dirtData = Renderer::LoadPNG( "textures/dirt.png", &outWidth, &outHeight );
			dirtTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, dirtData );
			delete dirtData;
			Renderer::Material::SamplerBinding samplerBindingDirt;
			samplerBindingDirt.unit = 1;
			samplerBindingDirt.uniform = "u_dirtTexture";
			samplerBindingDirt.texture = dirtTexture;
			material->samplerBindings.push_back( samplerBindingDirt );

			// snow texture
			uint8_t *snowData = Renderer::LoadPNG( "textures/snow.png", &outWidth, &outHeight );
			snowTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, snowData );
			delete snowData;
			Renderer::Material::SamplerBinding samplerBindingSnow;
			samplerBindingSnow.unit = 2;
			samplerBindingSnow.uniform = "u_snowTexture";
			samplerBindingSnow.texture = snowTexture;
			material->samplerBindings.push_back( samplerBindingSnow );

			real32_t averagePoint = 0.0f;
			real32_t highestPoint = 0.0f;
			for ( const auto &v : mesh->vertices ) {
				averagePoint += v.y;
				if ( v.y > highestPoint ) {
					highestPoint = v.y;
				}
			}
			averagePoint /= static_cast<real32_t>( mesh->vertices.size() );
			program->SetUniform1( "u_lowPoint", averagePoint );
			program->SetUniform1( "u_highPoint", highestPoint );

			material->shaderProgram = program;
			//terrainMaterial->flags |= Renderer::MF_WIREFRAME;

			mesh->material = material;
		}

		Terrain::~Terrain() {
			RemoveObject( gameObj );
			delete gameObj;
			delete program;
			delete dirtTexture;
			delete grassTexture;
			delete snowTexture;
		}

	} // namespace ClientGame

} // namespace XS
<commit_msg>Small terrain generation changes. Hotfix for perlin noise generator breaking on seeds > 0x7FFF<commit_after>#include "XSCommon/XSCommon.h"
#include "XSCommon/XSFile.h"
#include "XSCommon/XSConsole.h"
#include "XSCommon/XSCvar.h"
#include "XSClient/XSClientGame.h"
#include "XSClient/XSGameObject.h"
#include "XSClient/XSTerrain.h"
#include "XSClient/XSPerlin.h"
#include "XSRenderer/XSRenderer.h"
#include "XSRenderer/XSShaderProgram.h"
#include "XSRenderer/XSMaterial.h"
#include "XSRenderer/XSTexture.h"
#include "XSRenderer/XSModel.h"
#include "XSRenderer/XSMesh.h"
#include "XSRenderer/XSVertexAttributes.h"
#include "XSRenderer/XSImagePNG.h"

namespace XS {

	namespace ClientGame {

		Cvar *cg_terrainPersistence = nullptr;
		Cvar *cg_terrainFrequency = nullptr;
		Cvar *cg_terrainAmplitude = nullptr;
		Cvar *cg_terrainOctaves = nullptr;
		Cvar *cg_terrainDimensions = nullptr;

		Terrain::Terrain( const char *path ) {

			const size_t dimensions = cg_terrainDimensions->GetUInt32();

			//FIXME: seeds > 32k break the generator
			Perlin perlin(
				cg_terrainPersistence->GetReal64(), // persistence
				cg_terrainFrequency->GetReal64(), // frequency
				cg_terrainAmplitude->GetReal64(), // amplitude
				cg_terrainOctaves->GetInt32(), // octaves
				rand() & 0x7FFFu // seed
			);

			real32_t *heightmap = new real32_t[dimensions * dimensions];
			std::memset( heightmap, 0, dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				for ( int col = 0; col < dimensions; col++ ) {
					real64_t p = perlin.GetHeight( row, col ); // [-1.0, 1.0]
					real64_t r = (p + 1.0) / 2.0; // [0.0, 1.0]
					heightmap[(row * dimensions) + col] = r;
				}
			}

			gameObj = new GameObject();
			gameObj->renderObject = Renderer::Model::Register( nullptr );
			Renderer::Mesh *mesh = new Renderer::Mesh();
			const real32_t scale = 64.0f;

			// positions
			mesh->vertices.reserve( dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				const float fRow = static_cast<real32_t>( row );
				for ( int col = 0; col < dimensions; col++ ) {
					const float fCol = static_cast<real32_t>( col );
					const real32_t *sample = &heightmap[(row * dimensions) + col];
					vector3 pos(
						fRow - (dimensions / 2.0f),
						(*sample * scale) - (scale / 1.5f),
						fCol - (dimensions / 2.0f)
					);
					mesh->vertices.push_back( pos );

					vector2 uv(
						fCol / dimensions,
						fRow / dimensions
					);
					mesh->UVs.push_back( uv );
				}
			}

			delete[] heightmap;

			// normals
			mesh->normals.reserve( dimensions * dimensions );
			for ( int row = 0; row < dimensions; row++ ) {
				for ( int col = 0; col < dimensions; col++ ) {
					//TODO: handle edge cases more gracefully
					vector3 normal;
					if ( row != dimensions - 1 && col != dimensions - 1 ) {
						vector3 a = mesh->vertices[row * dimensions + col];
						vector3 u = vector3( mesh->vertices[(row + 1) * dimensions + col] );
						vector3 v = vector3( mesh->vertices[(row + 1) * dimensions + (col + 1)] );
						normal = vector3::cross( u - a, v - a ) * -1.0f;
					}
					normal.normaliseFast();
					mesh->normals.push_back( normal );
				}
			}

			// indices
			mesh->indices.reserve( (dimensions - 1) * (dimensions - 1) * 6 );
			for ( int row = 0; row < dimensions - 1; row++ ) {
				for ( int col = 0; col < dimensions - 1; col++ ) {
					const int32_t start = (row * dimensions) + col;
					mesh->indices.push_back( start );
					mesh->indices.push_back( start + 1 );
					mesh->indices.push_back( start + dimensions );

					mesh->indices.push_back( start + 1 );
					mesh->indices.push_back( start + 1 + dimensions );
					mesh->indices.push_back( start + dimensions );
				}
			}

			mesh->Upload();

			dynamic_cast<Renderer::Model *>( gameObj->renderObject )->meshes.push_back( mesh );
			AddObject( gameObj );

			// create shader program
			static const Renderer::VertexAttribute attributes[] = {
				{ 0, "in_Position" },
				{ 1, "in_Normal" },
				{ 2, "in_TexCoord" },
			};
			program = new Renderer::ShaderProgram( "terrain", "terrain", attributes, ARRAY_LEN( attributes ) );

			// create material
			material = new Renderer::Material();

			// create textures
			uint32_t outWidth = 0u, outHeight = 0u;

			// grass texture
			uint8_t *grassData = Renderer::LoadPNG( "textures/grass.png", &outWidth, &outHeight );
			grassTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, grassData );
			delete grassData;
			Renderer::Material::SamplerBinding samplerBindingGrass;
			samplerBindingGrass.unit = 0;
			samplerBindingGrass.uniform = "u_grassTexture";
			samplerBindingGrass.texture = grassTexture;
			material->samplerBindings.push_back( samplerBindingGrass );

			// dirt texture
			uint8_t *dirtData = Renderer::LoadPNG( "textures/dirt.png", &outWidth, &outHeight );
			dirtTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, dirtData );
			delete dirtData;
			Renderer::Material::SamplerBinding samplerBindingDirt;
			samplerBindingDirt.unit = 1;
			samplerBindingDirt.uniform = "u_dirtTexture";
			samplerBindingDirt.texture = dirtTexture;
			material->samplerBindings.push_back( samplerBindingDirt );

			// snow texture
			uint8_t *snowData = Renderer::LoadPNG( "textures/snow.png", &outWidth, &outHeight );
			snowTexture = new Renderer::Texture( outWidth, outHeight, Renderer::InternalFormat::RGBA8, snowData );
			delete snowData;
			Renderer::Material::SamplerBinding samplerBindingSnow;
			samplerBindingSnow.unit = 2;
			samplerBindingSnow.uniform = "u_snowTexture";
			samplerBindingSnow.texture = snowTexture;
			material->samplerBindings.push_back( samplerBindingSnow );

			real32_t averagePoint = 0.0f;
			real32_t highestPoint = 0.0f;
			for ( const auto &v : mesh->vertices ) {
				averagePoint += v.y;
				if ( v.y > highestPoint ) {
					highestPoint = v.y;
				}
			}
			averagePoint /= static_cast<real32_t>( mesh->vertices.size() );
			program->SetUniform1( "u_lowPoint", averagePoint );
			program->SetUniform1( "u_highPoint", highestPoint );

			material->shaderProgram = program;
			//terrainMaterial->flags |= Renderer::MF_WIREFRAME;

			mesh->material = material;
		}

		Terrain::~Terrain() {
			RemoveObject( gameObj );
			delete gameObj;
			delete program;
			delete dirtTexture;
			delete grassTexture;
			delete snowTexture;
		}

	} // namespace ClientGame

} // namespace XS
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abc/testing/test_case.hxx>
#include <abc/trace.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::test::exception_polymorphism

namespace abc {

namespace test {

class exception_polymorphism :
   public testing::test_case {

   typedef environment_error    derived1_error;
   typedef io_error             derived2_error;
   typedef file_not_found_error derived3_error;

public:

   /** See testing::test_case::title().
   */
   virtual istr title() {
      return istr(SL("abc::exception - polymorphism"));
   }

   /** See testing::test_case::run().
   */
   virtual void run() {
      ABC_TRACE_FN((this));

      ABC_TESTING_ASSERT_THROWS(exception, throw_exception());
      ABC_TESTING_ASSERT_THROWS(generic_error, throw_generic_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived1_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived2_error());
      ABC_TESTING_ASSERT_THROWS(derived2_error, throw_derived2_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived3_error(2351));
//    ABC_TESTING_ASSERT_THROWS(derived2_error, throw_derived3_error(2351));
      ABC_TESTING_ASSERT_THROWS(derived3_error, throw_derived3_error(2351));
   }

   void throw_exception() {
      ABC_TRACE_FN((this));

      ABC_THROW(exception, ());
   }

   void throw_generic_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(generic_error, ());
   }

   void throw_derived1_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(derived1_error, ());
   }

   void throw_derived2_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(derived2_error, ());
   }

   void throw_derived3_error(int i) {
      ABC_TRACE_FN((this, i));

      ABC_THROW(derived3_error, ());
   }
};

} //namespace test

} //namespace abc

ABC_TESTING_REGISTER_TEST_CASE(abc::test::exception_polymorphism)

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::test::exception_from_os_hard_error

namespace abc {

namespace test {

class exception_from_os_hard_error :
   public testing::test_case {
public:

   /** See testing::test_case::title().
   */
   virtual istr title() {
      return istr(SL("abc::exception - conversion of hard OS errors into C++ exceptions"));
   }

   /** See testing::test_case::run().
   */
   virtual void run() {
      ABC_TRACE_FN((this));

      {
         int * p(nullptr);
         ABC_TESTING_ASSERT_THROWS(null_pointer_error, *p = 1);

         // Under POSIX, this also counts as second test for SIGSEGV, checking that the handler is
         // still in place after its first activation above.
         ABC_TESTING_ASSERT_THROWS(memory_address_error, *++p = 1);
      }

      // Enable alignment checking if the architecture supports it.
#ifdef ABC_ALIGN_CHECK
#ifdef __GNUC__
   #if defined(__i386__)
      __asm__(
         "pushf\n"
         "orl $0x00040000,(%esp)\n"
         "popf"
      );
      #define ABC_ALIGN_CHECK
   #elif defined(__x86_64__)
      __asm__(
         "pushf\n"
         "orl $0x0000000000040000,(%rsp)\n"
         "popf"
      );
      #define ABC_ALIGN_CHECK
   #endif
#endif

      {
         // Create an int (with another one following it) and a pointer to it.
         int i[2];
         void * p(&i[0]);
         // Misalign the pointer, partly entering the second int.
         p = static_cast<int8_t *>(p) + 1;
         ABC_TESTING_ASSERT_THROWS(memory_access_error, *static_cast<int *>(p) = 1);
      }

      // Disable alignment checking back.
#ifdef __GNUC__
   #if defined(__i386__)
      __asm__(
         "pushf\n"
         "andl $0xfffbffff,(%esp)\n"
         "popf"
      );
   #elif defined(__x86_64__)
      __asm__(
         "pushf\n"
         "andl $0xfffffffffffbffff,(%rsp)\n"
         "popf"
      );
   #endif
#endif
#endif //ifdef ABC_ALIGN_CHECK

      {
         // Non-obvious division by zero that can’t be detected at compile time: sEmpty always has
         // a NUL terminator at its end, so use that as a zero divider.
         istr sEmpty;
         int iZero(sEmpty[0]), iOne(1);
         ABC_TESTING_ASSERT_THROWS(division_by_zero_error, iOne /= iZero);
         // The call to istr::format() makes use of the quotient, so it shouldn’t be optimized away.
         istr(SL("{}")).format(iOne);
      }
   }
};

} //namespace test

} //namespace abc

ABC_TESTING_REGISTER_TEST_CASE(abc::test::exception_from_os_hard_error)

////////////////////////////////////////////////////////////////////////////////////////////////////

<commit_msg>Use testing-specific exception hierarchy for polymorphism tests<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abc/testing/test_case.hxx>
#include <abc/trace.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::test::exception_polymorphism

namespace abc {

namespace test {

class exception_polymorphism :
   public testing::test_case {
protected:

   /** First-level abc::generic_error subclass.
   */
   class derived1_error :
      public virtual generic_error {
   public:

      /** Constructor.
      */
      derived1_error() :
         generic_error() {
         m_pszWhat = "abc::test::exception_polymorphism::derived1_error";
      }
   };

   /** Second-level abc::generic_error subclass.
   */
   class derived2_error :
      public virtual derived1_error {
   public:

      /** Constructor.
      */
      derived2_error() :
         derived1_error() {
         m_pszWhat = "abc::test::exception_polymorphism::derived2_error";
      }
   };

   /** Diamond-inheritance abc::generic_error subclass.
   */
   class derived3_error :
      public virtual derived1_error,
      public virtual derived2_error {
   public:

      /** Constructor.
      */
      derived3_error() :
         derived1_error(),
         derived2_error() {
         m_pszWhat = "abc::test::exception_polymorphism::derived3_error";
      }
   };

public:

   /** See testing::test_case::title().
   */
   virtual istr title() {
      return istr(SL("abc::exception - polymorphism"));
   }

   /** See testing::test_case::run().
   */
   virtual void run() {
      ABC_TRACE_FN((this));

      ABC_TESTING_ASSERT_THROWS(exception, throw_exception());
      ABC_TESTING_ASSERT_THROWS(generic_error, throw_generic_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived1_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived2_error());
      ABC_TESTING_ASSERT_THROWS(derived2_error, throw_derived2_error());
      ABC_TESTING_ASSERT_THROWS(derived1_error, throw_derived3_error(2351));
      ABC_TESTING_ASSERT_THROWS(derived2_error, throw_derived3_error(3512));
      ABC_TESTING_ASSERT_THROWS(derived3_error, throw_derived3_error(5123));
   }

   void throw_exception() {
      ABC_TRACE_FN((this));

      ABC_THROW(exception, ());
   }

   void throw_generic_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(generic_error, ());
   }

   void throw_derived1_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(derived1_error, ());
   }

   void throw_derived2_error() {
      ABC_TRACE_FN((this));

      ABC_THROW(derived2_error, ());
   }

   void throw_derived3_error(int i) {
      ABC_TRACE_FN((this, i));

      ABC_THROW(derived3_error, ());
   }
};

} //namespace test

} //namespace abc

ABC_TESTING_REGISTER_TEST_CASE(abc::test::exception_polymorphism)

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::test::exception_from_os_hard_error

namespace abc {

namespace test {

class exception_from_os_hard_error :
   public testing::test_case {
public:

   /** See testing::test_case::title().
   */
   virtual istr title() {
      return istr(SL("abc::exception - conversion of hard OS errors into C++ exceptions"));
   }

   /** See testing::test_case::run().
   */
   virtual void run() {
      ABC_TRACE_FN((this));

      {
         int * p(nullptr);
         ABC_TESTING_ASSERT_THROWS(null_pointer_error, *p = 1);

         // Under POSIX, this also counts as second test for SIGSEGV, checking that the handler is
         // still in place after its first activation above.
         ABC_TESTING_ASSERT_THROWS(memory_address_error, *++p = 1);
      }

      // Enable alignment checking if the architecture supports it.
#ifdef ABC_ALIGN_CHECK
#ifdef __GNUC__
   #if defined(__i386__)
      __asm__(
         "pushf\n"
         "orl $0x00040000,(%esp)\n"
         "popf"
      );
      #define ABC_ALIGN_CHECK
   #elif defined(__x86_64__)
      __asm__(
         "pushf\n"
         "orl $0x0000000000040000,(%rsp)\n"
         "popf"
      );
      #define ABC_ALIGN_CHECK
   #endif
#endif

      {
         // Create an int (with another one following it) and a pointer to it.
         int i[2];
         void * p(&i[0]);
         // Misalign the pointer, partly entering the second int.
         p = static_cast<int8_t *>(p) + 1;
         ABC_TESTING_ASSERT_THROWS(memory_access_error, *static_cast<int *>(p) = 1);
      }

      // Disable alignment checking back.
#ifdef __GNUC__
   #if defined(__i386__)
      __asm__(
         "pushf\n"
         "andl $0xfffbffff,(%esp)\n"
         "popf"
      );
   #elif defined(__x86_64__)
      __asm__(
         "pushf\n"
         "andl $0xfffffffffffbffff,(%rsp)\n"
         "popf"
      );
   #endif
#endif
#endif //ifdef ABC_ALIGN_CHECK

      {
         // Non-obvious division by zero that can’t be detected at compile time: sEmpty always has
         // a NUL terminator at its end, so use that as a zero divider.
         istr sEmpty;
         int iZero(sEmpty[0]), iOne(1);
         ABC_TESTING_ASSERT_THROWS(division_by_zero_error, iOne /= iZero);
         // The call to istr::format() makes use of the quotient, so it shouldn’t be optimized away.
         istr(SL("{}")).format(iOne);
      }
   }
};

} //namespace test

} //namespace abc

ABC_TESTING_REGISTER_TEST_CASE(abc::test::exception_from_os_hard_error)

////////////////////////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/

#include "pluginmanager.h"

#include "transport/connectionlistenerfactory.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>

#include <QtCore/QDebug>

namespace MoleQueue
{

namespace
{
// Compiler initializes this static pointer to 0.
static PluginManager *pluginManagerInstance;
}

PluginManager::PluginManager(QObject *p) : QObject(p)
{
  m_relativeToApp = "/../lib/molequeue/plugins";
#ifdef __APPLE__
  QString buildRelative("/../../../..");
  qDebug() << QCoreApplication::applicationDirPath() + buildRelative
              + "/CMakeCache.txt";
  if (QFileInfo(QCoreApplication::applicationDirPath() + buildRelative
                + "/CMakeCache.txt").exists()) {
    qDebug() << QCoreApplication::applicationDirPath()
                + buildRelative
                + "/lib/molequeue/plugins";
    m_pluginDirs.append(QDir(QCoreApplication::applicationDirPath()
                             + buildRelative
                             + "/lib/molequeue/plugins").absolutePath());
    qDebug() << QDir(QCoreApplication::applicationDirPath()
                     + buildRelative
                     + "/lib/molequeue/plugins").absolutePath();
  }
#endif
  QDir dir(QCoreApplication::applicationDirPath() + m_relativeToApp);
  m_pluginDirs.append(dir.absolutePath());
}

PluginManager::~PluginManager()
{
}

PluginManager * PluginManager::instance()
{
  static QMutex mutex;
  if (!pluginManagerInstance) {
    mutex.lock();
    if (!pluginManagerInstance)
      pluginManagerInstance = new PluginManager(QCoreApplication::instance());
    mutex.unlock();
  }
  return pluginManagerInstance;
}

void PluginManager::load()
{
  foreach(const QString &dir, m_pluginDirs)
    load(dir);
}

void PluginManager::load(const QString &path)
{
  QDir dir(path);
  qDebug() << dir.entryList(QDir::Files);
  foreach(const QString &pluginPath, dir.entryList(QDir::Files)) {
    QPluginLoader pluginLoader(dir.absolutePath() + QDir::separator() + pluginPath);

    if (pluginLoader.isLoaded()) {
      qDebug() << "Plugin already loaded: " << pluginLoader.fileName();
      continue;
    }

    QObject *pluginInstance = pluginLoader.instance();

    // Check if the plugin loaded correctly. Keep debug output for now, should
    // go away once we have verified this (or added to a logger).
    if (!pluginInstance) {
      qDebug() << "Failed to load" << pluginPath << "error"
               << pluginLoader.errorString();
    }
    else {
      qDebug() << "Loaded" << pluginPath << "->";
      pluginInstance->dumpObjectInfo();
    }

    // Now attempt to cast to known factory types, and make it available.
    ConnectionListenerFactory *connectionListenerFactory =
      qobject_cast<ConnectionListenerFactory *>(pluginInstance);
    if (connectionListenerFactory)
      m_connectionListenerFactories.append(connectionListenerFactory);
  }
}

QList<ConnectionListenerFactory *> PluginManager::connectionListenerFactories() const
{
  return m_connectionListenerFactories;
}

} // End MoleQueue namespace
<commit_msg>Prevent same connection factory being added twice<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/

#include "pluginmanager.h"

#include "transport/connectionlistenerfactory.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>

#include <QtCore/QDebug>

namespace MoleQueue
{

namespace
{
// Compiler initializes this static pointer to 0.
static PluginManager *pluginManagerInstance;
}

PluginManager::PluginManager(QObject *p) : QObject(p)
{
  m_relativeToApp = "/../lib/molequeue/plugins";
#ifdef __APPLE__
  QString buildRelative("/../../../..");
  qDebug() << QCoreApplication::applicationDirPath() + buildRelative
              + "/CMakeCache.txt";
  if (QFileInfo(QCoreApplication::applicationDirPath() + buildRelative
                + "/CMakeCache.txt").exists()) {
    qDebug() << QCoreApplication::applicationDirPath()
                + buildRelative
                + "/lib/molequeue/plugins";
    m_pluginDirs.append(QDir(QCoreApplication::applicationDirPath()
                             + buildRelative
                             + "/lib/molequeue/plugins").absolutePath());
    qDebug() << QDir(QCoreApplication::applicationDirPath()
                     + buildRelative
                     + "/lib/molequeue/plugins").absolutePath();
  }
#endif
  QDir dir(QCoreApplication::applicationDirPath() + m_relativeToApp);
  m_pluginDirs.append(dir.absolutePath());
}

PluginManager::~PluginManager()
{
}

PluginManager * PluginManager::instance()
{
  static QMutex mutex;
  if (!pluginManagerInstance) {
    mutex.lock();
    if (!pluginManagerInstance)
      pluginManagerInstance = new PluginManager(QCoreApplication::instance());
    mutex.unlock();
  }
  return pluginManagerInstance;
}

void PluginManager::load()
{
  foreach(const QString &dir, m_pluginDirs)
    load(dir);
}

void PluginManager::load(const QString &path)
{
  QDir dir(path);
  qDebug() << dir.entryList(QDir::Files);
  foreach(const QString &pluginPath, dir.entryList(QDir::Files)) {
    QPluginLoader pluginLoader(dir.absolutePath() + QDir::separator() + pluginPath);

    if (pluginLoader.isLoaded()) {
      qDebug() << "Plugin already loaded: " << pluginLoader.fileName();
      continue;
    }

    QObject *pluginInstance = pluginLoader.instance();

    // Check if the plugin loaded correctly. Keep debug output for now, should
    // go away once we have verified this (or added to a logger).
    if (!pluginInstance) {
      qDebug() << "Failed to load" << pluginPath << "error"
               << pluginLoader.errorString();
    }
    else {
      qDebug() << "Loaded" << pluginPath << "->";
      pluginInstance->dumpObjectInfo();
    }

    // Now attempt to cast to known factory types, and make it available.
    ConnectionListenerFactory *connectionListenerFactory =
      qobject_cast<ConnectionListenerFactory *>(pluginInstance);
    if (connectionListenerFactory &&
        !m_connectionListenerFactories.contains(connectionListenerFactory))
      m_connectionListenerFactories.append(connectionListenerFactory);
  }
}

QList<ConnectionListenerFactory *> PluginManager::connectionListenerFactories() const
{
  return m_connectionListenerFactories;
}

} // End MoleQueue namespace
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <assert.h>
#include <sstream>

static void normalize_sig(RTLIL::Module *module, RTLIL::SigSpec &sig)
{
	for (auto &conn : module->connections)
		sig.replace(conn.first, conn.second);
}

static bool find_sig_before_dff(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
{
	normalize_sig(module, sig);
	sig.expand();

	for (size_t i = 0; i < sig.chunks.size(); i++)
	{
		RTLIL::SigChunk &chunk = sig.chunks[i];

		if (chunk.wire == NULL)
			continue;

		for (auto &cell_it : module->cells)
		{
			RTLIL::Cell *cell = cell_it.second;

			if (cell->type != "$dff")
				continue;

			if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
				if (cell->connections["\\CLK"] != clk)
					continue;
				if (cell->parameters["\\CLK_POLARITY"].as_bool() != clk_polarity)
					continue;
			}

			RTLIL::SigSpec q_norm = cell->connections[after ? "\\D" : "\\Q"];
			normalize_sig(module, q_norm);

			RTLIL::SigSpec d = q_norm.extract(chunk, &cell->connections[after ? "\\Q" : "\\D"]);
			if (d.width != 1)
				continue;

			assert(d.chunks.size() == 1);
			chunk = d.chunks[0];
			clk = cell->connections["\\CLK"];
			clk_polarity = cell->parameters["\\CLK_POLARITY"].as_bool();
			goto replaced_this_bit;
		}

		return false;
	replaced_this_bit:;
	}

	sig.optimize();
	return true;
}

static void handle_wr_cell(RTLIL::Module *module, RTLIL::Cell *cell)
{
	log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());

	RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
	bool clk_polarity = 0;

	RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"];
	if (!find_sig_before_dff(module, sig_addr, clk, clk_polarity)) {
		log("no (compatible) $dff for address input found.\n");
		return;
	}

	RTLIL::SigSpec sig_data = cell->connections["\\DATA"];
	if (!find_sig_before_dff(module, sig_data, clk, clk_polarity)) {
		log("no (compatible) $dff for data input found.\n");
		return;
	}

	RTLIL::SigSpec sig_en = cell->connections["\\EN"];
	if (!find_sig_before_dff(module, sig_en, clk, clk_polarity)) {
		log("no (compatible) $dff for enable input found.\n");
		return;
	}

	if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
		cell->connections["\\CLK"] = clk;
		cell->connections["\\ADDR"] = sig_addr;
		cell->connections["\\DATA"] = sig_data;
		cell->connections["\\EN"] = sig_en;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		log("merged $dff to cell.\n");
	}
}

static void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig)
{
	normalize_sig(module, sig);
	sig.sort_and_unify();

	std::stringstream sstr;
	sstr << "$memory_dff_disconnected$" << (RTLIL::autoidx++);

	RTLIL::Wire *wire = new RTLIL::Wire;
	wire->name = sstr.str();
	wire->width = sig.width;
	module->wires[wire->name] = wire;

	RTLIL::SigSpec newsig(wire);

	for (auto &cell_it : module->cells) {
		RTLIL::Cell *cell = cell_it.second;
		if (cell->type == "$dff")
			cell->connections["\\Q"].replace(sig, newsig);
	}
}

static void handle_rd_cell(RTLIL::Module *module, RTLIL::Cell *cell)
{
	log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());

	bool clk_polarity = 0;

	RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx);
	RTLIL::SigSpec sig_data = cell->connections["\\DATA"];
	if (find_sig_before_dff(module, sig_data, clk_data, clk_polarity, true) &&
			clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
	{
		disconnect_dff(module, sig_data);
		cell->connections["\\CLK"] = clk_data;
		cell->connections["\\DATA"] = sig_data;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
		log("merged data $dff to cell.\n");
		return;
	}

	RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx);
	RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"];
	if (find_sig_before_dff(module, sig_addr, clk_addr, clk_polarity) &&
			clk_addr != RTLIL::SigSpec(RTLIL::State::Sx))
	{
		cell->connections["\\CLK"] = clk_addr;
		cell->connections["\\ADDR"] = sig_addr;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		cell->parameters["\\TRANSPARENT"] = RTLIL::Const(1);
		log("merged address $dff to cell.\n");
		return;
	}

	log("no (compatible) $dff found.\n");
}

static void handle_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_wr_only)
{
	for (auto &cell_it : module->cells) {
		if (!design->selected(module, cell_it.second))
			continue;
		if (cell_it.second->type == "$memwr" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool())
				handle_wr_cell(module, cell_it.second);
		if (!flag_wr_only && cell_it.second->type == "$memrd" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool())
				handle_rd_cell(module, cell_it.second);
	}
}

struct MemoryDffPass : public Pass {
	MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    memory_dff [options] [selection]\n");
		log("\n");
		log("This pass detects DFFs at memory ports and merges them into the memory port.\n");
		log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
		log("interface and yields a synchronous memory port.\n");
		log("\n");
		log("    -wr_only\n");
		log("        do not merge registers on read ports\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		bool flag_wr_only = false;

		log_header("Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-wr_only") {
				flag_wr_only = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second))
				handle_module(design, mod_it.second, flag_wr_only);
	}
} MemoryDffPass;

<commit_msg>Fixed log messages in memory_dff<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <assert.h>
#include <sstream>

static void normalize_sig(RTLIL::Module *module, RTLIL::SigSpec &sig)
{
	for (auto &conn : module->connections)
		sig.replace(conn.first, conn.second);
}

static bool find_sig_before_dff(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
{
	normalize_sig(module, sig);
	sig.expand();

	for (size_t i = 0; i < sig.chunks.size(); i++)
	{
		RTLIL::SigChunk &chunk = sig.chunks[i];

		if (chunk.wire == NULL)
			continue;

		for (auto &cell_it : module->cells)
		{
			RTLIL::Cell *cell = cell_it.second;

			if (cell->type != "$dff")
				continue;

			if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
				if (cell->connections["\\CLK"] != clk)
					continue;
				if (cell->parameters["\\CLK_POLARITY"].as_bool() != clk_polarity)
					continue;
			}

			RTLIL::SigSpec q_norm = cell->connections[after ? "\\D" : "\\Q"];
			normalize_sig(module, q_norm);

			RTLIL::SigSpec d = q_norm.extract(chunk, &cell->connections[after ? "\\Q" : "\\D"]);
			if (d.width != 1)
				continue;

			assert(d.chunks.size() == 1);
			chunk = d.chunks[0];
			clk = cell->connections["\\CLK"];
			clk_polarity = cell->parameters["\\CLK_POLARITY"].as_bool();
			goto replaced_this_bit;
		}

		return false;
	replaced_this_bit:;
	}

	sig.optimize();
	return true;
}

static void handle_wr_cell(RTLIL::Module *module, RTLIL::Cell *cell)
{
	log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());

	RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
	bool clk_polarity = 0;

	RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"];
	if (!find_sig_before_dff(module, sig_addr, clk, clk_polarity)) {
		log("no (compatible) $dff for address input found.\n");
		return;
	}

	RTLIL::SigSpec sig_data = cell->connections["\\DATA"];
	if (!find_sig_before_dff(module, sig_data, clk, clk_polarity)) {
		log("no (compatible) $dff for data input found.\n");
		return;
	}

	RTLIL::SigSpec sig_en = cell->connections["\\EN"];
	if (!find_sig_before_dff(module, sig_en, clk, clk_polarity)) {
		log("no (compatible) $dff for enable input found.\n");
		return;
	}

	if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
		cell->connections["\\CLK"] = clk;
		cell->connections["\\ADDR"] = sig_addr;
		cell->connections["\\DATA"] = sig_data;
		cell->connections["\\EN"] = sig_en;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		log("merged $dff to cell.\n");
	}

	log("no (compatible) $dff found.\n");
}

static void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig)
{
	normalize_sig(module, sig);
	sig.sort_and_unify();

	std::stringstream sstr;
	sstr << "$memory_dff_disconnected$" << (RTLIL::autoidx++);

	RTLIL::Wire *wire = new RTLIL::Wire;
	wire->name = sstr.str();
	wire->width = sig.width;
	module->wires[wire->name] = wire;

	RTLIL::SigSpec newsig(wire);

	for (auto &cell_it : module->cells) {
		RTLIL::Cell *cell = cell_it.second;
		if (cell->type == "$dff")
			cell->connections["\\Q"].replace(sig, newsig);
	}
}

static void handle_rd_cell(RTLIL::Module *module, RTLIL::Cell *cell)
{
	log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());

	bool clk_polarity = 0;

	RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx);
	RTLIL::SigSpec sig_data = cell->connections["\\DATA"];
	if (find_sig_before_dff(module, sig_data, clk_data, clk_polarity, true) &&
			clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
	{
		disconnect_dff(module, sig_data);
		cell->connections["\\CLK"] = clk_data;
		cell->connections["\\DATA"] = sig_data;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
		log("merged data $dff to cell.\n");
		return;
	}

	RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx);
	RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"];
	if (find_sig_before_dff(module, sig_addr, clk_addr, clk_polarity) &&
			clk_addr != RTLIL::SigSpec(RTLIL::State::Sx))
	{
		cell->connections["\\CLK"] = clk_addr;
		cell->connections["\\ADDR"] = sig_addr;
		cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
		cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
		cell->parameters["\\TRANSPARENT"] = RTLIL::Const(1);
		log("merged address $dff to cell.\n");
		return;
	}

	log("no (compatible) $dff found.\n");
}

static void handle_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_wr_only)
{
	for (auto &cell_it : module->cells) {
		if (!design->selected(module, cell_it.second))
			continue;
		if (cell_it.second->type == "$memwr" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool())
				handle_wr_cell(module, cell_it.second);
		if (!flag_wr_only && cell_it.second->type == "$memrd" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool())
				handle_rd_cell(module, cell_it.second);
	}
}

struct MemoryDffPass : public Pass {
	MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    memory_dff [options] [selection]\n");
		log("\n");
		log("This pass detects DFFs at memory ports and merges them into the memory port.\n");
		log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
		log("interface and yields a synchronous memory port.\n");
		log("\n");
		log("    -wr_only\n");
		log("        do not merge registers on read ports\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		bool flag_wr_only = false;

		log_header("Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-wr_only") {
				flag_wr_only = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second))
				handle_module(design, mod_it.second, flag_wr_only);
	}
} MemoryDffPass;

<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <gtest/gtest.h>
#include <qi/signal.hpp>
#include <qi/future.hpp>
#include <qi/signalspy.hpp>
#include <qi/anyobject.hpp>
#include <qi/application.hpp>
#include <qi/type/objecttypebuilder.hpp>
#include <qi/type/dynamicobjectbuilder.hpp>

qiLogCategory("test");

class Foo
{
public:
  void func(int)               { }
  void func1(qi::Atomic<int>* r, int)
  {
    // hackish sleep so that asynchronous trigger detection is safer
    qi::os::msleep(1); ++*r;
  }
  void func2(qi::Atomic<int>* r, int, int) { ++*r; }
};
void foo(qi::Atomic<int>* r, int, int)     { ++*r; }
void foo2(qi::Atomic<int>* r, char, char)  { ++*r; }
void foo3(qi::Atomic<int>* r, Foo *)       { ++*r; }
void foolast(int, qi::Promise<void> prom, qi::Atomic<int>* r) { prom.setValue(0); ++*r; }

TEST(TestSignal, TestCompilation)
{
  qi::Atomic<int>        res{0};
  qi::Signal<int> s;
  Foo*                   f = (Foo*)1;
  qi::Promise<void>      prom;

  //do not count
  s.connect(qi::AnyFunction::from(&Foo::func, f));
  s.connect(boost::bind<void>(&Foo::func, f, _1));

  s.connect(boost::bind(&foo, &res, 12, _1));
  s.connect(boost::bind(&foo2, &res, 12, _1));
  s.connect(boost::bind<void>(&Foo::func1, f, &res, _1));
  s.connect(boost::bind<void>(&Foo::func2, f, &res, 5, _1));
  s.connect(boost::bind(&foo3, &res, f));
  s.connect(boost::bind(&foolast, _1, prom, &res));

  s(42);

  while (res.load() != 6)
    qi::os::msleep(10);

  ASSERT_EQ(6, res.load());
  ASSERT_TRUE(prom.future().isFinished());
  ASSERT_FALSE(prom.future().hasError());
}

void write42(boost::shared_ptr<int> ptr)
{
  *ptr = 42;
}

TEST(TestSignal, SharedPtr)
{
  // Redundant with Copy test, but just to be sure, check that shared_ptr
  // is correctly transmited.
  qi::Signal<boost::shared_ptr<int> > sig;
  sig.connect(qi::AnyFunction::from(&write42)).setCallType(qi::MetaCallType_Queued);
  {
    boost::shared_ptr<int> ptr(new int(12));
    sig(ptr);
  };
}

void byRef(int& i, bool* done)
{
  qiLogDebug() <<"byRef " << &i << ' ' << done;
  i = 12;
  *done = true;
}

TEST(TestSignal, AutoDisconnect)
{
  // Test automatic disconnection when passing shared_ptrs
  qi::Atomic<int> r{0};
  boost::shared_ptr<Foo> foo(new Foo());
  qi::Signal<qi::Atomic<int>*, int> sig;
  sig.connect(&Foo::func1, boost::weak_ptr<Foo>(foo), _1, _2).setCallType(qi::MetaCallType_Direct);
  sig(&r, 0);
  ASSERT_EQ(1, r.load());
  foo.reset();
  sig(&r, 0);
  ASSERT_EQ(1, r.load());
}

void waitFuture(qi::Atomic<int>& cnt, qi::Promise<void> start, qi::Future<void> f)
{
  if (++cnt == 2)
    start.setValue(0);
  f.wait();

  // force disconnection, may trigger a segfault
  throw qi::PointerLockException();
}

TEST(TestSignal, NonBlockingDestroy)
{
  // disconnect is blocking, but signal destruction should not be

  qi::Promise<void> start;
  qi::Promise<void> finish;
  qi::Atomic<int> cnt{0};

  {
    qi::Signal<void> sig;
    sig.connect(boost::bind(waitFuture, boost::ref(cnt), start, finish.future()));

    sig();
    sig();

    start.future().wait();
    // now that the callback is running, destroy the signal
  }

  // all went well, unblock the callback
  finish.setValue(0);
}

TEST(TestSignal, BadArity)
{
  // Test runtime detection of arity errors
  qi::Signal<> s;
  // avoid using s.connect() which will catch the problem at compile-time
  EXPECT_ANY_THROW(s.connect(qi::SignalSubscriber(qi::AnyFunction::from(&foo))));
  EXPECT_ANY_THROW(s.connect(qi::SignalSubscriber(qi::AnyFunction::from(&foo2))));
  EXPECT_ANY_THROW(s.connect(qi::AnyFunction::from((boost::function<void(qi::Atomic<int>*, int)>)boost::bind(&Foo::func1, (Foo*)0, _1, _2))));
}

void lol(int v, int& target)
{
  target = v;
}
TEST(TestSignal, SignalSignal)
{
  qi::SignalF<void (int)> sig1;
  qi::SignalF<void (int)> *sig2 = new  qi::SignalF<void (int)>();
  sig1.connect(*sig2);
  qi::SignalSpy spy(*sig2);
  sig1(10);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  ASSERT_EQ(10, spy.record(0).arg<int>(0));

  // Test autodisconnect
  delete sig2;
  sig1(20);
  ASSERT_FALSE(spy.waitUntil(2, qi::MilliSeconds(300)));
}

class SignalTest {
public:
  qi::Signal<int> sig;
  qi::Signal<int> sig2;
};

TEST(TestSignal, SignalSignal2)
{
  SignalTest st;
  qi::SignalSpy spy(st.sig2);
  st.sig.connect(st.sig2);
  qiLogDebug() << "sigptrs are " << &st.sig << " " << &st.sig2;
  st.sig(4242);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  assert(spy.recordCount() == 1u);
  EXPECT_EQ(4242, spy.lastRecord().arg<int>(0));
}

TEST(TestSignal, SignalN)
{
  qi::Signal<int> sig;
  qi::SignalSpy spy(sig);
  sig(5);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  ASSERT_EQ(5, spy.lastRecord().arg<int>(0));
}

class SigHolder
{
public:
  qi::Signal<> s0;
  qi::Signal<int> s1;
  qi::Signal<int, int> s2;
  void fire0() { s0();}
  void fire1(int i) { s1(i); }
  void fire2(int i, int j) { s2(i, j);}
};

QI_REGISTER_OBJECT(SigHolder, s0, s1, s2, fire0, fire1, fire2)

TEST(TestSignal, SignalNBind)
{
  int res = 0;
  boost::shared_ptr<SigHolder> so(new SigHolder);
  qi::AnyObject op = qi::AnyReference::from(so).to<qi::AnyObject>();
  qi::detail::printMetaObject(std::cerr, op.metaObject());
  op.connect("s1", (boost::function<void(int)>)boost::bind<void>(&lol, _1, boost::ref(res)));
  op.post("s1", 2);
  for (unsigned i=0; i<30 && res!=2; ++i) qi::os::msleep(10);
  ASSERT_EQ(2, res);
  so->s1(3);
  for (unsigned i=0; i<30 && res!=3; ++i) qi::os::msleep(10);
  ASSERT_EQ(3, res);
  so->s0.connect( boost::bind<void>(&lol, 42, boost::ref(res)));
  op.post("s0");
  for (unsigned i=0; i<30 && res!=42; ++i) qi::os::msleep(10);
  ASSERT_EQ(42, res);
}

void foothrow() {
  throw 42;
}

TEST(TestSignal, SignalThrow)
{
  qi::Signal<> sig;
  sig.connect(boost::bind<void>(&foothrow));
  ASSERT_NO_THROW(sig());
  qi::os::msleep(50);
}

void dynTest0(int& tgt)                     { tgt |= 1;}
void dynTest1(int& tgt, int)                { tgt |= 2;}
void dynTest2(int& tgt, int, int)           { tgt |= 4;}
void dynTest3(int& tgt, int, std::string)   { tgt |= 8;}
void dynTestN(int& tgt, const qi::AnyArguments& a)   { tgt |= 32;}
qi::AnyReference dynTestN2(int& tgt, const std::vector<qi::AnyReference>& a)   { tgt |= 16; return qi::AnyReference();}

TEST(TestSignal, Dynamic)
{
  qi::SignalBase s(qi::Signature("m"));
  int trig = 0;
  s.setCallType(qi::MetaCallType_Direct);
  s.connect((boost::function<void()>) boost::bind(&dynTest0, boost::ref(trig)));
  s.connect((boost::function<void(int)>) boost::bind(&dynTest1, boost::ref(trig), _1));
  s.connect((boost::function<void(int, int)>) boost::bind(&dynTest2, boost::ref(trig), _1, _2));
  s.connect((boost::function<void(int, std::string)>) boost::bind(&dynTest3, boost::ref(trig), _1, _2));
  s.connect(qi::AnyFunction::fromDynamicFunction(boost::bind(&dynTestN2, boost::ref(trig), _1)));
  s.connect((boost::function<void(const qi::AnyArguments&)>)(boost::bind(&dynTestN, boost::ref(trig), _1)));
  int a, b;
  std::string c;
  qi::GenericFunctionParameters params;
  s.trigger(params);
  EXPECT_EQ(49, trig);
  params.push_back(qi::AnyReference::from(a));
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(50, trig);
  params.push_back(qi::AnyReference::from(b));
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(52, trig);
  params[1] = qi::AnyReference::from(c);
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(56, trig);
}

void onSubs(std::atomic<bool>& var, bool subs)
{
  var = subs;
}

void callback(int i)
{}

TEST(TestSignal, OnSubscriber)
{
  std::atomic<bool> subscribers(false);

  qi::Signal<int> sig(boost::bind(onSubs, boost::ref(subscribers), _1));
  ASSERT_FALSE(subscribers);
  qi::SignalLink l = sig.connect(&callback);
  ASSERT_TRUE(subscribers);
  ASSERT_TRUE(sig.disconnect(l));
  ASSERT_FALSE(subscribers);
}

void store2(qi::Promise<int> variable1, qi::Promise<int> variable2, int value1, int value2)
{
  variable1.setValue(value1);
  variable2.setValue(value2);
}

TEST(TestSignal, SignalToSignalWithExtraArgument)
{
  qi::Promise<int> target1, target2;
  qi::Signal<int> signal1;
  qi::Signal<int, int> signal2;
  signal1.connect(boost::bind(boost::ref(signal2), _1, 42));
  signal2.connect(store2, target1, target2, _1, _2);
  signal1(12);
  EXPECT_EQ(12, target1.future().value());
  EXPECT_EQ(42, target2.future().value());
}

TEST(TestSignal, SignalSubscriberDoesNotUnsubscribeAtDestruction)
{
  int count = 0;
  qi::Signal<void> signal;
  auto subscriber = signal.connect([&]{ ++count; })
      .setCallType(qi::MetaCallType_Direct)
      .shared_from_this();
  signal();
  ASSERT_EQ(1, count);

  subscriber.reset();
  signal();
  ASSERT_EQ(2, count);
}

// ===========================================================
// Signal Spy
// -----------------------------------------------------------
TEST(TestSignalSpy, Counter)
{
  qi::Signal<int> sig;
  qi::SignalSpy sp(sig);
  QI_EMIT sig(1);
  QI_EMIT sig(1);
  ASSERT_TRUE(sp.waitUntil(2, qi::MilliSeconds(300)));
  ASSERT_EQ(sp.getCounter(), 2u);

  qi::DynamicObjectBuilder ob;
  ob.advertiseSignal("signal", &sig);
  qi::AnyObject obj(ob.object());
  qi::SignalSpy sp2(obj, "signal");
  QI_EMIT sig(1);
  QI_EMIT sig(1);
  ASSERT_TRUE(sp2.waitUntil(2, qi::MilliSeconds(300)));
  ASSERT_EQ(sp2.getCounter(), 2u);
}

TEST(TestSignalSpy, Async)
{
  qi::Signal<int> sig;
  qi::SignalSpy sp(sig);
  qi::async(boost::bind(boost::ref(sig), 1));
  qi::async(boost::bind(boost::ref(sig), 1));
  ASSERT_TRUE(sp.waitUntil(2, qi::Seconds(1)));
  ASSERT_EQ(sp.recordCount(), 2u);
}

TEST(TestSignalSpy, StoringTypedValueRecords)
{
  const std::vector<int> ints{ 1, 42, 13, 2016 };
  const std::vector<std::string> strings{ "poil", "slip", "banane", "pancréas" };
  qi::Signal<int, std::string> signal;
  qi::SignalSpy spy(signal);

  signal(ints[0], strings[0]);
  ASSERT_EQ(1u, spy.recordCount());
  auto record = spy.record(0);
  ASSERT_EQ(ints[0], record.arg<int>(0));
  ASSERT_EQ(strings[0], record.arg<std::string>(1));

  for(auto i = 1u; i < ints.size(); ++i)
  {
    signal(ints[i], strings[i]);
  }
  spy.waitUntil(ints.size(), qi::MilliSeconds(300));

  for(auto i = 1u; i < ints.size(); ++i)
  {
    record = spy.record(i);
    EXPECT_EQ(ints[i], record.arg<int>(0));
    EXPECT_EQ(strings[i], record.arg<std::string>(1));
  }

  auto records = spy.allRecords();
  ASSERT_EQ(ints.size(), records.size());
  for(auto i = 0u; i < records.size(); ++i)
  {
    EXPECT_EQ(ints[i], records[i].arg<int>(0));
    EXPECT_EQ(strings[i], records[i].arg<std::string>(1));
  }
}

int main(int argc, char **argv) {
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  qi::log::addFilter("*", qi::LogLevel_Debug);
  return RUN_ALL_TESTS();
}
<commit_msg>Fixed warning: we were using deprecated SignalSpy functions in tests.<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <gtest/gtest.h>
#include <qi/signal.hpp>
#include <qi/future.hpp>
#include <qi/signalspy.hpp>
#include <qi/anyobject.hpp>
#include <qi/application.hpp>
#include <qi/type/objecttypebuilder.hpp>
#include <qi/type/dynamicobjectbuilder.hpp>

qiLogCategory("test");

class Foo
{
public:
  void func(int)               { }
  void func1(qi::Atomic<int>* r, int)
  {
    // hackish sleep so that asynchronous trigger detection is safer
    qi::os::msleep(1); ++*r;
  }
  void func2(qi::Atomic<int>* r, int, int) { ++*r; }
};
void foo(qi::Atomic<int>* r, int, int)     { ++*r; }
void foo2(qi::Atomic<int>* r, char, char)  { ++*r; }
void foo3(qi::Atomic<int>* r, Foo *)       { ++*r; }
void foolast(int, qi::Promise<void> prom, qi::Atomic<int>* r) { prom.setValue(0); ++*r; }

TEST(TestSignal, TestCompilation)
{
  qi::Atomic<int>        res{0};
  qi::Signal<int> s;
  Foo*                   f = (Foo*)1;
  qi::Promise<void>      prom;

  //do not count
  s.connect(qi::AnyFunction::from(&Foo::func, f));
  s.connect(boost::bind<void>(&Foo::func, f, _1));

  s.connect(boost::bind(&foo, &res, 12, _1));
  s.connect(boost::bind(&foo2, &res, 12, _1));
  s.connect(boost::bind<void>(&Foo::func1, f, &res, _1));
  s.connect(boost::bind<void>(&Foo::func2, f, &res, 5, _1));
  s.connect(boost::bind(&foo3, &res, f));
  s.connect(boost::bind(&foolast, _1, prom, &res));

  s(42);

  while (res.load() != 6)
    qi::os::msleep(10);

  ASSERT_EQ(6, res.load());
  ASSERT_TRUE(prom.future().isFinished());
  ASSERT_FALSE(prom.future().hasError());
}

void write42(boost::shared_ptr<int> ptr)
{
  *ptr = 42;
}

TEST(TestSignal, SharedPtr)
{
  // Redundant with Copy test, but just to be sure, check that shared_ptr
  // is correctly transmited.
  qi::Signal<boost::shared_ptr<int> > sig;
  sig.connect(qi::AnyFunction::from(&write42)).setCallType(qi::MetaCallType_Queued);
  {
    boost::shared_ptr<int> ptr(new int(12));
    sig(ptr);
  };
}

void byRef(int& i, bool* done)
{
  qiLogDebug() <<"byRef " << &i << ' ' << done;
  i = 12;
  *done = true;
}

TEST(TestSignal, AutoDisconnect)
{
  // Test automatic disconnection when passing shared_ptrs
  qi::Atomic<int> r{0};
  boost::shared_ptr<Foo> foo(new Foo());
  qi::Signal<qi::Atomic<int>*, int> sig;
  sig.connect(&Foo::func1, boost::weak_ptr<Foo>(foo), _1, _2).setCallType(qi::MetaCallType_Direct);
  sig(&r, 0);
  ASSERT_EQ(1, r.load());
  foo.reset();
  sig(&r, 0);
  ASSERT_EQ(1, r.load());
}

void waitFuture(qi::Atomic<int>& cnt, qi::Promise<void> start, qi::Future<void> f)
{
  if (++cnt == 2)
    start.setValue(0);
  f.wait();

  // force disconnection, may trigger a segfault
  throw qi::PointerLockException();
}

TEST(TestSignal, NonBlockingDestroy)
{
  // disconnect is blocking, but signal destruction should not be

  qi::Promise<void> start;
  qi::Promise<void> finish;
  qi::Atomic<int> cnt{0};

  {
    qi::Signal<void> sig;
    sig.connect(boost::bind(waitFuture, boost::ref(cnt), start, finish.future()));

    sig();
    sig();

    start.future().wait();
    // now that the callback is running, destroy the signal
  }

  // all went well, unblock the callback
  finish.setValue(0);
}

TEST(TestSignal, BadArity)
{
  // Test runtime detection of arity errors
  qi::Signal<> s;
  // avoid using s.connect() which will catch the problem at compile-time
  EXPECT_ANY_THROW(s.connect(qi::SignalSubscriber(qi::AnyFunction::from(&foo))));
  EXPECT_ANY_THROW(s.connect(qi::SignalSubscriber(qi::AnyFunction::from(&foo2))));
  EXPECT_ANY_THROW(s.connect(qi::AnyFunction::from((boost::function<void(qi::Atomic<int>*, int)>)boost::bind(&Foo::func1, (Foo*)0, _1, _2))));
}

void lol(int v, int& target)
{
  target = v;
}
TEST(TestSignal, SignalSignal)
{
  qi::SignalF<void (int)> sig1;
  qi::SignalF<void (int)> *sig2 = new  qi::SignalF<void (int)>();
  sig1.connect(*sig2);
  qi::SignalSpy spy(*sig2);
  sig1(10);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  ASSERT_EQ(10, spy.record(0).arg<int>(0));

  // Test autodisconnect
  delete sig2;
  sig1(20);
  ASSERT_FALSE(spy.waitUntil(2, qi::MilliSeconds(300)));
}

class SignalTest {
public:
  qi::Signal<int> sig;
  qi::Signal<int> sig2;
};

TEST(TestSignal, SignalSignal2)
{
  SignalTest st;
  qi::SignalSpy spy(st.sig2);
  st.sig.connect(st.sig2);
  qiLogDebug() << "sigptrs are " << &st.sig << " " << &st.sig2;
  st.sig(4242);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  assert(spy.recordCount() == 1u);
  EXPECT_EQ(4242, spy.lastRecord().arg<int>(0));
}

TEST(TestSignal, SignalN)
{
  qi::Signal<int> sig;
  qi::SignalSpy spy(sig);
  sig(5);
  ASSERT_TRUE(spy.waitUntil(1, qi::MilliSeconds(300)));
  ASSERT_EQ(5, spy.lastRecord().arg<int>(0));
}

class SigHolder
{
public:
  qi::Signal<> s0;
  qi::Signal<int> s1;
  qi::Signal<int, int> s2;
  void fire0() { s0();}
  void fire1(int i) { s1(i); }
  void fire2(int i, int j) { s2(i, j);}
};

QI_REGISTER_OBJECT(SigHolder, s0, s1, s2, fire0, fire1, fire2)

TEST(TestSignal, SignalNBind)
{
  int res = 0;
  boost::shared_ptr<SigHolder> so(new SigHolder);
  qi::AnyObject op = qi::AnyReference::from(so).to<qi::AnyObject>();
  qi::detail::printMetaObject(std::cerr, op.metaObject());
  op.connect("s1", (boost::function<void(int)>)boost::bind<void>(&lol, _1, boost::ref(res)));
  op.post("s1", 2);
  for (unsigned i=0; i<30 && res!=2; ++i) qi::os::msleep(10);
  ASSERT_EQ(2, res);
  so->s1(3);
  for (unsigned i=0; i<30 && res!=3; ++i) qi::os::msleep(10);
  ASSERT_EQ(3, res);
  so->s0.connect( boost::bind<void>(&lol, 42, boost::ref(res)));
  op.post("s0");
  for (unsigned i=0; i<30 && res!=42; ++i) qi::os::msleep(10);
  ASSERT_EQ(42, res);
}

void foothrow() {
  throw 42;
}

TEST(TestSignal, SignalThrow)
{
  qi::Signal<> sig;
  sig.connect(boost::bind<void>(&foothrow));
  ASSERT_NO_THROW(sig());
  qi::os::msleep(50);
}

void dynTest0(int& tgt)                     { tgt |= 1;}
void dynTest1(int& tgt, int)                { tgt |= 2;}
void dynTest2(int& tgt, int, int)           { tgt |= 4;}
void dynTest3(int& tgt, int, std::string)   { tgt |= 8;}
void dynTestN(int& tgt, const qi::AnyArguments& a)   { tgt |= 32;}
qi::AnyReference dynTestN2(int& tgt, const std::vector<qi::AnyReference>& a)   { tgt |= 16; return qi::AnyReference();}

TEST(TestSignal, Dynamic)
{
  qi::SignalBase s(qi::Signature("m"));
  int trig = 0;
  s.setCallType(qi::MetaCallType_Direct);
  s.connect((boost::function<void()>) boost::bind(&dynTest0, boost::ref(trig)));
  s.connect((boost::function<void(int)>) boost::bind(&dynTest1, boost::ref(trig), _1));
  s.connect((boost::function<void(int, int)>) boost::bind(&dynTest2, boost::ref(trig), _1, _2));
  s.connect((boost::function<void(int, std::string)>) boost::bind(&dynTest3, boost::ref(trig), _1, _2));
  s.connect(qi::AnyFunction::fromDynamicFunction(boost::bind(&dynTestN2, boost::ref(trig), _1)));
  s.connect((boost::function<void(const qi::AnyArguments&)>)(boost::bind(&dynTestN, boost::ref(trig), _1)));
  int a, b;
  std::string c;
  qi::GenericFunctionParameters params;
  s.trigger(params);
  EXPECT_EQ(49, trig);
  params.push_back(qi::AnyReference::from(a));
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(50, trig);
  params.push_back(qi::AnyReference::from(b));
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(52, trig);
  params[1] = qi::AnyReference::from(c);
  trig = 0;
  s.trigger(params);
  EXPECT_EQ(56, trig);
}

void onSubs(std::atomic<bool>& var, bool subs)
{
  var = subs;
}

void callback(int i)
{}

TEST(TestSignal, OnSubscriber)
{
  std::atomic<bool> subscribers(false);

  qi::Signal<int> sig(boost::bind(onSubs, boost::ref(subscribers), _1));
  ASSERT_FALSE(subscribers);
  qi::SignalLink l = sig.connect(&callback);
  ASSERT_TRUE(subscribers);
  ASSERT_TRUE(sig.disconnect(l));
  ASSERT_FALSE(subscribers);
}

void store2(qi::Promise<int> variable1, qi::Promise<int> variable2, int value1, int value2)
{
  variable1.setValue(value1);
  variable2.setValue(value2);
}

TEST(TestSignal, SignalToSignalWithExtraArgument)
{
  qi::Promise<int> target1, target2;
  qi::Signal<int> signal1;
  qi::Signal<int, int> signal2;
  signal1.connect(boost::bind(boost::ref(signal2), _1, 42));
  signal2.connect(store2, target1, target2, _1, _2);
  signal1(12);
  EXPECT_EQ(12, target1.future().value());
  EXPECT_EQ(42, target2.future().value());
}

TEST(TestSignal, SignalSubscriberDoesNotUnsubscribeAtDestruction)
{
  int count = 0;
  qi::Signal<void> signal;
  auto subscriber = signal.connect([&]{ ++count; })
      .setCallType(qi::MetaCallType_Direct)
      .shared_from_this();
  signal();
  ASSERT_EQ(1, count);

  subscriber.reset();
  signal();
  ASSERT_EQ(2, count);
}

// ===========================================================
// Signal Spy
// -----------------------------------------------------------
TEST(TestSignalSpy, Counter)
{
  qi::Signal<int> sig;
  qi::SignalSpy sp(sig);
  QI_EMIT sig(1);
  QI_EMIT sig(1);
  ASSERT_TRUE(sp.waitUntil(2, qi::MilliSeconds(300)));
  ASSERT_EQ(sp.recordCount(), 2u);

  qi::DynamicObjectBuilder ob;
  ob.advertiseSignal("signal", &sig);
  qi::AnyObject obj(ob.object());
  qi::SignalSpy sp2(obj, "signal");
  QI_EMIT sig(1);
  QI_EMIT sig(1);
  ASSERT_TRUE(sp2.waitUntil(2, qi::MilliSeconds(300)));
  ASSERT_EQ(sp2.recordCount(), 2u);
}

TEST(TestSignalSpy, Async)
{
  qi::Signal<int> sig;
  qi::SignalSpy sp(sig);
  qi::async(boost::bind(boost::ref(sig), 1));
  qi::async(boost::bind(boost::ref(sig), 1));
  ASSERT_TRUE(sp.waitUntil(2, qi::Seconds(1)));
  ASSERT_EQ(sp.recordCount(), 2u);
}

TEST(TestSignalSpy, StoringTypedValueRecords)
{
  const std::vector<int> ints{ 1, 42, 13, 2016 };
  const std::vector<std::string> strings{ "poil", "slip", "banane", "pancréas" };
  qi::Signal<int, std::string> signal;
  qi::SignalSpy spy(signal);

  signal(ints[0], strings[0]);
  ASSERT_EQ(1u, spy.recordCount());
  auto record = spy.record(0);
  ASSERT_EQ(ints[0], record.arg<int>(0));
  ASSERT_EQ(strings[0], record.arg<std::string>(1));

  for(auto i = 1u; i < ints.size(); ++i)
  {
    signal(ints[i], strings[i]);
  }
  spy.waitUntil(ints.size(), qi::MilliSeconds(300));

  for(auto i = 1u; i < ints.size(); ++i)
  {
    record = spy.record(i);
    EXPECT_EQ(ints[i], record.arg<int>(0));
    EXPECT_EQ(strings[i], record.arg<std::string>(1));
  }

  auto records = spy.allRecords();
  ASSERT_EQ(ints.size(), records.size());
  for(auto i = 0u; i < records.size(); ++i)
  {
    EXPECT_EQ(ints[i], records[i].arg<int>(0));
    EXPECT_EQ(strings[i], records[i].arg<std::string>(1));
  }
}

int main(int argc, char **argv) {
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  qi::log::addFilter("*", qi::LogLevel_Debug);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include <qi/type/detail/manageable.hpp>
#include <qi/type/objecttypebuilder.hpp>

#include "staticobjecttype.hpp"

namespace qi
{

  class ManageablePrivate
  {
  public:
    ManageablePrivate();
    ~ManageablePrivate();
    // SignalLinks that target us. Needed to be able to disconnect upon destruction
    std::vector<SignalSubscriber>       registrations;
    mutable boost::mutex                registrationsMutex;
    bool                                dying;
    // Event loop in which calls are made if set
    boost::shared_ptr<ExecutionContext> executionContext;
    boost::mutex                        initMutex;

    bool statsEnabled;
    bool traceEnabled;
    ObjectStatistics stats;
    qi::Atomic<int> traceId;
  };

  ManageablePrivate::ManageablePrivate()
    : dying(false)
    , statsEnabled(false)
    , traceEnabled(false)
  {
  }

  ManageablePrivate::~ManageablePrivate()
  {
    dying = true;
    std::vector<SignalSubscriber> copy;
    {
      boost::mutex::scoped_lock sl(registrationsMutex);
      copy = registrations;
    }
    for (unsigned i = 0; i < copy.size(); ++i)
    {
      copy[i].source->disconnect(copy[i].linkId);
    }
  }

  Manageable::Manageable()
    : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
    , _p(new ManageablePrivate())
  {
  }

  Manageable::Manageable(const Manageable& b)
    : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
    , _p(new ManageablePrivate())
  {
    _p->executionContext = b._p->executionContext;
  }

  void Manageable::operator=(const Manageable& b)
  {
    _p.reset(new ManageablePrivate());
    _p->executionContext = b._p->executionContext;
  }

  Manageable::~Manageable()
  {
  }

  boost::mutex& Manageable::initMutex()
  {
    return _p->initMutex;
  }

  void Manageable::forceExecutionContext(
      boost::shared_ptr<ExecutionContext> ec)
  {
    _p->executionContext = ec;
  }

  boost::shared_ptr<ExecutionContext> Manageable::executionContext() const
  {
    return _p->executionContext;
  }

  bool Manageable::isStatsEnabled() const
  {
    return _p->statsEnabled;
  }

  void Manageable::enableStats(bool state)
  {
    _p->statsEnabled = state;
  }

  void Manageable::pushStats(int slotId, float wallTime, float userTime, float systemTime)
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    MethodStatistics& ms = _p->stats[slotId];
    ms.push(wallTime, userTime, systemTime);
  }

  ObjectStatistics Manageable::stats() const
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    return _p->stats;
  }

  void Manageable::clearStats()
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    _p->stats.clear();
  }

  bool Manageable::isTraceEnabled() const
  {
    return _p->traceEnabled;
  }

  void Manageable::enableTrace(bool state)
  {
    _p->traceEnabled = state;
  }

  int Manageable::_nextTraceId()
  {
    return ++_p->traceId;
  }

  namespace manageable
  {
  static Manageable::MethodMap* methodMap = 0;
  static Manageable::SignalMap* signalMap = 0;
  static MetaObject* metaObject = 0;
  }
  void Manageable::_build()
  {
    if (manageable::methodMap)
      return;
    manageable::methodMap = new MethodMap();
    manageable::signalMap = new SignalMap();
    manageable::metaObject = new MetaObject();
    ObjectTypeBuilder<Manageable> builder;
    unsigned int id = startId;
    builder.advertiseMethod("isStatsEnabled", &Manageable::isStatsEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableStats", &Manageable::enableStats,       MetaCallType_Auto, id++);
    builder.advertiseMethod("stats", &Manageable::stats,                   MetaCallType_Auto, id++);
    builder.advertiseMethod("clearStats", &Manageable::clearStats,         MetaCallType_Auto, id++);
    builder.advertiseMethod("isTraceEnabled", &Manageable::isTraceEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableTrace", &Manageable::enableTrace,       MetaCallType_Auto, id++);
    builder.advertiseSignal("traceObject", &Manageable::traceObject, id++);
    assert(id <= endId);
    const ObjectTypeData& typeData = builder.typeData();
    *manageable::methodMap = typeData.methodMap;
    *manageable::signalMap = typeData.signalGetterMap;
    *manageable::metaObject = builder.metaObject();
  }

  Manageable::MethodMap& Manageable::manageableMmethodMap()
  {
    _build();
    return *manageable::methodMap;
  }

  Manageable::SignalMap& Manageable::manageableSignalMap()
  {
    _build();
    return *manageable::signalMap;
  }

  MetaObject& Manageable::manageableMetaObject()
  {
    _build();
    return *manageable::metaObject;
  }

}
<commit_msg>fix wrongly instanciated scoped_locks<commit_after>#include <qi/type/detail/manageable.hpp>
#include <qi/type/objecttypebuilder.hpp>

#include "staticobjecttype.hpp"

namespace qi
{

  class ManageablePrivate
  {
  public:
    ManageablePrivate();
    ~ManageablePrivate();
    // SignalLinks that target us. Needed to be able to disconnect upon destruction
    std::vector<SignalSubscriber>       registrations;
    mutable boost::mutex                registrationsMutex;
    bool                                dying;
    // Event loop in which calls are made if set
    boost::shared_ptr<ExecutionContext> executionContext;
    boost::mutex                        initMutex;

    bool statsEnabled;
    bool traceEnabled;
    ObjectStatistics stats;
    qi::Atomic<int> traceId;
  };

  ManageablePrivate::ManageablePrivate()
    : dying(false)
    , statsEnabled(false)
    , traceEnabled(false)
  {
  }

  ManageablePrivate::~ManageablePrivate()
  {
    dying = true;
    std::vector<SignalSubscriber> copy;
    {
      boost::mutex::scoped_lock sl(registrationsMutex);
      copy = registrations;
    }
    for (unsigned i = 0; i < copy.size(); ++i)
    {
      copy[i].source->disconnect(copy[i].linkId);
    }
  }

  Manageable::Manageable()
    : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
    , _p(new ManageablePrivate())
  {
  }

  Manageable::Manageable(const Manageable& b)
    : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
    , _p(new ManageablePrivate())
  {
    _p->executionContext = b._p->executionContext;
  }

  void Manageable::operator=(const Manageable& b)
  {
    _p.reset(new ManageablePrivate());
    _p->executionContext = b._p->executionContext;
  }

  Manageable::~Manageable()
  {
  }

  boost::mutex& Manageable::initMutex()
  {
    return _p->initMutex;
  }

  void Manageable::forceExecutionContext(
      boost::shared_ptr<ExecutionContext> ec)
  {
    _p->executionContext = ec;
  }

  boost::shared_ptr<ExecutionContext> Manageable::executionContext() const
  {
    return _p->executionContext;
  }

  bool Manageable::isStatsEnabled() const
  {
    return _p->statsEnabled;
  }

  void Manageable::enableStats(bool state)
  {
    _p->statsEnabled = state;
  }

  void Manageable::pushStats(int slotId, float wallTime, float userTime, float systemTime)
  {
    boost::mutex::scoped_lock l(_p->registrationsMutex);
    MethodStatistics& ms = _p->stats[slotId];
    ms.push(wallTime, userTime, systemTime);
  }

  ObjectStatistics Manageable::stats() const
  {
    boost::mutex::scoped_lock l(_p->registrationsMutex);
    return _p->stats;
  }

  void Manageable::clearStats()
  {
    boost::mutex::scoped_lock l(_p->registrationsMutex);
    _p->stats.clear();
  }

  bool Manageable::isTraceEnabled() const
  {
    return _p->traceEnabled;
  }

  void Manageable::enableTrace(bool state)
  {
    _p->traceEnabled = state;
  }

  int Manageable::_nextTraceId()
  {
    return ++_p->traceId;
  }

  namespace manageable
  {
  static Manageable::MethodMap* methodMap = 0;
  static Manageable::SignalMap* signalMap = 0;
  static MetaObject* metaObject = 0;
  }
  void Manageable::_build()
  {
    if (manageable::methodMap)
      return;
    manageable::methodMap = new MethodMap();
    manageable::signalMap = new SignalMap();
    manageable::metaObject = new MetaObject();
    ObjectTypeBuilder<Manageable> builder;
    unsigned int id = startId;
    builder.advertiseMethod("isStatsEnabled", &Manageable::isStatsEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableStats", &Manageable::enableStats,       MetaCallType_Auto, id++);
    builder.advertiseMethod("stats", &Manageable::stats,                   MetaCallType_Auto, id++);
    builder.advertiseMethod("clearStats", &Manageable::clearStats,         MetaCallType_Auto, id++);
    builder.advertiseMethod("isTraceEnabled", &Manageable::isTraceEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableTrace", &Manageable::enableTrace,       MetaCallType_Auto, id++);
    builder.advertiseSignal("traceObject", &Manageable::traceObject, id++);
    assert(id <= endId);
    const ObjectTypeData& typeData = builder.typeData();
    *manageable::methodMap = typeData.methodMap;
    *manageable::signalMap = typeData.signalGetterMap;
    *manageable::metaObject = builder.metaObject();
  }

  Manageable::MethodMap& Manageable::manageableMmethodMap()
  {
    _build();
    return *manageable::methodMap;
  }

  Manageable::SignalMap& Manageable::manageableSignalMap()
  {
    _build();
    return *manageable::signalMap;
  }

  MetaObject& Manageable::manageableMetaObject()
  {
    _build();
    return *manageable::metaObject;
  }

}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#include <utility>

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/gtl/flatmap.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename T>
class UniqueOp : public OpKernel {
 public:
  explicit UniqueOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                errors::InvalidArgument("unique expects a 1D vector."));
    // TODO(dga):  Make unique polymorphic for returning int32 and int64
    // vectors to support large tensors.
    OP_REQUIRES(context,
                input.NumElements() <= std::numeric_limits<int32>::max(),
                errors::InvalidArgument(
                    "unique does not support input tensors larger than ",
                    std::numeric_limits<int32>::max(), " elements"));
    auto Tin = input.vec<T>();
    const int64 N = static_cast<int64>(Tin.size());

    Tensor* idx = nullptr;
    OP_REQUIRES_OK(context, context->forward_input_or_allocate_output(
                                {0}, 1, input.shape(), &idx));
    auto idx_vec = idx->template vec<int32>();

    gtl::FlatMap<T, int32> uniq(N);
    for (int64 i = 0, j = 0; i < N; ++i) {
      auto it = uniq.insert(std::make_pair(Tin(i), j));
      idx_vec(i) = it.first->second;
      if (it.second) {
        ++j;
      }
    }
    int64 uniq_size = static_cast<int64>(uniq.size());
    Tensor* output = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(
                                0, TensorShape({uniq_size}), &output));
    auto output_vec = output->template vec<T>();

    for (auto it : uniq) {
      output_vec(it.second) = it.first;
    }

    if (num_outputs() > 2) {
      OP_REQUIRES_OK(context, context->allocate_output(
                                  2, TensorShape({uniq_size}), &output));
      auto count_output_vec = output->template vec<int32>();
      count_output_vec.setZero();
      for (int64 i = 0; i < N; ++i) {
        count_output_vec(idx_vec(i))++;
      }
    }
  }
};

#define REGISTER_UNIQUE(type)                                    \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type>);                       \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type>)
TF_CALL_REAL_NUMBER_TYPES(REGISTER_UNIQUE);
REGISTER_UNIQUE(string)
#undef REGISTER_UNIQUE

// Fake integer GPU kernels so that the use of Unique in optimizers (to
// de-duplicate sparse gradient indices) does not conflict with gradients being
// located on a GPU. These kernels run on the CPU, their inputs and outputs
// residing in host (not GPU) memory.
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64>);

#ifdef TENSORFLOW_USE_SYCL
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64>);
#endif // TENSORFLOW_USE_SYCL
}  // namespace tensorflow
<commit_msg>Automated g4 rollback of changelist 155070869<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#include <unordered_map>
#include <utility>

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/status.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename T>
class UniqueOp : public OpKernel {
 public:
  explicit UniqueOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                errors::InvalidArgument("unique expects a 1D vector."));
    // TODO(dga):  Make unique polymorphic for returning int32 and int64
    // vectors to support large tensors.
    OP_REQUIRES(context,
                input.NumElements() <= std::numeric_limits<int32>::max(),
                errors::InvalidArgument(
                    "unique does not support input tensors larger than ",
                    std::numeric_limits<int32>::max(), " elements"));
    auto Tin = input.vec<T>();
    const int64 N = static_cast<int64>(Tin.size());

    Tensor* idx = nullptr;
    OP_REQUIRES_OK(context, context->forward_input_or_allocate_output(
                                {0}, 1, input.shape(), &idx));
    auto idx_vec = idx->template vec<int32>();

    std::unordered_map<T, int32> uniq;
    uniq.reserve(2 * N);
    for (int64 i = 0, j = 0; i < N; ++i) {
      auto it = uniq.insert(std::make_pair(Tin(i), j));
      idx_vec(i) = it.first->second;
      if (it.second) {
        ++j;
      }
    }
    int64 uniq_size = static_cast<int64>(uniq.size());
    Tensor* output = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(
                                0, TensorShape({uniq_size}), &output));
    auto output_vec = output->template vec<T>();

    for (auto it : uniq) {
      output_vec(it.second) = it.first;
    }

    if (num_outputs() > 2) {
      OP_REQUIRES_OK(context, context->allocate_output(
                                  2, TensorShape({uniq_size}), &output));
      auto count_output_vec = output->template vec<int32>();
      count_output_vec.setZero();
      for (int64 i = 0; i < N; ++i) {
        count_output_vec(idx_vec(i))++;
      }
    }
  }
};

#define REGISTER_UNIQUE(type)                                    \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type>);                       \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type>)
TF_CALL_REAL_NUMBER_TYPES(REGISTER_UNIQUE);
REGISTER_UNIQUE(string)
#undef REGISTER_UNIQUE

// Fake integer GPU kernels so that the use of Unique in optimizers (to
// de-duplicate sparse gradient indices) does not conflict with gradients being
// located on a GPU. These kernels run on the CPU, their inputs and outputs
// residing in host (not GPU) memory.
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64>);

#ifdef TENSORFLOW_USE_SYCL
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64>);
#endif // TENSORFLOW_USE_SYCL
}  // namespace tensorflow
<|endoftext|>


<commit_before>// RUN: %clang_cc1 %s -g -S -emit-llvm -o - | FileCheck %s

struct A {
  virtual void f();
};

struct B {
  virtual void f();
};

struct C : A, B {
  virtual void f();
};

void C::f() { }

// CHECK: [ DW_TAG_subprogram ] [line 15] [def] [_ZThn8_N1C1fEv]
<commit_msg>clang/test/CodeGenCXX/debug-info-thunk.cpp: Suppress it for now with XFAIL:*, due to failing on i686-*-*.<commit_after>// RUN: %clang_cc1 %s -g -S -emit-llvm -o - | FileCheck %s

// FIXME: Failing on i686.
// XFAIL: *
// RUN: %clang_cc1 -triple i686-linux %s -g -S -emit-llvm -o - | FileCheck %s

struct A {
  virtual void f();
};

struct B {
  virtual void f();
};

struct C : A, B {
  virtual void f();
};

void C::f() { }

// CHECK: [ DW_TAG_subprogram ] [line 15] [def] [_ZThn8_N1C1fEv]
<|endoftext|>


<commit_before>// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// /Yc but pch generation fails => main file not compiled
// This is a separate file since executing this failure path requires
// code generation, which makes this test require an x86 backend.
// REQUIRES: x86-registered-target

// RUN: not %clang_cl -internal-enable-pch -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c -DERR_HEADER -- %s 2>&1 \
// RUN:   | FileCheck %s

// CHECK: nope1
// CHECK-NOT: nope2

#error nope2
<commit_msg>test/Driver/cl-pch-errorhandling.cpp: Copy input file to a temporary location as we cannot assume the location of the input file to be writable.<commit_after>// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// /Yc but pch generation fails => main file not compiled
// This is a separate file since executing this failure path requires
// code generation, which makes this test require an x86 backend.
// REQUIRES: x86-registered-target

// RUN: cp %S/Inputs/pchfile.h %t.h
// RUN: not %clang_cl -internal-enable-pch -Werror /Yc%t.h /FI%t.h /c -DERR_HEADER -- %s 2>&1 \
// RUN:   | FileCheck %s

// CHECK: nope1
// CHECK-NOT: nope2

#error nope2
<|endoftext|>


<commit_before><commit_msg>Fix building warning under Visual Studio 2015 in test project.<commit_after><|endoftext|>


<commit_before><commit_msg>coverity#1202948 Uninitialized pointer field<commit_after><|endoftext|>