<commit_before>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma GCC push_options
#pragma GCC optimize ("O0")

#include "f4.h"
#include "rosflight.h"
#include "mavlink.h"

int main(void)
{
  rosflight_firmware::Revo board;
  rosflight_firmware::Mavlink mavlink(board);
  rosflight_firmware::ROSflight firmware(board, mavlink);
  board.init_board();

  firmware.init();

  while(1)
  {
    firmware.run();
  }
  return 0;
}

#pragma GCC pop_options
<commit_msg>lingering rename<commit_after>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma GCC push_options
#pragma GCC optimize ("O0")

#include "f4.h"
#include "rosflight.h"
#include "mavlink.h"

int main(void)
{
  rosflight_firmware::F4Board board;
  rosflight_firmware::Mavlink mavlink(board);
  rosflight_firmware::ROSflight firmware(board, mavlink);
  board.init_board();

  firmware.init();

  while(1)
  {
    firmware.run();
  }
  return 0;
}

#pragma GCC pop_options
<|endoftext|>


<commit_before><commit_msg>fixed BUG where broadcast didn't copy the start offset<commit_after><|endoftext|>


<commit_before>#include "move.hh"

template<class T>
inline static T fixLen(T len) {
    return len ? len : 1;
}
boost::optional< std::shared_ptr<change> > mvf(contents& contents, boost::optional<int> op) {
    int times = op ? op.get() : 1;
    long newx = contents.x + times;
    try {
        while(fixLen(contents.cont.at(contents.y).length()) <= newx) {
            newx -= fixLen(contents.cont[contents.y].length());
            contents.y++;
        }
    } catch(...) { }
    if(contents.y >= contents.cont.size()) contents.y = contents.cont.size() - 1;
    if((long) contents.x < 0) contents.x = 0;
    else                      contents.x = newx;
    contents.waiting_for_desired = false;
    return boost::none;
}
boost::optional< std::shared_ptr<change> > mvb(contents& contents, boost::optional<int> op) {
    int times = op ? op.get() : 1;
    if(contents.y == 0 && contents.x == 0) return boost::none;
    long newx = contents.x - times;
    try {
        while(newx < 0) {
            contents.y--;
            newx += fixLen(contents.cont.at(contents.y).length());
        }
    } catch(...) { }
    if(newx < 0) contents.x = 0;
    else         contents.x = newx;
    contents.waiting_for_desired = false;
    return boost::none;
}
<commit_msg>``mvf`` and ``mvb`` will show a message and do nothing if at start/end buffer<commit_after>#include "../../../src/show_message.hh"
#include "move.hh"

template<class T>
inline static T fixLen(T len) {
    return len ? len : 1;
}
boost::optional< std::shared_ptr<change> > mvf(contents& contents, boost::optional<int> op) {
    if (contents.y == contents.cont.size() - 1 &&
        contents.x == contents.cont[contents.y].size() - 1) {
        show_message("Can't move to that location (start/end of buffer)");
        return boost::none;
    }
    int times = op ? op.get() : 1;
    long newx = contents.x + times;
    try {
        while(fixLen(contents.cont.at(contents.y).length()) <= newx) {
            newx -= fixLen(contents.cont[contents.y].length());
            contents.y++;
        }
    } catch(...) { }
    if(contents.y >= contents.cont.size()) contents.y = contents.cont.size() - 1;
    if((long) contents.x < 0) contents.x = 0;
    else                      contents.x = newx;
    contents.waiting_for_desired = false;
    return boost::none;
}
boost::optional< std::shared_ptr<change> > mvb(contents& contents, boost::optional<int> op) {
    if (contents.y == 0 && contents.x == 0) {
        show_message("Can't move to that location (start/end of buffer)");
        return boost::none;
    }
    int times = op ? op.get() : 1;
    long newx = contents.x - times;
    try {
        while(newx < 0) {
            contents.y--;
            newx += fixLen(contents.cont.at(contents.y).length());
        }
    } catch(...) { }
    if(newx < 0) contents.x = 0;
    else         contents.x = newx;
    contents.waiting_for_desired = false;
    return boost::none;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  SEEDA03 (RX64M) メイン
	@copyright Copyright 2017 Kunihito Hiramatsu All Right Reserved.
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"

#include "common/rspi_io.hpp"
#include "common/spi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/command.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/input.hpp"
#include "common/time.h"

#include "chip/LTC2348_16.hpp"
#include "sample.hpp"
#include "preference.hpp"

#include "chip/EUI_XX.hpp"

#include "r_net/http_server.hpp"
#include "r_net/ftp_server.hpp"

#ifdef DEBUG
#define CLIENT_DEBUG
#define NETS_DEBUG
#define WRITE_FILE_DEBUG
#endif

namespace seeda {

	static const int seeda_version_ = 330;
	static const uint32_t build_id_ = B_ID;

	typedef utils::command<256> CMD;

#ifdef SEEDA
	typedef device::PORT<device::PORT6, device::bitpos::B7> SW1;
	typedef device::PORT<device::PORT6, device::bitpos::B6> SW2;
#endif

	// Soft SDC 用　SPI 定義（SPI）
#ifdef SEEDA
	typedef device::PORT<device::PORTD, device::bitpos::B6> MISO;
	typedef device::PORT<device::PORTD, device::bitpos::B4> MOSI;
	typedef device::PORT<device::PORTD, device::bitpos::B5> SPCK;
	typedef device::spi_io<MISO, MOSI, SPCK> SPI;

	typedef device::PORT<device::PORTD, device::bitpos::B3> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTE, device::bitpos::B6> SDC_DETECT;	///< カード検出
#else
	// SDC 用　SPI 定義（RSPI）
	typedef device::rspi_io<device::RSPI> SPI;
	typedef device::PORT<device::PORTC, device::bitpos::B4> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTB, device::bitpos::B7> SDC_DETECT;	///< カード検出
#endif
	typedef utils::sdc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> SDC;

#ifdef SEEDA
	// LTC2348-16 A/D 制御ポート定義
	typedef device::PORT<device::PORT4, device::bitpos::B0> LTC_CSN;   // P40(141)
	typedef device::PORT<device::PORTC, device::bitpos::B6> LTC_CNV;   // PC6(61)
	typedef device::PORT<device::PORTD, device::bitpos::B0> LTC_BUSY;  // PD0/IRQ0(126)
	typedef device::PORT<device::PORT5, device::bitpos::B3> LTC_PD;    // P53(53)
	typedef device::PORT<device::PORT5, device::bitpos::B6> LTC_SDI;   // P56(50)
	typedef device::PORT<device::PORT8, device::bitpos::B6> LTC_SCKO;  // P86(41)
	typedef device::PORT<device::PORT8, device::bitpos::B7> LTC_SCKI;  // P87(39)
	typedef device::PORT<device::PORT2, device::bitpos::B0> LTC_SDO0;  // P20(37)
	typedef device::PORT<device::PORT2, device::bitpos::B1> LTC_SDO2;  // P21(36)
	typedef device::PORT<device::PORT2, device::bitpos::B2> LTC_SDO4;  // P22(35)
	typedef device::PORT<device::PORT2, device::bitpos::B3> LTC_SDO6;  // P23(34)
	typedef struct chip::LTC2348_SDO_t<LTC_SCKO, LTC_SDO0, LTC_SDO2, LTC_SDO4, LTC_SDO6> LTC_SDO;
	typedef chip::LTC2348_16<LTC_CSN, LTC_CNV, LTC_BUSY, LTC_PD, LTC_SDI, LTC_SCKI, LTC_SDO> EADC;
#endif

	typedef net::http_server<SDC, 16, 8192> HTTP;
	typedef HTTP::http_format http_format;

	typedef net::ftp_server<SDC> FTPS;

	//-----------------------------------------------------------------//
	/*!
		@brief  SDC_IO クラスへの参照
		@return SDC_IO クラス
	*/
	//-----------------------------------------------------------------//
	SDC& at_sdc();

	//-----------------------------------------------------------------//
	/*!
		@brief  プリファレンスへの参照
		@return プリファレンス
	*/
	//-----------------------------------------------------------------//
	preference& at_pre();

#ifdef SEEDA
	//-----------------------------------------------------------------//
	/*!
		@brief  EADC クラスへの参照
		@return EADC クラス
	*/
	//-----------------------------------------------------------------//
	EADC& at_eadc();
#endif

	//-----------------------------------------------------------------//
	/*!
		@brief  EADC サーバー
	*/
	//-----------------------------------------------------------------//
	void eadc_server();

	//-----------------------------------------------------------------//
	/*!
		@brief  EADC サーバー許可
		@param[in]	ena	「false」の場合不許可
	*/
	//-----------------------------------------------------------------//
	void enable_eadc_server(bool ena = true);

	//-----------------------------------------------------------------//
	/*!
		@brief  時間の作成
		@param[in]	date	日付
		@param[in]	time	時間
	*/
	//-----------------------------------------------------------------//
	size_t make_time(const char* date, const char* time);

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の設定
		@param[in]	t	GMT 時間
	*/
	//-----------------------------------------------------------------//
	void set_time(time_t t);

	//-----------------------------------------------------------------//
	/*!
		@brief  時間の表示
		@param[in]	t		時間
		@param[in]	dst		出力文字列
		@param[in]	size	文字列の大きさ
		@return 生成された文字列の長さ
	*/
	//-----------------------------------------------------------------//
	int disp_time(time_t t, char* dst = nullptr, uint32_t size = 0);

	//-----------------------------------------------------------------//
	/*!
		@brief  設定スイッチの状態を取得
		@return 設定スイッチの状態
	*/
	//-----------------------------------------------------------------//
	uint8_t get_switch()
	{
#ifdef SEEDA
		return static_cast<uint8_t>(!SW1::P()) | (static_cast<uint8_t>(!SW2::P()) << 1);
#else
		return 0;  // for only develope mode
#endif
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  A/D サンプルの参照
		@param[in]	ch	チャネル（０～７）
		@return A/D サンプル
	*/
	//-----------------------------------------------------------------//
	sample_t& at_sample(uint8_t ch);

	//-----------------------------------------------------------------//
	/*!
		@brief  A/D サンプルの取得
		@return A/D サンプル
	*/
	//-----------------------------------------------------------------//
	const sample_data& get_sample_data();

	//-----------------------------------------------------------------//
	/*!
		@brief  内臓 A/D 変換値の取得
		@param[in]	ch	チャネル（５、６、７）
		@return A/D 変換値
	*/
	//-----------------------------------------------------------------//
	uint16_t get_adc(uint32_t ch);
}

extern "C" {

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の取得
		@return GMT 時間
	*/
	//-----------------------------------------------------------------//
	time_t get_time();

};
<commit_msg>update version NO<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  SEEDA03 (RX64M) メイン
	@copyright Copyright 2017 Kunihito Hiramatsu All Right Reserved.
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"

#include "common/rspi_io.hpp"
#include "common/spi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/command.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/input.hpp"
#include "common/time.h"

#include "chip/LTC2348_16.hpp"
#include "sample.hpp"
#include "preference.hpp"

#include "chip/EUI_XX.hpp"

#include "r_net/http_server.hpp"
#include "r_net/ftp_server.hpp"

#ifdef DEBUG
#define CLIENT_DEBUG
#define NETS_DEBUG
#define WRITE_FILE_DEBUG
#endif

namespace seeda {

	static const int seeda_version_ = 501;
	static const uint32_t build_id_ = B_ID;

	typedef utils::command<256> CMD;

#ifdef SEEDA
	typedef device::PORT<device::PORT6, device::bitpos::B7> SW1;
	typedef device::PORT<device::PORT6, device::bitpos::B6> SW2;
#endif

	// Soft SDC 用　SPI 定義（SPI）
#ifdef SEEDA
	typedef device::PORT<device::PORTD, device::bitpos::B6> MISO;
	typedef device::PORT<device::PORTD, device::bitpos::B4> MOSI;
	typedef device::PORT<device::PORTD, device::bitpos::B5> SPCK;
	typedef device::spi_io<MISO, MOSI, SPCK> SPI;

	typedef device::PORT<device::PORTD, device::bitpos::B3> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTE, device::bitpos::B6> SDC_DETECT;	///< カード検出
#else
	// SDC 用　SPI 定義（RSPI）
	typedef device::rspi_io<device::RSPI> SPI;
	typedef device::PORT<device::PORTC, device::bitpos::B4> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTB, device::bitpos::B7> SDC_DETECT;	///< カード検出
#endif
	typedef utils::sdc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> SDC;

#ifdef SEEDA
	// LTC2348-16 A/D 制御ポート定義
	typedef device::PORT<device::PORT4, device::bitpos::B0> LTC_CSN;   // P40(141)
	typedef device::PORT<device::PORTC, device::bitpos::B6> LTC_CNV;   // PC6(61)
	typedef device::PORT<device::PORTD, device::bitpos::B0> LTC_BUSY;  // PD0/IRQ0(126)
	typedef device::PORT<device::PORT5, device::bitpos::B3> LTC_PD;    // P53(53)
	typedef device::PORT<device::PORT5, device::bitpos::B6> LTC_SDI;   // P56(50)
	typedef device::PORT<device::PORT8, device::bitpos::B6> LTC_SCKO;  // P86(41)
	typedef device::PORT<device::PORT8, device::bitpos::B7> LTC_SCKI;  // P87(39)
	typedef device::PORT<device::PORT2, device::bitpos::B0> LTC_SDO0;  // P20(37)
	typedef device::PORT<device::PORT2, device::bitpos::B1> LTC_SDO2;  // P21(36)
	typedef device::PORT<device::PORT2, device::bitpos::B2> LTC_SDO4;  // P22(35)
	typedef device::PORT<device::PORT2, device::bitpos::B3> LTC_SDO6;  // P23(34)
	typedef struct chip::LTC2348_SDO_t<LTC_SCKO, LTC_SDO0, LTC_SDO2, LTC_SDO4, LTC_SDO6> LTC_SDO;
	typedef chip::LTC2348_16<LTC_CSN, LTC_CNV, LTC_BUSY, LTC_PD, LTC_SDI, LTC_SCKI, LTC_SDO> EADC;
#endif

	typedef net::http_server<SDC, 16, 8192> HTTP;
	typedef HTTP::http_format http_format;

	typedef net::ftp_server<SDC> FTPS;

	//-----------------------------------------------------------------//
	/*!
		@brief  SDC_IO クラスへの参照
		@return SDC_IO クラス
	*/
	//-----------------------------------------------------------------//
	SDC& at_sdc();

	//-----------------------------------------------------------------//
	/*!
		@brief  プリファレンスへの参照
		@return プリファレンス
	*/
	//-----------------------------------------------------------------//
	preference& at_pre();

#ifdef SEEDA
	//-----------------------------------------------------------------//
	/*!
		@brief  EADC クラスへの参照
		@return EADC クラス
	*/
	//-----------------------------------------------------------------//
	EADC& at_eadc();
#endif

	//-----------------------------------------------------------------//
	/*!
		@brief  EADC サーバー
	*/
	//-----------------------------------------------------------------//
	void eadc_server();

	//-----------------------------------------------------------------//
	/*!
		@brief  EADC サーバー許可
		@param[in]	ena	「false」の場合不許可
	*/
	//-----------------------------------------------------------------//
	void enable_eadc_server(bool ena = true);

	//-----------------------------------------------------------------//
	/*!
		@brief  時間の作成
		@param[in]	date	日付
		@param[in]	time	時間
	*/
	//-----------------------------------------------------------------//
	size_t make_time(const char* date, const char* time);

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の設定
		@param[in]	t	GMT 時間
	*/
	//-----------------------------------------------------------------//
	void set_time(time_t t);

	//-----------------------------------------------------------------//
	/*!
		@brief  時間の表示
		@param[in]	t		時間
		@param[in]	dst		出力文字列
		@param[in]	size	文字列の大きさ
		@return 生成された文字列の長さ
	*/
	//-----------------------------------------------------------------//
	int disp_time(time_t t, char* dst = nullptr, uint32_t size = 0);

	//-----------------------------------------------------------------//
	/*!
		@brief  設定スイッチの状態を取得
		@return 設定スイッチの状態
	*/
	//-----------------------------------------------------------------//
	uint8_t get_switch()
	{
#ifdef SEEDA
		return static_cast<uint8_t>(!SW1::P()) | (static_cast<uint8_t>(!SW2::P()) << 1);
#else
		return 0;  // for only develope mode
#endif
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  A/D サンプルの参照
		@param[in]	ch	チャネル（０～７）
		@return A/D サンプル
	*/
	//-----------------------------------------------------------------//
	sample_t& at_sample(uint8_t ch);

	//-----------------------------------------------------------------//
	/*!
		@brief  A/D サンプルの取得
		@return A/D サンプル
	*/
	//-----------------------------------------------------------------//
	const sample_data& get_sample_data();

	//-----------------------------------------------------------------//
	/*!
		@brief  内臓 A/D 変換値の取得
		@param[in]	ch	チャネル（５、６、７）
		@return A/D 変換値
	*/
	//-----------------------------------------------------------------//
	uint16_t get_adc(uint32_t ch);
}

extern "C" {

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の取得
		@return GMT 時間
	*/
	//-----------------------------------------------------------------//
	time_t get_time();

};
<|endoftext|>


<commit_before>// Copyright (C) 2009, 2010 by Florent Lamiraux, Thomas Moulard, JRL.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#include <iostream>
#include <string>

#include <hpp/corbaserver/openhrp.hh>

#include <hpp/util/debug.hh>
#include <hpp/model/body.hh>
#include <hpp/model/joint.hh>
#include <hpp/model/humanoid-robot.hh>

#include <hppOpenHRP/parserOpenHRPKineoDevice.h>
#include <hppOpenHRP/parserOpenHRPKineoObstacle.h>

#include <hpp/model/urdf/parser.hh>
#include <hpp/model/srdf/parser.hh>

// CORBA stubs.
#include "common-modelloader.hh"
#include "jrl-modelloader.hh"

namespace hpp
{
  namespace corbaServer
  {
    namespace impl
    {
      // Note : this class has been created because "common.hh" and "modelloader.hh"
      // should not appear in openhrp.hh
      class InternalCorbaObject
      {
      public:
	/// Corba elements.
	CORBA::ORB_var orb;
	/// Corba elements.
	CORBA::Object_var nameService;

	// HRP2 Corba Information
	ModelInfo_var HRP2info;

	// Obstacle Corba Information
	std::vector<ModelInfo_var> obstInfoVector;

	OpenHRP* attOpenHrpClient;

	// Constructor
	InternalCorbaObject (OpenHRP* openHrpClientPtr)
	{
	  attOpenHrpClient = openHrpClientPtr;
	}

	ktStatus getModelLoader ();

	ModelLoader_var attLoader;
      };

      OpenHRP::OpenHRP (core::Planner *hpp)
      {
	hppPlanner = hpp;
	privateCorbaObject = new InternalCorbaObject(this) ;
      }

      OpenHRP::~OpenHRP()
      {}

      ktStatus
      OpenHRP::loadHrp2Model (double inPenetration,
			      const std::string& inModel)
      {
	model::HumanoidRobotShPtr HRP2Device;
	if (loadHrp2Model(HRP2Device, inModel) != KD_OK){
	  return KD_ERROR;
	}

	//
	// ADD HRP2 to the planner
	//
      }

      ktStatus
      OpenHRP::loadHrp2Model
      (model::HumanoidRobotShPtr& HRP2Device, const std::string& inModel)
      {
	model::HumanoidRobotShPtr hrp2;
	hpp::model::urdf::Parser parser;
	hpp::model::srdf::Parser srdfParser;
	hrp2 = parser.parse ("package://hrp2_14_description/urdf/hrp2-capsule.urdf",
			     "base_footprint_joint");

	HRP2Device = hrp2;
	if (!HRP2Device)
	  {
	    hppDout (error, "failed to build Kineo HRP2 Model");
	    return KD_ERROR;
	  }

	//
	// set HRP2 joints in invisible mode by default
	//
	HRP2Device->isVisible (false);

	// set Collision Check Pairs
	srdfParser.parse ("package://hrp2_14_description/urdf/hrp2-capsule.urdf",
			  "package://hrp2_14_description/srdf/hrp2-capsule.srdf",
			  hrp2);

	//
	// set HRP2 in a default configuration (HALFSITTING) ;
	//
	hpp::model::srdf::Parser::HppConfigurationType halfSittingConfig
	  = srdfParser.getHppReferenceConfig ("all", "half_sitting");

	HRP2Device->hppSetCurrentConfig (halfSittingConfig);

	return KD_OK;
      }

      ktStatus
      OpenHRP::loadRobotModel(const std::string& inFilename,
			      const std::string& inDeviceName,
			      model::DeviceShPtr &outDevice,
			      const std::string& inDirectory)
      {
	ModelLoader_var loader;
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  {
	    hppDout (error, "failed to load robot model");
	    return KD_ERROR;
	  }

	//
	// Build hppDevice from OpenHRPModel
	//
	std::string url ("file://");
	url += inDirectory;
	url += std::string ("/");
	url += inFilename;

	hppDout (info, "reading " << url);

	try
	  {
	    CparserOpenHRPKineoDevice parser(privateCorbaObject->attLoader->loadURL(url.c_str())) ;
	    model::HumanoidRobotShPtr humanoid;
	    parser.parser(humanoid) ;
	    outDevice = humanoid;
	  }
	catch (CORBA::SystemException &ex)
	  {
	    hppDout (error, "system exception (" << ex._rep_id () << ")");
	    return KD_ERROR;
	  }
	catch (...)
	  {
	    hppDout (error, "unknown exception");
	    return KD_ERROR;
	  }

	if (!outDevice)
	  {
	    hppDout (error, "failed to build Kineo Robot Model");
	    return KD_ERROR;
	  }

	//
	// set joints in invisible mode by default
	//
	outDevice->isVisible (false);
	outDevice->name (inDeviceName);
	return KD_OK;
      }

      ktStatus
      OpenHRP::loadObstacleModel (const std::string& inFilename,
				  const std::string& inObstacleName,
				  CkppKCDPolyhedronShPtr& outPolyhedron,
				  const std::string& inDirectory)
      {
	//
	// Get Corba objects containing model of Obstacles.
	//
	std::string url ("file://");
	url += inDirectory;
	url += std::string ("/");
	url += inFilename;

	if (getObstacleURL(url)!= KD_OK)
	  {
	    privateCorbaObject->orb->destroy();
	    hppDout (error, "failed to load Obstacle model");
	    return KD_ERROR;
	  }

	//
	// build obstacles (if there is some obstacle)
	//
	if (!privateCorbaObject->obstInfoVector.empty ())
	  {
	    //
	    // Build KineoObstacle from OpenHRPModel
	    //
	    CparserOpenHRPKineoObstacle parserObstacle (privateCorbaObject->obstInfoVector);

	    std::vector<CkppKCDPolyhedronShPtr> obstacleVector = parserObstacle.parser ();

	    if (obstacleVector.empty ())
	      {
		hppDout (error, "failed to parse the obstacle model");
		return KD_ERROR;
	      }
	    outPolyhedron = obstacleVector[0];
	    outPolyhedron->name (inObstacleName);
	  }
	return KD_OK;
      }

      ktStatus
      InternalCorbaObject::getModelLoader ()
      {
	// Services
	std::string modelLoaderString ("ModelLoaderJRL");
	std::string nameServiceString ("NameService");

	try
	  {
	  int argc = 1;
	  char *argv[1] = {"unused"};
	  // ORB Creation.
	  orb = CORBA::ORB_init (argc, argv);

	  // Getting reference of name server
	  try
	    {
	      nameService = orb->resolve_initial_references(nameServiceString.c_str());
	    }
	  catch (const CORBA::ORB::InvalidName&)
	    {
	      hppDout (error, "cannot resolve " << nameServiceString);
	      return KD_ERROR;
	    }
	  if (CORBA::is_nil (nameService))
	    {
	      hppDout (info, nameServiceString << "is a nil object reference");
	      return KD_ERROR;
	    }

	  // Getting root naming context
	  CosNaming::NamingContext_var cxt =
	    CosNaming::NamingContext::_narrow(nameService);
	  if (CORBA::is_nil(cxt))
	    {
	      hppDout (error, nameServiceString
		       << " is not a NamingContext object reference");
	      return KD_ERROR;
	    }

	  CosNaming::Name ncFactory;
	  ncFactory.length (1);

	  // modelloaderJRL
	  CosNaming::Name mFactory;
	  mFactory.length (1);
	  mFactory[0].id = CORBA::string_dup (modelLoaderString.c_str ());
	  mFactory[0].kind = CORBA::string_dup ("");

	  try
	    {
	      attLoader = ModelLoader::_narrow (cxt -> resolve (mFactory));
	    }
	  catch (const CosNaming::NamingContext::NotFound&)
	    {
	      hppDout (error, modelLoaderString <<  " not found");
	      return KD_ERROR;
	    }
	  }
	catch (CORBA::SystemException &ex)
	  {
	    hppDout (error, "system exception (" << ex._rep_id() << ")");
	    return KD_ERROR;
	  }
	catch (...)
	  {
	    hppDout (error, "unknown exception");
	    return KD_ERROR;
	  }
	return KD_OK;
      }

      ktStatus OpenHRP::getRobotURL (const std::string& inModel)
      {
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  return KD_ERROR;

	if(privateCorbaObject->attLoader)
	  {
	    //Get HRP2 Information
	    std::string url ("file://");
	    url += inModel;
	    privateCorbaObject->HRP2info = privateCorbaObject->attLoader->loadURL (url.c_str ());

	    hppDout (info,
		     "loaded URL: "
		     << privateCorbaObject->HRP2info->getUrl ());
	    hppDout
	      (info,
	       "loaded Model Name: "
	       << privateCorbaObject->HRP2info->getCharObject ()->name ());
	    hppDout
	      (info, "loaded Model Size: "
	       << privateCorbaObject->HRP2info->getCharObject ()->modelObjectSeq ()->length ());
	}
	return KD_OK;
      }

      ktStatus OpenHRP::getObstacleURL (const std::string& inFilename)
      {
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  return KD_ERROR;
	if(privateCorbaObject->attLoader)
	  {
	    try
	      {
		privateCorbaObject->obstInfoVector.push_back
		  (privateCorbaObject->attLoader->loadURL (inFilename.c_str ()));

		hppDout (info, "vector Obstacle " << 0);
		hppDout (info, "loaded URL: "
			 << privateCorbaObject->obstInfoVector[0]->getUrl ());
		hppDout
		  (info, "loaded Model Name: "
		   << privateCorbaObject->obstInfoVector[0]->getCharObject ()->name ());
		hppDout
		  (info, "loaded Model Size: "
		   << privateCorbaObject->obstInfoVector[0]->getCharObject ()->modelObjectSeq ()->length ());
	      }
	    catch (ModelLoader::ModelLoaderException& exception)
	      {
		hppDout (error, "failed to open obstacle file");
		return KD_ERROR;
	      }
	  }
	return KD_OK;
      }

    } // end of namespace implementation.
  } // end of namespace corbaServer.
} // end of namespace hpp.
<commit_msg>Update HRP-2 capsule model loader.<commit_after>// Copyright (C) 2009, 2010 by Florent Lamiraux, Thomas Moulard, JRL.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#include <iostream>
#include <string>

#include <hpp/corbaserver/openhrp.hh>

#include <hpp/util/debug.hh>
#include <hpp/model/body.hh>
#include <hpp/model/joint.hh>
#include <hpp/model/humanoid-robot.hh>

#include <hppOpenHRP/parserOpenHRPKineoDevice.h>
#include <hppOpenHRP/parserOpenHRPKineoObstacle.h>

#include <hpp/model/urdf/parser.hh>
#include <hpp/model/srdf/parser.hh>
#include <hpp/model/rcpdf/parser.hh>

// CORBA stubs.
#include "common-modelloader.hh"
#include "jrl-modelloader.hh"

namespace hpp
{
  namespace corbaServer
  {
    namespace impl
    {
      // Note : this class has been created because "common.hh" and "modelloader.hh"
      // should not appear in openhrp.hh
      class InternalCorbaObject
      {
      public:
	/// Corba elements.
	CORBA::ORB_var orb;
	/// Corba elements.
	CORBA::Object_var nameService;

	// HRP2 Corba Information
	ModelInfo_var HRP2info;

	// Obstacle Corba Information
	std::vector<ModelInfo_var> obstInfoVector;

	OpenHRP* attOpenHrpClient;

	// Constructor
	InternalCorbaObject (OpenHRP* openHrpClientPtr)
	{
	  attOpenHrpClient = openHrpClientPtr;
	}

	ktStatus getModelLoader ();

	ModelLoader_var attLoader;
      };

      OpenHRP::OpenHRP (core::Planner *hpp)
      {
	hppPlanner = hpp;
	privateCorbaObject = new InternalCorbaObject(this) ;
      }

      OpenHRP::~OpenHRP()
      {}

      ktStatus
      OpenHRP::loadHrp2Model (double inPenetration,
			      const std::string& inModel)
      {
	model::HumanoidRobotShPtr HRP2Device;
	if (loadHrp2Model(HRP2Device, inModel) != KD_OK){
	  return KD_ERROR;
	}

	//
	// ADD HRP2 to the planner
	//
      }

      ktStatus
      OpenHRP::loadHrp2Model
      (model::HumanoidRobotShPtr& HRP2Device, const std::string& inModel)
      {
	model::HumanoidRobotShPtr hrp2;
	hpp::model::urdf::Parser parser;
	hpp::model::srdf::Parser srdfParser;
	hpp::model::rcpdf::Parser rcpdfParser;
	hrp2 = parser.parse ("package://hrp2_14_description/urdf/hrp2_capsule.urdf");

	HRP2Device = hrp2;
	if (!HRP2Device)
	  {
	    hppDout (error, "failed to build Kineo HRP2 Model");
	    return KD_ERROR;
	  }

	//
	// set HRP2 joints in invisible mode by default
	//
	HRP2Device->isVisible (false);

	// set Collision Check Pairs
	srdfParser.parse ("package://hrp2_14_description/urdf/hrp2_capsule.urdf",
			  "package://hrp2_14_description/srdf/hrp2_capsule.srdf",
			  hrp2);

	//
	// set HRP2 in a default configuration (HALFSITTING) ;
	//
	hpp::model::srdf::Parser::HppConfigurationType halfSittingConfig
	  = srdfParser.getHppReferenceConfig ("all", "half_sitting");

	HRP2Device->hppSetCurrentConfig (halfSittingConfig);

	// Parse contact points to set foot size.
	rcpdfParser.parse ("package://hrp2_14_description/rcpdf/hrp2.rcpdf",
			   hrp2);

	return KD_OK;
      }

      ktStatus
      OpenHRP::loadRobotModel(const std::string& inFilename,
			      const std::string& inDeviceName,
			      model::DeviceShPtr &outDevice,
			      const std::string& inDirectory)
      {
	ModelLoader_var loader;
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  {
	    hppDout (error, "failed to load robot model");
	    return KD_ERROR;
	  }

	//
	// Build hppDevice from OpenHRPModel
	//
	std::string url ("file://");
	url += inDirectory;
	url += std::string ("/");
	url += inFilename;

	hppDout (info, "reading " << url);

	try
	  {
	    CparserOpenHRPKineoDevice parser(privateCorbaObject->attLoader->loadURL(url.c_str())) ;
	    model::HumanoidRobotShPtr humanoid;
	    parser.parser(humanoid) ;
	    outDevice = humanoid;
	  }
	catch (CORBA::SystemException &ex)
	  {
	    hppDout (error, "system exception (" << ex._rep_id () << ")");
	    return KD_ERROR;
	  }
	catch (...)
	  {
	    hppDout (error, "unknown exception");
	    return KD_ERROR;
	  }

	if (!outDevice)
	  {
	    hppDout (error, "failed to build Kineo Robot Model");
	    return KD_ERROR;
	  }

	//
	// set joints in invisible mode by default
	//
	outDevice->isVisible (false);
	outDevice->name (inDeviceName);
	return KD_OK;
      }

      ktStatus
      OpenHRP::loadObstacleModel (const std::string& inFilename,
				  const std::string& inObstacleName,
				  CkppKCDPolyhedronShPtr& outPolyhedron,
				  const std::string& inDirectory)
      {
	//
	// Get Corba objects containing model of Obstacles.
	//
	std::string url ("file://");
	url += inDirectory;
	url += std::string ("/");
	url += inFilename;

	if (getObstacleURL(url)!= KD_OK)
	  {
	    privateCorbaObject->orb->destroy();
	    hppDout (error, "failed to load Obstacle model");
	    return KD_ERROR;
	  }

	//
	// build obstacles (if there is some obstacle)
	//
	if (!privateCorbaObject->obstInfoVector.empty ())
	  {
	    //
	    // Build KineoObstacle from OpenHRPModel
	    //
	    CparserOpenHRPKineoObstacle parserObstacle (privateCorbaObject->obstInfoVector);

	    std::vector<CkppKCDPolyhedronShPtr> obstacleVector = parserObstacle.parser ();

	    if (obstacleVector.empty ())
	      {
		hppDout (error, "failed to parse the obstacle model");
		return KD_ERROR;
	      }
	    outPolyhedron = obstacleVector[0];
	    outPolyhedron->name (inObstacleName);
	  }
	return KD_OK;
      }

      ktStatus
      InternalCorbaObject::getModelLoader ()
      {
	// Services
	std::string modelLoaderString ("ModelLoaderJRL");
	std::string nameServiceString ("NameService");

	try
	  {
	  int argc = 1;
	  char *argv[1] = {"unused"};
	  // ORB Creation.
	  orb = CORBA::ORB_init (argc, argv);

	  // Getting reference of name server
	  try
	    {
	      nameService = orb->resolve_initial_references(nameServiceString.c_str());
	    }
	  catch (const CORBA::ORB::InvalidName&)
	    {
	      hppDout (error, "cannot resolve " << nameServiceString);
	      return KD_ERROR;
	    }
	  if (CORBA::is_nil (nameService))
	    {
	      hppDout (info, nameServiceString << "is a nil object reference");
	      return KD_ERROR;
	    }

	  // Getting root naming context
	  CosNaming::NamingContext_var cxt =
	    CosNaming::NamingContext::_narrow(nameService);
	  if (CORBA::is_nil(cxt))
	    {
	      hppDout (error, nameServiceString
		       << " is not a NamingContext object reference");
	      return KD_ERROR;
	    }

	  CosNaming::Name ncFactory;
	  ncFactory.length (1);

	  // modelloaderJRL
	  CosNaming::Name mFactory;
	  mFactory.length (1);
	  mFactory[0].id = CORBA::string_dup (modelLoaderString.c_str ());
	  mFactory[0].kind = CORBA::string_dup ("");

	  try
	    {
	      attLoader = ModelLoader::_narrow (cxt -> resolve (mFactory));
	    }
	  catch (const CosNaming::NamingContext::NotFound&)
	    {
	      hppDout (error, modelLoaderString <<  " not found");
	      return KD_ERROR;
	    }
	  }
	catch (CORBA::SystemException &ex)
	  {
	    hppDout (error, "system exception (" << ex._rep_id() << ")");
	    return KD_ERROR;
	  }
	catch (...)
	  {
	    hppDout (error, "unknown exception");
	    return KD_ERROR;
	  }
	return KD_OK;
      }

      ktStatus OpenHRP::getRobotURL (const std::string& inModel)
      {
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  return KD_ERROR;

	if(privateCorbaObject->attLoader)
	  {
	    //Get HRP2 Information
	    std::string url ("file://");
	    url += inModel;
	    privateCorbaObject->HRP2info = privateCorbaObject->attLoader->loadURL (url.c_str ());

	    hppDout (info,
		     "loaded URL: "
		     << privateCorbaObject->HRP2info->getUrl ());
	    hppDout
	      (info,
	       "loaded Model Name: "
	       << privateCorbaObject->HRP2info->getCharObject ()->name ());
	    hppDout
	      (info, "loaded Model Size: "
	       << privateCorbaObject->HRP2info->getCharObject ()->modelObjectSeq ()->length ());
	}
	return KD_OK;
      }

      ktStatus OpenHRP::getObstacleURL (const std::string& inFilename)
      {
	if (privateCorbaObject->getModelLoader() != KD_OK)
	  return KD_ERROR;
	if(privateCorbaObject->attLoader)
	  {
	    try
	      {
		privateCorbaObject->obstInfoVector.push_back
		  (privateCorbaObject->attLoader->loadURL (inFilename.c_str ()));

		hppDout (info, "vector Obstacle " << 0);
		hppDout (info, "loaded URL: "
			 << privateCorbaObject->obstInfoVector[0]->getUrl ());
		hppDout
		  (info, "loaded Model Name: "
		   << privateCorbaObject->obstInfoVector[0]->getCharObject ()->name ());
		hppDout
		  (info, "loaded Model Size: "
		   << privateCorbaObject->obstInfoVector[0]->getCharObject ()->modelObjectSeq ()->length ());
	      }
	    catch (ModelLoader::ModelLoaderException& exception)
	      {
		hppDout (error, "failed to open obstacle file");
		return KD_ERROR;
	      }
	  }
	return KD_OK;
      }

    } // end of namespace implementation.
  } // end of namespace corbaServer.
} // end of namespace hpp.
<|endoftext|>


<commit_before>/*
 *  The driver for braingrid.
 *  The driver performs the following steps:
 *  1) reads parameters from an xml file (specified as the first argument)
 *  2) creates the network
 *  3) launches the simulation
 *
 *  @authors Allan Ortiz and Cory Mayberry.
 */

#include <fstream>
#include "Global.h"
#include "../paramcontainer/ParamContainer.h"

#include "IModel.h"
#include "FClassOfCategory.h"
#include "IRecorder.h"
#include "FSInput.h"
#include "Simulator.h"

// Uncomment to use visual leak detector (Visual Studios Plugin)
// #include <vld.h>

#if defined(USE_GPU)
    #include "GPUSpikingModel.h"
#elif defined(USE_OMP)
//    #include "MultiThreadedSim.h"
#else
    #include "SingleThreadedSpikingModel.h"
#endif

using namespace std;

// functions
bool LoadAllParameters(SimulationInfo *simInfo);
void printParams(SimulationInfo *simInfo);
bool parseCommandLine(int argc, char* argv[], SimulationInfo *simInfo);
bool createAllModelClassInstances(TiXmlDocument* simDoc, SimulationInfo *simInfo);

/*
 *  Main for Simulator. Handles command line arguments and loads parameters
 *  from parameter file. All initial loading before running simulator in Network
 *  is here.
 *
 *  @param  argc    argument count.
 *  @param  argv    arguments.
 *  @return -1 if error, else if success.
 */
int main(int argc, char* argv[]) {
    SimulationInfo *simInfo = NULL;    // simulation information
    Simulator *simulator = NULL;       // Simulator object

    // create simulation info object
    simInfo = new SimulationInfo();

    // Handles parsing of the command line
    if (!parseCommandLine(argc, argv, simInfo)) {
        cerr << "! ERROR: failed during command line parse" << endl;
        return -1;
    }

    // Create all model instances and load parameters from a file.
    if (!LoadAllParameters(simInfo)) {
        cerr << "! ERROR: failed while parsing simulation parameters." << endl;
        return -1;
    }

    // create & init simulation recorder
    simInfo->simRecorder = simInfo->model->getConnections()->createRecorder(simInfo);
    if (simInfo->simRecorder == NULL) {
        cerr << "! ERROR: invalid state output file name extension." << endl;
        return -1;
    }

    // Create a stimulus input object
    simInfo->pInput = FSInput::get()->CreateInstance(simInfo);

    time_t start_time, end_time;
    time(&start_time);

    // create the simulator
    simulator = new Simulator();

    // setup simulation
    DEBUG(cout << "Setup simulation." << endl;);
    simulator->setup(simInfo);

    // Deserializes internal state from a prior run of the simulation
    if (!simInfo->memInputFileName.empty()) {
        ifstream memory_in;
        memory_in.open(simInfo->memInputFileName.c_str(), ofstream::binary | ofstream::in);
        simulator->deserialize(memory_in, simInfo);
        memory_in.close();
    }

    // Run simulation
    simulator->simulate(simInfo);

    // Terminate the stimulus input
    if (simInfo->pInput != NULL)
    {
        simInfo->pInput->term(simInfo);
        delete simInfo->pInput;
    }

    // Writes simulation results to an output destination
    simulator->saveData(simInfo);

    // Serializes internal state for the current simulation
    ofstream memory_out;
    if (!simInfo->memOutputFileName.empty()) {
        memory_out.open(simInfo->memOutputFileName.c_str(),ofstream::binary | ofstream::trunc);
        simulator->serialize(memory_out, simInfo);
        memory_out.close();
    }

    // Tell simulation to clean-up and run any post-simulation logic.
    simulator->finish(simInfo);

    // terminates the simulation recorder
    if (simInfo->simRecorder != NULL) {
        simInfo->simRecorder->term();
    }

    for(unsigned int i = 0; i < rgNormrnd.size(); ++i) {
        delete rgNormrnd[i];
    }

    rgNormrnd.clear();

    time(&end_time);
    double time_elapsed = difftime(end_time, start_time);
    double ssps = simInfo->epochDuration * simInfo->maxSteps / time_elapsed;
    cout << "time simulated: " << simInfo->epochDuration * simInfo->maxSteps << endl;
    cout << "time elapsed: " << time_elapsed << endl;
    cout << "ssps (simulation seconds / real time seconds): " << ssps << endl;

    delete simInfo->model;
    simInfo->model = NULL;

    if (simInfo->simRecorder != NULL) {
        delete simInfo->simRecorder;
        simInfo->simRecorder = NULL;
    }

    delete simInfo;
    simInfo = NULL;

    delete simulator;
    simulator = NULL;

    return 0;
}

/*
 *  Create instances of all model classes.
 *
 *  @param  simDoc  the TiXmlDocument to read from.
 *  @param  simInfo   SimulationInfo class to read information from.
 *  @retrun true if successful, false if not
 */
bool createAllModelClassInstances(TiXmlDocument* simDoc, SimulationInfo *simInfo)
{
    TiXmlElement* parms = NULL;

    if ((parms = simDoc->FirstChildElement("ModelParams")) == NULL) {
        cerr << "Could not find <MoelParms> in simulation parameter file " << endl;
        return false;
    }

    // create neurons, synapses, connections, and layout objects specified in the description file
    IAllNeurons *neurons = NULL;
    IAllSynapses *synapses = NULL;
    Connections *conns = NULL;
    Layout *layout = NULL;
    const TiXmlNode* pNode = NULL;

    while ((pNode = parms->IterateChildren(pNode)) != NULL) {
        if (strcmp(pNode->Value(), "NeuronsParams") == 0) {
            neurons = FClassOfCategory::get()->createNeurons(pNode);
        } else if (strcmp(pNode->Value(), "SynapsesParams") == 0) {
            synapses = FClassOfCategory::get()->createSynapses(pNode);
        } else if (strcmp(pNode->Value(), "ConnectionsParams") == 0) {
            conns = FClassOfCategory::get()->createConnections(pNode);
        } else if (strcmp(pNode->Value(), "LayoutParams") == 0) {
            layout = FClassOfCategory::get()->createLayout(pNode);
        }
    }

    if (neurons == NULL || synapses == NULL || conns == NULL || layout == NULL) {
        cerr << "!ERROR: failed to create classes" << endl;
        return false;
    }

    // create the model
    #if defined(USE_GPU)
         simInfo->model = new GPUSpikingModel(conns, neurons, synapses, layout);
    #else
         simInfo->model = new SingleThreadedSpikingModel(conns, neurons, synapses, layout);
    #endif

    return true;
}

/*
 *  Load parameters from a file.
 *
 *  @param  simInfo   SimulationInfo class to read information from.
 *  @return true if successful, false if not
 */
bool LoadAllParameters(SimulationInfo *simInfo)
{
    DEBUG(cout << "reading parameters from xml file" << endl;)

    TiXmlDocument simDoc(simInfo->stateInputFileName.c_str());
    if (!simDoc.LoadFile()) {
        cerr << "Failed loading simulation parameter file "
             << simInfo->stateInputFileName << ":" << "\n\t" << simDoc.ErrorDesc()
             << endl;
        cerr << " error: " << simDoc.ErrorRow() << ", " << simDoc.ErrorCol()
             << endl;
        return false;
    }

    // load simulation parameters
    if (simInfo->readParameters(&simDoc) != true) {
        return false;
    }

    // create instances of all model classes
    DEBUG(cout << "creating instances of all classes" << endl;)
    if (createAllModelClassInstances(&simDoc, simInfo) != true) {
        return false;
    }

    // load parameters for all models
    if (FClassOfCategory::get()->readParameters(&simDoc) != true) {
        return false;
    }

    if (simInfo->stateOutputFileName.empty()) {
        cerr << "! ERROR: no stateOutputFileName is specified." << endl;
        return -1;
    }

    /*    verify that params were read correctly */
    DEBUG(printParams(simInfo);)

    return true;
}

/*
 *  Prints loaded parameters out to console.
 *
 *  @param  simInfo   SimulationInfo class to read information from.
 */
void printParams(SimulationInfo *simInfo) {
    cout << "\nPrinting simulation parameters...\n";
    simInfo->printParameters(cout);

    cout << "Model Parameters:" << endl;
    FClassOfCategory::get()->printParameters(cout);
    cout << "Done printing parameters" << endl;
}

/*
 *  Handles parsing of the command line
 *
 *  @param  argc      argument count.
 *  @param  argv      arguments.
 *  @param  simInfo   SimulationInfo class to read information from.
 *  @returns    true if successful, false otherwise.
 */
bool parseCommandLine(int argc, char* argv[], SimulationInfo *simInfo)
{
    ParamContainer cl;
    cl.initOptions(false);  // don't allow unknown parameters
    cl.setHelpString(string("The DCT growth modeling simulator\nUsage: ") + argv[0] + " ");

#if defined(USE_GPU)
    if ((cl.addParam("stateoutfile", 'o', ParamContainer::filename, "simulation state output filename") != ParamContainer::errOk)
            || (cl.addParam("stateinfile", 't', ParamContainer::filename | ParamContainer::required, "simulation state input filename") != ParamContainer::errOk)
            || (cl.addParam("deviceid", 'd', ParamContainer::regular, "CUDA device id") != ParamContainer::errOk)
            || (cl.addParam( "stiminfile", 's', ParamContainer::filename, "stimulus input file" ) != ParamContainer::errOk)
            || (cl.addParam("meminfile", 'r', ParamContainer::filename, "simulation memory image input filename") != ParamContainer::errOk)
            || (cl.addParam("memoutfile", 'w', ParamContainer::filename, "simulation memory image output filename") != ParamContainer::errOk)) {
        cerr << "Internal error creating command line parser" << endl;
        return false;
    }
#else    // !USE_GPU
    if ((cl.addParam("stateoutfile", 'o', ParamContainer::filename, "simulation state output filename") != ParamContainer::errOk)
            || (cl.addParam("stateinfile", 't', ParamContainer::filename | ParamContainer::required, "simulation state input filename") != ParamContainer::errOk)
            || (cl.addParam( "stiminfile", 's', ParamContainer::filename, "stimulus input file" ) != ParamContainer::errOk)
            || (cl.addParam("meminfile", 'r', ParamContainer::filename, "simulation memory image filename") != ParamContainer::errOk)
            || (cl.addParam("memoutfile", 'w', ParamContainer::filename, "simulation memory image output filename") != ParamContainer::errOk)) {
        cerr << "Internal error creating command line parser" << endl;
        return false;
    }
#endif  // USE_GPU

    // Parse the command line
    if (cl.parseCommandLine(argc, argv) != ParamContainer::errOk) {
        cl.dumpHelp(stderr, true, 78);
        return false;
    }

    // Get the values
    simInfo->stateOutputFileName = cl["stateoutfile"];
    simInfo->stateInputFileName = cl["stateinfile"];
    simInfo->memInputFileName = cl["meminfile"];
    simInfo->memOutputFileName = cl["memoutfile"];
    simInfo->stimulusInputFileName = cl["stiminfile"];

#if defined(USE_GPU)
    if (EOF == sscanf(cl["deviceid"].c_str(), "%d", &g_deviceId)) {
        g_deviceId = 0;
    }
#endif  // USE_GPU

    return true;
}
<commit_msg>Removed extraneous BGDriver.cpp<commit_after><|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2016, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once
#pragma once
#include <kernel_headers/csrmm.hpp>
#include <program.hpp>
#include <traits.hpp>
#include <string>
#include <mutex>
#include <map>
#include <dispatch.hpp>
#include <Param.hpp>
#include <debug_opencl.hpp>
#include <cache.hpp>
#include <type_util.hpp>
#include "scan_dim.hpp"
#include "reduce.hpp"
#include "scan_first.hpp"
#include "config.hpp"

using cl::Buffer;
using cl::Program;
using cl::Kernel;
using cl::KernelFunctor;
using cl::EnqueueArgs;
using cl::NDRange;
using std::string;

namespace opencl
{
    namespace kernel
    {
        static const int MAX_CSRMM_GROUPS = 4096;
        template<typename T>
        void csrmm_nt(Param out,
                      const Param &values, const Param &rowIdx, const Param &colIdx,
                      const Param &rhs, const T alpha, const T beta)
        {
            try {
                bool use_alpha = (alpha != scalar<T>(1.0));
                bool use_beta = (beta != scalar<T>(0.0));

                // Using greedy indexing is causing performance issues on many platforms
                // FIXME: Figure out why
                bool use_greedy = false;

                std::string ref_name =
                    std::string("csrmm_") +
                    std::string(dtype_traits<T>::getName()) +
                    std::string("_") +
                    std::to_string(use_alpha) +
                    std::string("_") +
                    std::to_string(use_beta) +
                    std::string("_") +
                    std::to_string(use_greedy);

                int device = getActiveDeviceId();
                auto idx = kernelCaches[device].find(ref_name);
                kc_entry_t entry;

                if (idx == kernelCaches[device].end()) {

                    std::ostringstream options;
                    options << " -D T=" << dtype_traits<T>::getName();
                    options << " -D USE_ALPHA=" << use_alpha;
                    options << " -D USE_BETA=" << use_beta;
                    options << " -D USE_GREEDY=" << use_greedy;
                    options << " -D THREADS_PER_GROUP=" << THREADS_PER_GROUP;

                    if (std::is_same<T, double>::value ||
                        std::is_same<T, cdouble>::value) {
                        options << " -D USE_DOUBLE";
                    }
                    if (std::is_same<T, cfloat>::value ||
                        std::is_same<T, cdouble>::value) {
                        options << " -D IS_CPLX=1";
                    } else {
                        options << " -D IS_CPLX=0";
                    }

                    const char *ker_strs[] = {csrmm_cl};
                    const int   ker_lens[] = {csrmm_cl_len};

                    Program prog;
                    buildProgram(prog, 1, ker_strs, ker_lens, options.str());
                    entry.prog = new Program(prog);
                    entry.ker  = new Kernel[2];
                    entry.ker[0] = Kernel(*entry.prog, "csrmm_nt");
                    // FIXME: Change this after adding another kernel
                    entry.ker[1] = Kernel(*entry.prog, "csrmm_nt");
                } else {
                    entry = idx->second;
                }

                auto csrmm_nt_kernel = entry.ker[0];
                auto csrmm_nt_func = KernelFunctor<Buffer,
                                                   Buffer, Buffer, Buffer,
                                                   int, int,
                                                   Buffer, KParam, T, T, Buffer>(csrmm_nt_kernel);
                NDRange local(THREADS_PER_GROUP, 1);
                int M = rowIdx.info.dims[0] - 1;
                int N = rhs.info.dims[0];

                int groups_x = divup(N, local[0]);
                int groups_y = divup(M, REPEAT);
                groups_y = std::min(groups_y, MAX_CSRMM_GROUPS);
                NDRange global(local[0] * groups_x, local[1] * groups_y);

                std::vector<int> count(groups_x);
                cl::Buffer *counter = bufferAlloc(count.size() * sizeof(int));
                getQueue().enqueueWriteBuffer(*counter, CL_TRUE,
                                              0,
                                              count.size() * sizeof(int),
                                              (void *)count.data());

                csrmm_nt_func(EnqueueArgs(getQueue(), global, local),
                              *out.data, *values.data, *rowIdx.data, *colIdx.data,
                              M, N, *rhs.data, rhs.info, alpha, beta, *counter);

                bufferFree(counter);
            } catch (cl::Error &ex) {
                CL_TO_AF_ERROR(ex);
            }
        }
    }
}
<commit_msg>OPENCL: Fixing csrmm_nt to cache using proper tag<commit_after>/*******************************************************
 * Copyright (c) 2016, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once
#pragma once
#include <kernel_headers/csrmm.hpp>
#include <program.hpp>
#include <traits.hpp>
#include <string>
#include <mutex>
#include <map>
#include <dispatch.hpp>
#include <Param.hpp>
#include <debug_opencl.hpp>
#include <cache.hpp>
#include <type_util.hpp>
#include "scan_dim.hpp"
#include "reduce.hpp"
#include "scan_first.hpp"
#include "config.hpp"

using cl::Buffer;
using cl::Program;
using cl::Kernel;
using cl::KernelFunctor;
using cl::EnqueueArgs;
using cl::NDRange;
using std::string;

namespace opencl
{
    namespace kernel
    {
        static const int MAX_CSRMM_GROUPS = 4096;
        template<typename T>
        void csrmm_nt(Param out,
                      const Param &values, const Param &rowIdx, const Param &colIdx,
                      const Param &rhs, const T alpha, const T beta)
        {
            try {
                bool use_alpha = (alpha != scalar<T>(1.0));
                bool use_beta = (beta != scalar<T>(0.0));

                // Using greedy indexing is causing performance issues on many platforms
                // FIXME: Figure out why
                bool use_greedy = false;

                std::string ref_name =
                    std::string("csrmm_nt_") +
                    std::string(dtype_traits<T>::getName()) +
                    std::string("_") +
                    std::to_string(use_alpha) +
                    std::string("_") +
                    std::to_string(use_beta) +
                    std::string("_") +
                    std::to_string(use_greedy);

                int device = getActiveDeviceId();
                auto idx = kernelCaches[device].find(ref_name);
                kc_entry_t entry;

                if (idx == kernelCaches[device].end()) {

                    std::ostringstream options;
                    options << " -D T=" << dtype_traits<T>::getName();
                    options << " -D USE_ALPHA=" << use_alpha;
                    options << " -D USE_BETA=" << use_beta;
                    options << " -D USE_GREEDY=" << use_greedy;
                    options << " -D THREADS_PER_GROUP=" << THREADS_PER_GROUP;

                    if (std::is_same<T, double>::value ||
                        std::is_same<T, cdouble>::value) {
                        options << " -D USE_DOUBLE";
                    }
                    if (std::is_same<T, cfloat>::value ||
                        std::is_same<T, cdouble>::value) {
                        options << " -D IS_CPLX=1";
                    } else {
                        options << " -D IS_CPLX=0";
                    }

                    const char *ker_strs[] = {csrmm_cl};
                    const int   ker_lens[] = {csrmm_cl_len};

                    Program prog;
                    buildProgram(prog, 1, ker_strs, ker_lens, options.str());
                    entry.prog = new Program(prog);
                    entry.ker  = new Kernel[2];
                    entry.ker[0] = Kernel(*entry.prog, "csrmm_nt");
                    // FIXME: Change this after adding another kernel
                    entry.ker[1] = Kernel(*entry.prog, "csrmm_nt");
                } else {
                    entry = idx->second;
                }

                auto csrmm_nt_kernel = entry.ker[0];
                auto csrmm_nt_func = KernelFunctor<Buffer,
                                                   Buffer, Buffer, Buffer,
                                                   int, int,
                                                   Buffer, KParam, T, T, Buffer>(csrmm_nt_kernel);
                NDRange local(THREADS_PER_GROUP, 1);
                int M = rowIdx.info.dims[0] - 1;
                int N = rhs.info.dims[0];

                int groups_x = divup(N, local[0]);
                int groups_y = divup(M, REPEAT);
                groups_y = std::min(groups_y, MAX_CSRMM_GROUPS);
                NDRange global(local[0] * groups_x, local[1] * groups_y);

                std::vector<int> count(groups_x);
                cl::Buffer *counter = bufferAlloc(count.size() * sizeof(int));
                getQueue().enqueueWriteBuffer(*counter, CL_TRUE,
                                              0,
                                              count.size() * sizeof(int),
                                              (void *)count.data());

                csrmm_nt_func(EnqueueArgs(getQueue(), global, local),
                              *out.data, *values.data, *rowIdx.data, *colIdx.data,
                              M, N, *rhs.data, rhs.info, alpha, beta, *counter);

                bufferFree(counter);
            } catch (cl::Error &ex) {
                CL_TO_AF_ERROR(ex);
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *
 *  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 "log.h"
#include "nextpnr.h"

#if 0
#define dbg(...) log(__VA_ARGS__)
#else
#define dbg(...)
#endif

USING_NEXTPNR_NAMESPACE

namespace {

void archcheck_names(const Context *ctx)
{
    log_info("Checking entity names.\n");

    log_info("Checking bel names..\n");
    for (BelId bel : ctx->getBels()) {
        IdStringList name = ctx->getBelName(bel);
        BelId bel2 = ctx->getBelByName(name);
        if (bel != bel2) {
            log_error("bel != bel2, name = %s\n", ctx->nameOfBel(bel));
        }
    }

    log_info("Checking wire names..\n");
    for (WireId wire : ctx->getWires()) {
        IdStringList name = ctx->getWireName(wire);
        WireId wire2 = ctx->getWireByName(name);
        if (wire != wire2) {
            log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire));
        }
    }

    log_info("Checking bucket names..\n");
    for (BelBucketId bucket : ctx->getBelBuckets()) {
        IdString name = ctx->getBelBucketName(bucket);
        BelBucketId bucket2 = ctx->getBelBucketByName(name);
        if (bucket != bucket2) {
            log_error("bucket != bucket2, name = %s\n", name.c_str(ctx));
        }
    }

#ifndef ARCH_ECP5
    log_info("Checking pip names..\n");
    for (PipId pip : ctx->getPips()) {
        IdStringList name = ctx->getPipName(pip);
        PipId pip2 = ctx->getPipByName(name);
        if (pip != pip2) {
            log_error("pip != pip2, name = %s\n", ctx->nameOfPip(pip));
        }
    }
#endif
    log_break();
}

void archcheck_locs(const Context *ctx)
{
    log_info("Checking location data.\n");

    log_info("Checking all bels..\n");
    for (BelId bel : ctx->getBels()) {
        log_assert(bel != BelId());
        dbg("> %s\n", ctx->getBelName(bel).c_str(ctx));

        Loc loc = ctx->getBelLocation(bel);
        dbg("   ... %d %d %d\n", loc.x, loc.y, loc.z);

        log_assert(0 <= loc.x);
        log_assert(0 <= loc.y);
        log_assert(0 <= loc.z);
        log_assert(loc.x < ctx->getGridDimX());
        log_assert(loc.y < ctx->getGridDimY());
        log_assert(loc.z < ctx->getTileBelDimZ(loc.x, loc.y));

        BelId bel2 = ctx->getBelByLocation(loc);
        dbg("   ... %s\n", ctx->getBelName(bel2).c_str(ctx));
        log_assert(bel == bel2);
    }

    log_info("Checking all locations..\n");
    for (int x = 0; x < ctx->getGridDimX(); x++)
        for (int y = 0; y < ctx->getGridDimY(); y++) {
            dbg("> %d %d\n", x, y);
            std::unordered_set<int> usedz;

            for (int z = 0; z < ctx->getTileBelDimZ(x, y); z++) {
                BelId bel = ctx->getBelByLocation(Loc(x, y, z));
                if (bel == BelId())
                    continue;
                Loc loc = ctx->getBelLocation(bel);
                dbg("   + %d %s\n", z, ctx->nameOfBel(bel));
                log_assert(x == loc.x);
                log_assert(y == loc.y);
                log_assert(z == loc.z);
                usedz.insert(z);
            }

            for (BelId bel : ctx->getBelsByTile(x, y)) {
                Loc loc = ctx->getBelLocation(bel);
                dbg("   - %d %s\n", loc.z, ctx->nameOfBel(bel));
                log_assert(x == loc.x);
                log_assert(y == loc.y);
                log_assert(usedz.count(loc.z));
                usedz.erase(loc.z);
            }

            log_assert(usedz.empty());
        }

    log_break();
}

// Implements a LRU cache for pip to wire via getPipsDownhill/getPipsUphill.
//
// This allows a fast way to check getPipsDownhill/getPipsUphill from getPips,
// without balloning memory usage.
struct LruWireCacheMap
{
    LruWireCacheMap(const Context *ctx, size_t cache_size) : ctx(ctx), cache_size(cache_size)
    {
        cache_hits = 0;
        cache_misses = 0;
        cache_evictions = 0;
    }

    const Context *ctx;
    size_t cache_size;

    // Cache stats for checking on cache behavior.
    size_t cache_hits;
    size_t cache_misses;
    size_t cache_evictions;

    // Most recent accessed wires are added to the back of the list, front of
    // list is oldest wire in cache.
    std::list<WireId> last_access_list;
    // Quick wire -> list element lookup.
    std::unordered_map<WireId, std::list<WireId>::iterator> last_access_map;

    std::unordered_map<PipId, WireId> pips_downhill;
    std::unordered_map<PipId, WireId> pips_uphill;

    void removeWireFromCache(WireId wire_to_remove)
    {
        for (PipId pip : ctx->getPipsDownhill(wire_to_remove)) {
            log_assert(pips_downhill.erase(pip) == 1);
        }

        for (PipId pip : ctx->getPipsUphill(wire_to_remove)) {
            log_assert(pips_uphill.erase(pip) == 1);
        }
    }

    void addWireToCache(WireId wire)
    {
        for (PipId pip : ctx->getPipsDownhill(wire)) {
            auto result = pips_downhill.emplace(pip, wire);
            log_assert(result.second);
        }

        for (PipId pip : ctx->getPipsUphill(wire)) {
            auto result = pips_uphill.emplace(pip, wire);
            log_assert(result.second);
        }
    }

    void populateCache(WireId wire)
    {
        // Put this wire at the end of last_access_list.
        auto iter = last_access_list.emplace(last_access_list.end(), wire);
        last_access_map.emplace(wire, iter);

        if (last_access_list.size() > cache_size) {
            // Cache is full, remove front of last_access_list.
            cache_evictions += 1;
            WireId wire_to_remove = last_access_list.front();
            last_access_list.pop_front();
            log_assert(last_access_map.erase(wire_to_remove) == 1);

            removeWireFromCache(wire_to_remove);
        }

        addWireToCache(wire);
    }

    // Determine if wire is in the cache.  If wire is not in the cache,
    // adds the wire to the cache, and potentially evicts the oldest wire if
    // cache is now full.
    void checkCache(WireId wire)
    {
        auto iter = last_access_map.find(wire);
        if (iter == last_access_map.end()) {
            cache_misses += 1;
            populateCache(wire);
        } else {
            // Record that this wire has been accessed.
            cache_hits += 1;
            last_access_list.splice(last_access_list.end(), last_access_list, iter->second);
        }
    }

    // Returns true if pip is uphill of wire (e.g. pip in getPipsUphill(wire)).
    bool isPipUphill(PipId pip, WireId wire)
    {
        checkCache(wire);
        return pips_uphill.at(pip) == wire;
    }

    // Returns true if pip is downhill of wire (e.g. pip in getPipsDownhill(wire)).
    bool isPipDownhill(PipId pip, WireId wire)
    {
        checkCache(wire);
        return pips_downhill.at(pip) == wire;
    }

    void cache_info() const
    {
        log_info("Cache hits: %zu\n", cache_hits);
        log_info("Cache misses: %zu\n", cache_misses);
        log_info("Cache evictions: %zu\n", cache_evictions);
    }
};

void archcheck_conn(const Context *ctx)
{
    log_info("Checking connectivity data.\n");

    log_info("Checking all wires...\n");

    for (WireId wire : ctx->getWires()) {
        for (BelPin belpin : ctx->getWireBelPins(wire)) {
            WireId wire2 = ctx->getBelPinWire(belpin.bel, belpin.pin);
            log_assert(wire == wire2);
        }

        for (PipId pip : ctx->getPipsDownhill(wire)) {
            WireId wire2 = ctx->getPipSrcWire(pip);
            log_assert(wire == wire2);
        }

        for (PipId pip : ctx->getPipsUphill(wire)) {
            WireId wire2 = ctx->getPipDstWire(pip);
            log_assert(wire == wire2);
        }
    }

    log_info("Checking all BELs...\n");
    for (BelId bel : ctx->getBels()) {
        for (IdString pin : ctx->getBelPins(bel)) {
            WireId wire = ctx->getBelPinWire(bel, pin);

            if (wire == WireId()) {
                continue;
            }

            bool found_belpin = false;
            for (BelPin belpin : ctx->getWireBelPins(wire)) {
                if (belpin.bel == bel && belpin.pin == pin) {
                    found_belpin = true;
                    break;
                }
            }

            log_assert(found_belpin);
        }
    }

    // This cache is used to meet two goals:
    //  - Avoid linear scan by invoking getPipsDownhill/getPipsUphill directly.
    //  - Avoid having pip -> wire maps for the entire part.
    //
    // The overhead of maintaining the cache is small relatively to the memory
    // gains by avoiding the full pip -> wire map, and still preserves a fast
    // pip -> wire, assuming that pips are returned from getPips with some
    // chip locality.
    LruWireCacheMap pip_cache(ctx, /*cache_size=*/64 * 1024);
    log_info("Checking all PIPs...\n");
    for (PipId pip : ctx->getPips()) {
        WireId src_wire = ctx->getPipSrcWire(pip);
        if (src_wire != WireId()) {
            log_assert(pip_cache.isPipDownhill(pip, src_wire));
        }

        WireId dst_wire = ctx->getPipDstWire(pip);
        if (dst_wire != WireId()) {
            log_assert(pip_cache.isPipUphill(pip, dst_wire));
        }
    }
}

void archcheck_buckets(const Context *ctx)
{
    log_info("Checking bucket data.\n");

    // BEL buckets should be subsets of BELs that form an exact cover.
    // In particular that means cell types in a bucket should only be
    // placable in that bucket.
    for (BelBucketId bucket : ctx->getBelBuckets()) {

        // Find out which cell types are in this bucket.
        std::unordered_set<IdString> cell_types_in_bucket;
        for (IdString cell_type : ctx->getCellTypes()) {
            if (ctx->getBelBucketForCellType(cell_type) == bucket) {
                cell_types_in_bucket.insert(cell_type);
            }
        }

        // Make sure that all cell types in this bucket have at least one
        // BelId they can be placed at.
        std::unordered_set<IdString> cell_types_unused;

        std::unordered_set<BelId> bels_in_bucket;
        for (BelId bel : ctx->getBelsInBucket(bucket)) {
            BelBucketId bucket2 = ctx->getBelBucketForBel(bel);
            log_assert(bucket == bucket2);

            bels_in_bucket.insert(bel);

            // Check to see if a cell type not in this bucket can be
            // placed at a BEL in this bucket.
            for (IdString cell_type : ctx->getCellTypes()) {
                if (ctx->getBelBucketForCellType(cell_type) == bucket) {
                    if (ctx->isValidBelForCellType(cell_type, bel)) {
                        cell_types_unused.erase(cell_type);
                    }
                } else {
                    log_assert(!ctx->isValidBelForCellType(cell_type, bel));
                }
            }
        }

        // Verify that any BEL not in this bucket reports a different
        // bucket.
        for (BelId bel : ctx->getBels()) {
            if (ctx->getBelBucketForBel(bel) != bucket) {
                log_assert(bels_in_bucket.count(bel) == 0);
            }
        }

        log_assert(cell_types_unused.empty());
    }
}

} // namespace

NEXTPNR_NAMESPACE_BEGIN

void Context::archcheck() const
{
    log_info("Running architecture database integrity check.\n");
    log_break();

    archcheck_names(this);
    archcheck_locs(this);
    archcheck_conn(this);
    archcheck_buckets(this);
}

NEXTPNR_NAMESPACE_END
<commit_msg>archcheck: Use old connectivity check for CycloneV<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *
 *  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 "log.h"
#include "nextpnr.h"

#if 0
#define dbg(...) log(__VA_ARGS__)
#else
#define dbg(...)
#endif

USING_NEXTPNR_NAMESPACE

#ifndef ARCH_CYCLONEV
// The LRU cache to reduce memory usage during the connectivity check relies on getPips() having some spacial locality,
// which the current CycloneV arch impl doesn't have. This may be fixed in the future, though.
#define USING_LRU_CACHE
#endif

namespace {

void archcheck_names(const Context *ctx)
{
    log_info("Checking entity names.\n");

    log_info("Checking bel names..\n");
    for (BelId bel : ctx->getBels()) {
        IdStringList name = ctx->getBelName(bel);
        BelId bel2 = ctx->getBelByName(name);
        if (bel != bel2) {
            log_error("bel != bel2, name = %s\n", ctx->nameOfBel(bel));
        }
    }

    log_info("Checking wire names..\n");
    for (WireId wire : ctx->getWires()) {
        IdStringList name = ctx->getWireName(wire);
        WireId wire2 = ctx->getWireByName(name);
        if (wire != wire2) {
            log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire));
        }
    }

    log_info("Checking bucket names..\n");
    for (BelBucketId bucket : ctx->getBelBuckets()) {
        IdString name = ctx->getBelBucketName(bucket);
        BelBucketId bucket2 = ctx->getBelBucketByName(name);
        if (bucket != bucket2) {
            log_error("bucket != bucket2, name = %s\n", name.c_str(ctx));
        }
    }

#ifndef ARCH_ECP5
    log_info("Checking pip names..\n");
    for (PipId pip : ctx->getPips()) {
        IdStringList name = ctx->getPipName(pip);
        PipId pip2 = ctx->getPipByName(name);
        if (pip != pip2) {
            log_error("pip != pip2, name = %s\n", ctx->nameOfPip(pip));
        }
    }
#endif
    log_break();
}

void archcheck_locs(const Context *ctx)
{
    log_info("Checking location data.\n");

    log_info("Checking all bels..\n");
    for (BelId bel : ctx->getBels()) {
        log_assert(bel != BelId());
        dbg("> %s\n", ctx->getBelName(bel).c_str(ctx));

        Loc loc = ctx->getBelLocation(bel);
        dbg("   ... %d %d %d\n", loc.x, loc.y, loc.z);

        log_assert(0 <= loc.x);
        log_assert(0 <= loc.y);
        log_assert(0 <= loc.z);
        log_assert(loc.x < ctx->getGridDimX());
        log_assert(loc.y < ctx->getGridDimY());
        log_assert(loc.z < ctx->getTileBelDimZ(loc.x, loc.y));

        BelId bel2 = ctx->getBelByLocation(loc);
        dbg("   ... %s\n", ctx->getBelName(bel2).c_str(ctx));
        log_assert(bel == bel2);
    }

    log_info("Checking all locations..\n");
    for (int x = 0; x < ctx->getGridDimX(); x++)
        for (int y = 0; y < ctx->getGridDimY(); y++) {
            dbg("> %d %d\n", x, y);
            std::unordered_set<int> usedz;

            for (int z = 0; z < ctx->getTileBelDimZ(x, y); z++) {
                BelId bel = ctx->getBelByLocation(Loc(x, y, z));
                if (bel == BelId())
                    continue;
                Loc loc = ctx->getBelLocation(bel);
                dbg("   + %d %s\n", z, ctx->nameOfBel(bel));
                log_assert(x == loc.x);
                log_assert(y == loc.y);
                log_assert(z == loc.z);
                usedz.insert(z);
            }

            for (BelId bel : ctx->getBelsByTile(x, y)) {
                Loc loc = ctx->getBelLocation(bel);
                dbg("   - %d %s\n", loc.z, ctx->nameOfBel(bel));
                log_assert(x == loc.x);
                log_assert(y == loc.y);
                log_assert(usedz.count(loc.z));
                usedz.erase(loc.z);
            }

            log_assert(usedz.empty());
        }

    log_break();
}

// Implements a LRU cache for pip to wire via getPipsDownhill/getPipsUphill.
//
// This allows a fast way to check getPipsDownhill/getPipsUphill from getPips,
// without balloning memory usage.
struct LruWireCacheMap
{
    LruWireCacheMap(const Context *ctx, size_t cache_size) : ctx(ctx), cache_size(cache_size)
    {
        cache_hits = 0;
        cache_misses = 0;
        cache_evictions = 0;
    }

    const Context *ctx;
    size_t cache_size;

    // Cache stats for checking on cache behavior.
    size_t cache_hits;
    size_t cache_misses;
    size_t cache_evictions;

    // Most recent accessed wires are added to the back of the list, front of
    // list is oldest wire in cache.
    std::list<WireId> last_access_list;
    // Quick wire -> list element lookup.
    std::unordered_map<WireId, std::list<WireId>::iterator> last_access_map;

    std::unordered_map<PipId, WireId> pips_downhill;
    std::unordered_map<PipId, WireId> pips_uphill;

    void removeWireFromCache(WireId wire_to_remove)
    {
        for (PipId pip : ctx->getPipsDownhill(wire_to_remove)) {
            log_assert(pips_downhill.erase(pip) == 1);
        }

        for (PipId pip : ctx->getPipsUphill(wire_to_remove)) {
            log_assert(pips_uphill.erase(pip) == 1);
        }
    }

    void addWireToCache(WireId wire)
    {
        for (PipId pip : ctx->getPipsDownhill(wire)) {
            auto result = pips_downhill.emplace(pip, wire);
            log_assert(result.second);
        }

        for (PipId pip : ctx->getPipsUphill(wire)) {
            auto result = pips_uphill.emplace(pip, wire);
            log_assert(result.second);
        }
    }

    void populateCache(WireId wire)
    {
        // Put this wire at the end of last_access_list.
        auto iter = last_access_list.emplace(last_access_list.end(), wire);
        last_access_map.emplace(wire, iter);

        if (last_access_list.size() > cache_size) {
            // Cache is full, remove front of last_access_list.
            cache_evictions += 1;
            WireId wire_to_remove = last_access_list.front();
            last_access_list.pop_front();
            log_assert(last_access_map.erase(wire_to_remove) == 1);

            removeWireFromCache(wire_to_remove);
        }

        addWireToCache(wire);
    }

    // Determine if wire is in the cache.  If wire is not in the cache,
    // adds the wire to the cache, and potentially evicts the oldest wire if
    // cache is now full.
    void checkCache(WireId wire)
    {
        auto iter = last_access_map.find(wire);
        if (iter == last_access_map.end()) {
            cache_misses += 1;
            populateCache(wire);
        } else {
            // Record that this wire has been accessed.
            cache_hits += 1;
            last_access_list.splice(last_access_list.end(), last_access_list, iter->second);
        }
    }

    // Returns true if pip is uphill of wire (e.g. pip in getPipsUphill(wire)).
    bool isPipUphill(PipId pip, WireId wire)
    {
        checkCache(wire);
        return pips_uphill.at(pip) == wire;
    }

    // Returns true if pip is downhill of wire (e.g. pip in getPipsDownhill(wire)).
    bool isPipDownhill(PipId pip, WireId wire)
    {
        checkCache(wire);
        return pips_downhill.at(pip) == wire;
    }

    void cache_info() const
    {
        log_info("Cache hits: %zu\n", cache_hits);
        log_info("Cache misses: %zu\n", cache_misses);
        log_info("Cache evictions: %zu\n", cache_evictions);
    }
};

void archcheck_conn(const Context *ctx)
{
    log_info("Checking connectivity data.\n");

    log_info("Checking all wires...\n");

#ifndef USING_LRU_CACHE
    std::unordered_map<PipId, WireId> pips_downhill;
    std::unordered_map<PipId, WireId> pips_uphill;
#endif

    for (WireId wire : ctx->getWires()) {
        for (BelPin belpin : ctx->getWireBelPins(wire)) {
            WireId wire2 = ctx->getBelPinWire(belpin.bel, belpin.pin);
            log_assert(wire == wire2);
        }

        for (PipId pip : ctx->getPipsDownhill(wire)) {
            WireId wire2 = ctx->getPipSrcWire(pip);
            log_assert(wire == wire2);
#ifndef USING_LRU_CACHE
            auto result = pips_downhill.emplace(pip, wire);
            log_assert(result.second);
#endif
        }

        for (PipId pip : ctx->getPipsUphill(wire)) {
            WireId wire2 = ctx->getPipDstWire(pip);
            log_assert(wire == wire2);
#ifndef USING_LRU_CACHE
            auto result = pips_uphill.emplace(pip, wire);
            log_assert(result.second);
#endif
        }
    }

    log_info("Checking all BELs...\n");
    for (BelId bel : ctx->getBels()) {
        for (IdString pin : ctx->getBelPins(bel)) {
            WireId wire = ctx->getBelPinWire(bel, pin);

            if (wire == WireId()) {
                continue;
            }

            bool found_belpin = false;
            for (BelPin belpin : ctx->getWireBelPins(wire)) {
                if (belpin.bel == bel && belpin.pin == pin) {
                    found_belpin = true;
                    break;
                }
            }

            log_assert(found_belpin);
        }
    }
#ifdef USING_LRU_CACHE
    // This cache is used to meet two goals:
    //  - Avoid linear scan by invoking getPipsDownhill/getPipsUphill directly.
    //  - Avoid having pip -> wire maps for the entire part.
    //
    // The overhead of maintaining the cache is small relatively to the memory
    // gains by avoiding the full pip -> wire map, and still preserves a fast
    // pip -> wire, assuming that pips are returned from getPips with some
    // chip locality.
    LruWireCacheMap pip_cache(ctx, /*cache_size=*/64 * 1024);
#endif
    log_info("Checking all PIPs...\n");
    for (PipId pip : ctx->getPips()) {
        WireId src_wire = ctx->getPipSrcWire(pip);
        if (src_wire != WireId()) {
#ifdef USING_LRU_CACHE
            log_assert(pip_cache.isPipDownhill(pip, src_wire));
#else
            log_assert(pips_downhill.at(pip) == src_wire);
#endif
        }

        WireId dst_wire = ctx->getPipDstWire(pip);
        if (dst_wire != WireId()) {
#ifdef USING_LRU_CACHE
            log_assert(pip_cache.isPipUphill(pip, dst_wire));
#else
            log_assert(pips_uphill.at(pip) == dst_wire);
#endif
        }
    }
}

void archcheck_buckets(const Context *ctx)
{
    log_info("Checking bucket data.\n");

    // BEL buckets should be subsets of BELs that form an exact cover.
    // In particular that means cell types in a bucket should only be
    // placable in that bucket.
    for (BelBucketId bucket : ctx->getBelBuckets()) {

        // Find out which cell types are in this bucket.
        std::unordered_set<IdString> cell_types_in_bucket;
        for (IdString cell_type : ctx->getCellTypes()) {
            if (ctx->getBelBucketForCellType(cell_type) == bucket) {
                cell_types_in_bucket.insert(cell_type);
            }
        }

        // Make sure that all cell types in this bucket have at least one
        // BelId they can be placed at.
        std::unordered_set<IdString> cell_types_unused;

        std::unordered_set<BelId> bels_in_bucket;
        for (BelId bel : ctx->getBelsInBucket(bucket)) {
            BelBucketId bucket2 = ctx->getBelBucketForBel(bel);
            log_assert(bucket == bucket2);

            bels_in_bucket.insert(bel);

            // Check to see if a cell type not in this bucket can be
            // placed at a BEL in this bucket.
            for (IdString cell_type : ctx->getCellTypes()) {
                if (ctx->getBelBucketForCellType(cell_type) == bucket) {
                    if (ctx->isValidBelForCellType(cell_type, bel)) {
                        cell_types_unused.erase(cell_type);
                    }
                } else {
                    log_assert(!ctx->isValidBelForCellType(cell_type, bel));
                }
            }
        }

        // Verify that any BEL not in this bucket reports a different
        // bucket.
        for (BelId bel : ctx->getBels()) {
            if (ctx->getBelBucketForBel(bel) != bucket) {
                log_assert(bels_in_bucket.count(bel) == 0);
            }
        }

        log_assert(cell_types_unused.empty());
    }
}

} // namespace

NEXTPNR_NAMESPACE_BEGIN

void Context::archcheck() const
{
    log_info("Running architecture database integrity check.\n");
    log_break();

    archcheck_names(this);
    archcheck_locs(this);
    archcheck_conn(this);
    archcheck_buckets(this);
}

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>/*
	convert <addr> to <file:line addr>
	input stdin
	output stdout
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cybozu/bfd.hpp>
#include <cybozu/stacktrace.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/option.hpp>
#include <cybozu/string_operation.hpp>

/*
	find "[0x" ([0-9a-f]+) "]"
*/
const void* findAddr(const std::string& str)
{
	size_t p = str.find("[0x");
	if (p == std::string::npos) return 0;
	size_t q = str.find("]", p + 3);
	if (q == std::string::npos) return 0;
	bool b;
	size_t addr = cybozu::hextoi(&b, &str[p + 3], q - p - 3);
	if (!b) return 0;
	return (const void*)addr;
}

void decode(std::string& str, cybozu::Bfd& bfd)
{
	const void *addr = findAddr(str);
	if (addr == 0) return;
	std::string file;
	std::string func;
	int line;
	if (!bfd.getInfo(&file, &func, &line, addr)) return;
	cybozu::Demangle(func, func);
	str = file + ':' + cybozu::itoa(line) + ' ' + func + ' ' + str;
}

int main(int argc, char **argv)
	try
{
	cybozu::Option opt;
	bool doCheckAll = false;
	std::string fileName;
	opt.appendBoolOpt(&doCheckAll, "a", ": check all text");
	opt.appendHelp("h", ": put this message");
	opt.appendParam(&fileName, "target file name");
	if (!opt.parse(argc, argv)) {
		opt.usage();
		return 1;
	}
	const std::string beginStackTrace = "<<<STACKTRACE";
	const std::string endStackTrace = ">>>STACKTRACE";
	bool inStackTrace = false;
	cybozu::Bfd bfd(fileName);
	std::string line;
	while (std::getline(std::cin, line)) {
		cybozu::Strip(line);
		bool doDecode = false;
		if (doCheckAll) {
			doDecode = true;
		} else {
			if (inStackTrace) {
				if (line.find(endStackTrace) == 0) {
					inStackTrace = false;
				} else {
					doDecode = true;
				}
			} else {
				if (line.find(beginStackTrace) == 0) {
					inStackTrace = true;
				}
			}
		}
		if (doDecode) {
			decode(line, bfd);
		}
		printf("%s\n", line.c_str());
	}
} catch (std::exception& e) {
	printf("ERR %s\n", e.what());
}
<commit_msg>append -e option and load text from file<commit_after>/*
	convert <addr> to <file:line addr>
	input stdin
	output stdout
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <cybozu/bfd.hpp>
#include <cybozu/stacktrace.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/option.hpp>
#include <cybozu/string_operation.hpp>

/*
	find "[0x" ([0-9a-f]+) "]"
*/
const void* findAddr(const std::string& str)
{
	size_t p = str.find("[0x");
	if (p == std::string::npos) return 0;
	size_t q = str.find("]", p + 3);
	if (q == std::string::npos) return 0;
	bool b;
	size_t addr = cybozu::hextoi(&b, &str[p + 3], q - p - 3);
	if (!b) return 0;
	return (const void*)addr;
}

void decode(std::string& str, cybozu::Bfd& bfd)
{
	const void *addr = findAddr(str);
	if (addr == 0) return;
	std::string file;
	std::string func;
	int line;
	if (!bfd.getInfo(&file, &func, &line, addr)) return;
	cybozu::Demangle(func, func);
	str = file + ':' + cybozu::itoa(line) + ' ' + func + ' ' + str;
}

int main(int argc, char **argv)
	try
{
	cybozu::Option opt;
	bool doCheckAll = false;
	std::string exeName;
	std::string textName;
	opt.appendBoolOpt(&doCheckAll, "a", ": check all text");
	opt.appendOpt(&exeName, "", "e", ": target exe name");
	opt.appendParamOpt(&textName, "-", "e", ": target exe name");
	opt.appendHelp("h", ": put this message");
	if (!opt.parse(argc, argv)) {
		opt.usage();
		return 1;
	}
	const std::string beginStackTrace = "<<<STACK TRACE";
	const std::string endStackTrace = ">>>STACK TRACE";
	bool inStackTrace = false;
	cybozu::Bfd bfd(exeName);
	std::string line;
	std::istream *pis = 0;
	std::ifstream ifs;
	if (textName == "-") {
		pis = &std::cin;
	} else {
		ifs.open(textName.c_str(), std::ios::binary);
		pis = &ifs;
	}
	while (std::getline(*pis, line)) {
		cybozu::Strip(line);
		bool doDecode = false;
		if (doCheckAll) {
			doDecode = true;
		} else {
			if (inStackTrace) {
				if (line.find(endStackTrace) == 0) {
					inStackTrace = false;
				} else {
					doDecode = true;
				}
			} else {
				if (line.find(beginStackTrace) == 0) {
					inStackTrace = true;
				}
			}
		}
		if (doDecode) {
			decode(line, bfd);
		}
		printf("%s\n", line.c_str());
	}
} catch (std::exception& e) {
	printf("ERR %s\n", e.what());
}
<|endoftext|>