<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 NorthScale, Inc.
 *
 *   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 "config.h"

#include <sstream>
#include <fstream>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <cstring>

#include "sockstream.h"

using namespace std;

class sockstreambuf : public filebuf {
public:
    sockstreambuf(SOCKET s, size_t sz = 64*1024) : sock(s), size(sz),
                                                   buffer(NULL) {
        buffer = new char[size];
        setp(buffer, buffer + size - 1);
        setg(buffer, buffer, buffer);
    }

    virtual ~sockstreambuf() {
        sync();
        delete []buffer;
    }

    virtual int overflow(int c) {
        if (c != EOF) {
            *pptr() = c;
            pbump(1);
        }

        if (flushBuffer() == EOF) {
            fprintf(stderr, "RETURNING EOF\n");
            return EOF;
        }

        return c;
    }

    virtual int underflow() {
        ssize_t nr;

        while ((nr = recv(sock, buffer, size, 0)) == SOCKET_ERROR) {
            switch (get_socket_errno()) {
            case EINTR:
                // retry
                break;
            default:
                /* These should not happen. get a core file!! */
                abort();
            }
        }
        if (nr == 0) {
            return EOF;
        }
        setg(buffer, buffer, buffer + nr);
        return (unsigned char)buffer[0];
    }

    virtual int sync(){
        if (flushBuffer() == EOF) {
            return -1;
        }

        return 0;
    }

private:
    int flushBuffer() {
        ptrdiff_t nb = pptr() - pbase();

        if (nb > 0) {
            // @todo handle error code
            if (send(sock, buffer, nb, 0) != nb) {
                return EOF;
            }

            pbump(-nb);
        }

        return nb;
    }

    SOCKET sock;
    size_t size;
    char *buffer;
};

class osockstream : public ofstream {
public:
    osockstream(SOCKET sock) : buffer(sock) {
        ios::rdbuf(&buffer);
    }

private:
    sockstreambuf buffer;
};

class isockstream : public ifstream {
public:
    isockstream(SOCKET sock) : buffer(sock) {
        ios::rdbuf(&buffer);
    }

private:
    sockstreambuf buffer;
};

void Socket::resolve(void) throw (string)
{
    if (ai == NULL) {
        struct addrinfo hints;
        std::memset(&hints, 0, sizeof(hints));
        hints.ai_flags = AI_PASSIVE;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_family = AF_UNSPEC;

        int error = getaddrinfo(host.c_str(), port.c_str(), &hints, &ai);
        if (error != 0) {
            stringstream ss;
            ss << "getaddrinfo(): "
               << (error != EAI_SYSTEM) ? gai_strerror(error) : strerror(error);
            throw ss.str();
        }
    }
}

void Socket::connect(void) throw (string)
{
    if (sock != INVALID_SOCKET) {
        throw "Can't call connect() with an open Socket. Call close()!!";
    }

    resolve();

    for (struct addrinfo *next= ai; next; next= next->ai_next) {
        if ((sock = socket(ai->ai_family,
                           ai->ai_socktype,
                           ai->ai_protocol)) == INVALID_SOCKET) {
            continue;
        }

        if (::connect(sock, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR) {
            closesocket(sock);
            sock = INVALID_SOCKET;
            continue;
        }

        break;
    }

    if (sock == INVALID_SOCKET) {
        stringstream msg;
        msg << "Failed to connect to [" << host << ":" << port << "]";
        throw msg.str();
    }
}

void Socket::close(void) {
    if (in) {
        delete in;
        in = NULL;
    }

    if (out) {
        delete out;
        out = NULL;
    }

    if (sock != INVALID_SOCKET) {
#if 0
        WSAIoctl(sock, SIO_FLUSH, NULL, 0, NULL, 0, NULL, NULL, NULL);
#endif
        shutdown(sock, SD_SEND); // disable sending of more data

        closesocket(sock);
        sock = INVALID_SOCKET;
    }

    if (ai != NULL) {
        freeaddrinfo(ai);
        ai = NULL;
    }
}

ostream *Socket::getOutStream()
{
    if (out == NULL) {
        out = new osockstream(sock);
    }
    return out;
}

istream *Socket::getInStream()
{
    if (in == NULL) {
        in = new isockstream(sock);
    }

    return in;
}

void Socket::setTimeout(int which, int millis) {
#ifdef WIN32
    int err = setsockopt(sock, SOL_SOCKET,
                         which,
                         (char *)&millis, sizeof(millis));
    assert(err == NO_ERROR);
#else
    struct timeval tv;

    tv.tv_sec = millis / 1000;
    tv.tv_usec = (millis % 1000) * 1000;

    int err = setsockopt(sock, SOL_SOCKET, which,
                         (struct timeval *)&tv,
                         sizeof(struct timeval));
    assert(err == 0);
#endif
}

void Socket::setTimeout(int millis) {
    setTimeout(SO_SNDTIMEO, millis);
    setTimeout(SO_RCVTIMEO, millis);
}

void Socket::setBlockingMode(bool blocking) throw (std::string)
{
#ifdef WIN32
    u_long arg = blocking ? 0 : 1;
    if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR) {
        stringstream msg;
        msg << "Failed to enable " << (blocking ? "" : "non")
            << "blocking io: " << strerror(get_socket_errno());
        throw msg.str();
    }
#else
    int flags;
    if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
        stringstream msg;
        msg << "Failed to get current flags: " << strerror(get_socket_errno());
        throw msg.str();
    }

    bool update = false;
    if (blocking) {
        if ((flags & O_NONBLOCK) == O_NONBLOCK) {
            update = true;
            flags ^= O_NONBLOCK;
        }
    } else {
        if ((flags & O_NONBLOCK) != O_NONBLOCK) {
            update = true;
            flags |= O_NONBLOCK;
        }
    }

    if (update && (fcntl(sock, F_SETFL, flags) < 0)) {
        stringstream msg;
        msg << "Failed to " << (blocking ? "disable" : "enable")
            << " O_NONBLOCK: " << strerror(get_socket_errno());
        throw msg.str();
    }
#endif
}

std::string Socket::getLocalAddress() const throw (std::string) {
    char h[NI_MAXHOST];
    char p[NI_MAXSERV];
    struct sockaddr_storage saddr;
    socklen_t salen= sizeof(saddr);

    if ((getsockname(sock, (struct sockaddr *)&saddr, &salen) < 0) ||
        (getnameinfo((struct sockaddr *)&saddr, salen, h, sizeof(h),
                     p, sizeof(p), NI_NUMERICHOST | NI_NUMERICSERV) < 0))
    {
        stringstream msg;
        msg << "Failed to get local address: " << strerror(get_socket_errno());
        throw msg.str();
    }

    std::stringstream ss;
    ss << h << ";" << p;
    return ss.str();
}

std::string Socket::getRemoteAddress() const throw (std::string) {
    char h[NI_MAXHOST];
    char p[NI_MAXSERV];
    struct sockaddr_storage saddr;
    socklen_t salen= sizeof(saddr);

    if ((getpeername(sock, (struct sockaddr *)&saddr, &salen) < 0) ||
        (getnameinfo((struct sockaddr *)&saddr, salen, h, sizeof(h),
                     p, sizeof(p), NI_NUMERICHOST | NI_NUMERICSERV) < 0))
    {
        stringstream msg;
        msg << "Failed to get local address: " << strerror(get_socket_errno());
        throw msg.str();
    }

    std::stringstream ss;
    ss << h << ";" << p;
    return ss.str();
}
<commit_msg>Fixed the connect loop<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 NorthScale, Inc.
 *
 *   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 "config.h"

#include <sstream>
#include <fstream>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <cstring>

#include "sockstream.h"

using namespace std;

class sockstreambuf : public filebuf {
public:
    sockstreambuf(SOCKET s, size_t sz = 64*1024) : sock(s), size(sz),
                                                   buffer(NULL) {
        buffer = new char[size];
        setp(buffer, buffer + size - 1);
        setg(buffer, buffer, buffer);
    }

    virtual ~sockstreambuf() {
        sync();
        delete []buffer;
    }

    virtual int overflow(int c) {
        if (c != EOF) {
            *pptr() = c;
            pbump(1);
        }

        if (flushBuffer() == EOF) {
            fprintf(stderr, "RETURNING EOF\n");
            return EOF;
        }

        return c;
    }

    virtual int underflow() {
        ssize_t nr;

        while ((nr = recv(sock, buffer, size, 0)) == SOCKET_ERROR) {
            switch (get_socket_errno()) {
            case EINTR:
                // retry
                break;
            default:
                /* These should not happen. get a core file!! */
                abort();
            }
        }
        if (nr == 0) {
            return EOF;
        }
        setg(buffer, buffer, buffer + nr);
        return (unsigned char)buffer[0];
    }

    virtual int sync(){
        if (flushBuffer() == EOF) {
            return -1;
        }

        return 0;
    }

private:
    int flushBuffer() {
        ptrdiff_t nb = pptr() - pbase();

        if (nb > 0) {
            // @todo handle error code
            if (send(sock, buffer, nb, 0) != nb) {
                return EOF;
            }

            pbump(-nb);
        }

        return nb;
    }

    SOCKET sock;
    size_t size;
    char *buffer;
};

class osockstream : public ofstream {
public:
    osockstream(SOCKET sock) : buffer(sock) {
        ios::rdbuf(&buffer);
    }

private:
    sockstreambuf buffer;
};

class isockstream : public ifstream {
public:
    isockstream(SOCKET sock) : buffer(sock) {
        ios::rdbuf(&buffer);
    }

private:
    sockstreambuf buffer;
};

void Socket::resolve(void) throw (string)
{
    if (ai == NULL) {
        struct addrinfo hints;
        std::memset(&hints, 0, sizeof(hints));
        hints.ai_flags = AI_PASSIVE;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_family = AF_UNSPEC;

        int error = getaddrinfo(host.c_str(), port.c_str(), &hints, &ai);
        if (error != 0) {
            stringstream ss;
            ss << "getaddrinfo(): "
               << (error != EAI_SYSTEM) ? gai_strerror(error) : strerror(error);
            throw ss.str();
        }
    }
}

void Socket::connect(void) throw (string)
{
    if (sock != INVALID_SOCKET) {
        throw "Can't call connect() with an open Socket. Call close()!!";
    }

    resolve();

    for (struct addrinfo *next= ai; next; next= next->ai_next) {
        if ((sock = socket(next->ai_family,
                           next->ai_socktype,
                           next->ai_protocol)) == INVALID_SOCKET) {
            continue;
        }

        if (::connect(sock, next->ai_addr, next->ai_addrlen) == SOCKET_ERROR) {
            closesocket(sock);
            sock = INVALID_SOCKET;
            continue;
        }

        break;
    }

    if (sock == INVALID_SOCKET) {
        stringstream msg;
        msg << "Failed to connect to [" << host << ":" << port << "]";
        throw msg.str();
    }
}

void Socket::close(void) {
    if (in) {
        delete in;
        in = NULL;
    }

    if (out) {
        delete out;
        out = NULL;
    }

    if (sock != INVALID_SOCKET) {
#if 0
        WSAIoctl(sock, SIO_FLUSH, NULL, 0, NULL, 0, NULL, NULL, NULL);
#endif
        shutdown(sock, SD_SEND); // disable sending of more data

        closesocket(sock);
        sock = INVALID_SOCKET;
    }

    if (ai != NULL) {
        freeaddrinfo(ai);
        ai = NULL;
    }
}

ostream *Socket::getOutStream()
{
    if (out == NULL) {
        out = new osockstream(sock);
    }
    return out;
}

istream *Socket::getInStream()
{
    if (in == NULL) {
        in = new isockstream(sock);
    }

    return in;
}

void Socket::setTimeout(int which, int millis) {
#ifdef WIN32
    int err = setsockopt(sock, SOL_SOCKET,
                         which,
                         (char *)&millis, sizeof(millis));
    assert(err == NO_ERROR);
#else
    struct timeval tv;

    tv.tv_sec = millis / 1000;
    tv.tv_usec = (millis % 1000) * 1000;

    int err = setsockopt(sock, SOL_SOCKET, which,
                         (struct timeval *)&tv,
                         sizeof(struct timeval));
    assert(err == 0);
#endif
}

void Socket::setTimeout(int millis) {
    setTimeout(SO_SNDTIMEO, millis);
    setTimeout(SO_RCVTIMEO, millis);
}

void Socket::setBlockingMode(bool blocking) throw (std::string)
{
#ifdef WIN32
    u_long arg = blocking ? 0 : 1;
    if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR) {
        stringstream msg;
        msg << "Failed to enable " << (blocking ? "" : "non")
            << "blocking io: " << strerror(get_socket_errno());
        throw msg.str();
    }
#else
    int flags;
    if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
        stringstream msg;
        msg << "Failed to get current flags: " << strerror(get_socket_errno());
        throw msg.str();
    }

    bool update = false;
    if (blocking) {
        if ((flags & O_NONBLOCK) == O_NONBLOCK) {
            update = true;
            flags ^= O_NONBLOCK;
        }
    } else {
        if ((flags & O_NONBLOCK) != O_NONBLOCK) {
            update = true;
            flags |= O_NONBLOCK;
        }
    }

    if (update && (fcntl(sock, F_SETFL, flags) < 0)) {
        stringstream msg;
        msg << "Failed to " << (blocking ? "disable" : "enable")
            << " O_NONBLOCK: " << strerror(get_socket_errno());
        throw msg.str();
    }
#endif
}

std::string Socket::getLocalAddress() const throw (std::string) {
    char h[NI_MAXHOST];
    char p[NI_MAXSERV];
    struct sockaddr_storage saddr;
    socklen_t salen= sizeof(saddr);

    if ((getsockname(sock, (struct sockaddr *)&saddr, &salen) < 0) ||
        (getnameinfo((struct sockaddr *)&saddr, salen, h, sizeof(h),
                     p, sizeof(p), NI_NUMERICHOST | NI_NUMERICSERV) < 0))
    {
        stringstream msg;
        msg << "Failed to get local address: " << strerror(get_socket_errno());
        throw msg.str();
    }

    std::stringstream ss;
    ss << h << ";" << p;
    return ss.str();
}

std::string Socket::getRemoteAddress() const throw (std::string) {
    char h[NI_MAXHOST];
    char p[NI_MAXSERV];
    struct sockaddr_storage saddr;
    socklen_t salen= sizeof(saddr);

    if ((getpeername(sock, (struct sockaddr *)&saddr, &salen) < 0) ||
        (getnameinfo((struct sockaddr *)&saddr, salen, h, sizeof(h),
                     p, sizeof(p), NI_NUMERICHOST | NI_NUMERICSERV) < 0))
    {
        stringstream msg;
        msg << "Failed to get local address: " << strerror(get_socket_errno());
        throw msg.str();
    }

    std::stringstream ss;
    ss << h << ";" << p;
    return ss.str();
}
<|endoftext|>


<commit_before>#include "sourcefile.h"
#include <fstream>
#include <sstream>

const size_t buffer_size=131072;

//Only use on small files
std::string juci::filesystem::read(const std::string &path) {
  std::stringstream ss;
  std::ifstream input(path);
  if(input) {
    ss << input.rdbuf();
    input.close();
  }
  return ss.str();
}

bool juci::filesystem::read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) {
  std::ifstream input(path);
  if(input) {
    std::vector<char> buffer(buffer_size);
    size_t read_length;
    while((read_length=input.read(&buffer[0], buffer_size).gcount())>0) {
      auto ustr=Glib::ustring(std::string(&buffer[0], read_length));
      if(ustr.validate())
        text_buffer->insert_at_cursor(ustr);
      else {
        input.close();
        return false;
      }
    }
    input.close();
    return true;
  }
  return false;
}

//Only use on small files
std::vector<std::string> juci::filesystem::read_lines(const std::string &path) {
  std::vector<std::string> res;
  std::ifstream input(path);
  if (input) {
    do { res.emplace_back(); } while(getline(input, res.back()));
  }
  input.close();
  return res;
}

//Only use on small files
bool juci::filesystem::write(const std::string &path, const std::string &new_content) {
  std::ofstream output(path);
  if(output)
    output << new_content;
  else
    return false;
  output.close();
  return true;
}

bool juci::filesystem::write(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> buffer) {
  std::ofstream output(path, std::ofstream::binary);
  if(output) {
    auto start_iter=buffer->begin();
    auto end_iter=start_iter;
    bool end_reached=false;
    while(!end_reached) {
      for(size_t c=0;c<buffer_size;c++) {
        if(end_iter)
          end_iter++;
        else {
          end_reached=true;
          break;
        }
      }
      output << buffer->get_text(start_iter, end_iter).c_str();
      start_iter=end_iter;
    }
    output.close();
    return true;
  }
  return false;
}
<commit_msg>Added std::ofstream::binary to all file reads and writes.<commit_after>#include "sourcefile.h"
#include <fstream>
#include <sstream>

const size_t buffer_size=131072;

//Only use on small files
std::string juci::filesystem::read(const std::string &path) {
  std::stringstream ss;
  std::ifstream input(path, std::ofstream::binary);
  if(input) {
    ss << input.rdbuf();
    input.close();
  }
  return ss.str();
}

bool juci::filesystem::read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) {
  std::ifstream input(path, std::ofstream::binary);
  if(input) {
    std::vector<char> buffer(buffer_size);
    size_t read_length;
    while((read_length=input.read(&buffer[0], buffer_size).gcount())>0) {
      auto ustr=Glib::ustring(std::string(&buffer[0], read_length));
      if(ustr.validate())
        text_buffer->insert_at_cursor(ustr);
      else {
        input.close();
        return false;
      }
    }
    input.close();
    return true;
  }
  return false;
}

//Only use on small files
std::vector<std::string> juci::filesystem::read_lines(const std::string &path) {
  std::vector<std::string> res;
  std::ifstream input(path, std::ofstream::binary);
  if (input) {
    do { res.emplace_back(); } while(getline(input, res.back()));
  }
  input.close();
  return res;
}

//Only use on small files
bool juci::filesystem::write(const std::string &path, const std::string &new_content) {
  std::ofstream output(path, std::ofstream::binary);
  if(output)
    output << new_content;
  else
    return false;
  output.close();
  return true;
}

bool juci::filesystem::write(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> buffer) {
  std::ofstream output(path, std::ofstream::binary);
  if(output) {
    auto start_iter=buffer->begin();
    auto end_iter=start_iter;
    bool end_reached=false;
    while(!end_reached) {
      for(size_t c=0;c<buffer_size;c++) {
        if(end_iter)
          end_iter++;
        else {
          end_reached=true;
          break;
        }
      }
      output << buffer->get_text(start_iter, end_iter).c_str();
      start_iter=end_iter;
    }
    output.close();
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  testModelCopy.cpp                         *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Ayman Habib                                                     *
 *                                                                            *
 * 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 <stdint.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

// Test copying, serializing and deserializing models and verify
// that the number of bodies (nbods) and the number of attached geometry
// (ngeom) on a given PhysicalFrame (by name) are preserved.
void testCopyModel( const string& fileName, const int nbod,
                    const string& physicalFrameName, const int ngeom);

int main()
{
    try {

        // Test copying a simple property.
        {
            std::cout << "Test copying a simple property." << std::endl;
            Property<double>* a =
                Property<double>::TypeHelper::create("a", true);
            a->setValue(0.123456789);
            Property<double>* b =
                Property<double>::TypeHelper::create("b", true);
            b->setValue(10.0);

            b->assign(*a);

            cout << "b = " << b->toString() << endl;
            ASSERT(*a == *b);
        }

        // Test copying a an Object property.
        {
            std::cout << "Test copying a object property." << std::endl;
            Body A("A", 0.12345, SimTK::Vec3(0.1, 0.2, 0.3),
                SimTK::Inertia(0.33, 0.22, 0.11));
            Body B;

            Property<Body>* a = Property<Body>::TypeHelper::create("a", true);
            a->setValue(A);
            Property<Body>* b = Property<Body>::TypeHelper::create("b", true);
            b->setValue(B);

            b->assign(*a);

            cout << "b = " << b->toString() << endl;
            ASSERT(*a == *b);

            B = A;
            ASSERT(B == A);
        }

        Model arm("arm26.osim");
        Model armAssigned;

        armAssigned = arm;
        ASSERT(armAssigned == arm);

        LoadOpenSimLibrary("osimActuators");
        testCopyModel("arm26.osim", 2, "ground", 6);
        testCopyModel("Neck3dof_point_constraint.osim", 25, "spine", 1);
    }
    catch (const Exception& e) {
        cout << e.what() << endl;
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}

void testCopyModel(const string& fileName, const int nbod,
    const string& physicalFrameName, const int ngeom)
{
    const size_t mem0 = getCurrentRSS();

    // Automatically finalizes properties by default when loading from file
    Model* model = new Model(fileName);

    // Catch a possible decrease in the memory footprint, which will cause
    // size_t (unsigned int) to wrap through zero.
    const size_t mem1 = getCurrentRSS();
    const size_t increaseInMemory = mem1 > mem0 ? mem1-mem0 : 0;

    cout << "Memory use of '" << fileName <<"' model: " << increaseInMemory/1024
         << "KB" << endl;

    Model *test = nullptr;
    for (int i = 0; i < 10; ++i){
        test = new Model(fileName);
        delete test;
    }

    model->print("clone_" + fileName); //print is not realy const it changes the model
    // recall finalize from properties to make consistent
    model->finalizeFromProperties();

    //SimTK::State& defaultState = model->initSystem();

    Model* modelCopy = new Model(*model);
    modelCopy->finalizeFromProperties();
    // At this point properties should all match. assert that
    ASSERT(*model==*modelCopy);
    ASSERT(model->getActuators().getSize() ==
           modelCopy->getActuators().getSize());

    //SimTK::State& defaultStateOfCopy = modelCopy->initSystem();
    // Compare state
    //defaultState.getY().dump("defaultState:Y");
    //ASSERT ((defaultState.getY()-defaultStateOfCopy.getY()).norm() < 1e-7);

    //  Now delete original model and make sure copy can stand
    Model *cloneModel = modelCopy->clone();

    ASSERT(*model == *cloneModel);
    ASSERT(model->getActuators().getSize() ==
           cloneModel->getActuators().getSize());

    // Compare state again

    //SimTK::State& defaultStateOfCopy2 = newModel->initSystem();
    // Compare state
    //ASSERT ((defaultState.getY()-defaultStateOfCopy2.getY()).norm() < 1e-7);
    //ASSERT ((defaultState.getZ()-defaultStateOfCopy2.getZ()).norm() < 1e-7);

    std::string latestFile = "lastest_" + fileName;
    modelCopy->print(latestFile);
    modelCopy->finalizeFromProperties();

    Model* modelSerialized = new Model(latestFile);

    ASSERT(*model == *modelSerialized);
    ASSERT(*modelSerialized == *modelCopy);

    int nb = modelSerialized->getNumBodies();

    const PhysicalFrame* physFrame = nullptr;
    if(modelSerialized->hasComponent<PhysicalFrame>("./" + physicalFrameName)){
        physFrame = &modelSerialized
            ->getComponent<PhysicalFrame>("./" + physicalFrameName);
    }
    else {
        physFrame = &modelSerialized
            ->getComponent<PhysicalFrame>("./bodyset/" + physicalFrameName);
    }

    int ng = physFrame->getProperty_attached_geometry().size();

    ASSERT(nb == nbod);
    ASSERT(ng == ngeom);

    delete model;
    delete modelCopy;
    delete cloneModel;
    delete modelSerialized;

    // New memory footprint.
    const size_t mem2 = getCurrentRSS();
    // Increase in memory footprint.
    const int64_t memory_increase = mem2 > mem1 ? mem2-mem1 : 0;

    cout << "Memory increase AFTER copy and init and delete:  "
         << double(memory_increase)/mem1*100 << "%." << endl;
}
<commit_msg>Update comments in test to reflect that Model::print() must be const<commit_after>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  testModelCopy.cpp                         *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Ayman Habib                                                     *
 *                                                                            *
 * 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 <stdint.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

// Test copying, serializing and deserializing models and verify
// that the number of bodies (nbods) and the number of attached geometry
// (ngeom) on a given PhysicalFrame (by name) are preserved.
void testCopyModel( const string& fileName, const int nbod,
                    const string& physicalFrameName, const int ngeom);

int main()
{
    try {

        // Test copying a simple property.
        {
            std::cout << "Test copying a simple property." << std::endl;
            Property<double>* a =
                Property<double>::TypeHelper::create("a", true);
            a->setValue(0.123456789);
            Property<double>* b =
                Property<double>::TypeHelper::create("b", true);
            b->setValue(10.0);

            b->assign(*a);

            cout << "b = " << b->toString() << endl;
            ASSERT(*a == *b);
        }

        // Test copying a an Object property.
        {
            std::cout << "Test copying a object property." << std::endl;
            Body A("A", 0.12345, SimTK::Vec3(0.1, 0.2, 0.3),
                SimTK::Inertia(0.33, 0.22, 0.11));
            Body B;

            Property<Body>* a = Property<Body>::TypeHelper::create("a", true);
            a->setValue(A);
            Property<Body>* b = Property<Body>::TypeHelper::create("b", true);
            b->setValue(B);

            b->assign(*a);

            cout << "b = " << b->toString() << endl;
            ASSERT(*a == *b);

            B = A;
            ASSERT(B == A);
        }

        Model arm("arm26.osim");
        Model armAssigned;

        armAssigned = arm;
        ASSERT(armAssigned == arm);

        LoadOpenSimLibrary("osimActuators");
        testCopyModel("arm26.osim", 2, "ground", 6);
        testCopyModel("Neck3dof_point_constraint.osim", 25, "spine", 1);
    }
    catch (const Exception& e) {
        cout << e.what() << endl;
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}

void testCopyModel(const string& fileName, const int nbod,
    const string& physicalFrameName, const int ngeom)
{
    const size_t mem0 = getCurrentRSS();

    // Automatically finalizes properties by default when loading from file
    Model* model = new Model(fileName);

    // Catch a possible decrease in the memory footprint, which will cause
    // size_t (unsigned int) to wrap through zero.
    const size_t mem1 = getCurrentRSS();
    const size_t increaseInMemory = mem1 > mem0 ? mem1-mem0 : 0;

    cout << "Memory use of '" << fileName <<"' model: " << increaseInMemory/1024
         << "KB" << endl;

    Model *test = nullptr;
    for (int i = 0; i < 10; ++i){
        test = new Model(fileName);
        delete test;
    }
    // verify that the print is const and has no side-effects on the model
    model->print("clone_" + fileName);

    Model* modelCopy = new Model(*model);
    modelCopy->finalizeFromProperties();
    // At this point properties should all match. assert that
    ASSERT(*model==*modelCopy);
    ASSERT(model->getActuators().getSize() ==
           modelCopy->getActuators().getSize());

    //SimTK::State& defaultStateOfCopy = modelCopy->initSystem();
    // Compare state
    //defaultState.getY().dump("defaultState:Y");
    //ASSERT ((defaultState.getY()-defaultStateOfCopy.getY()).norm() < 1e-7);

    //  Now delete original model and make sure copy can stand
    Model *cloneModel = modelCopy->clone();

    ASSERT(*model == *cloneModel);
    ASSERT(model->getActuators().getSize() ==
           cloneModel->getActuators().getSize());

    // Compare state again

    //SimTK::State& defaultStateOfCopy2 = newModel->initSystem();
    // Compare state
    //ASSERT ((defaultState.getY()-defaultStateOfCopy2.getY()).norm() < 1e-7);
    //ASSERT ((defaultState.getZ()-defaultStateOfCopy2.getZ()).norm() < 1e-7);

    std::string latestFile = "lastest_" + fileName;
    modelCopy->print(latestFile);
    modelCopy->finalizeFromProperties();

    Model* modelSerialized = new Model(latestFile);

    ASSERT(*model == *modelSerialized);
    ASSERT(*modelSerialized == *modelCopy);

    int nb = modelSerialized->getNumBodies();

    const PhysicalFrame* physFrame = nullptr;
    if(modelSerialized->hasComponent<PhysicalFrame>("./" + physicalFrameName)){
        physFrame = &modelSerialized
            ->getComponent<PhysicalFrame>("./" + physicalFrameName);
    }
    else {
        physFrame = &modelSerialized
            ->getComponent<PhysicalFrame>("./bodyset/" + physicalFrameName);
    }

    int ng = physFrame->getProperty_attached_geometry().size();

    ASSERT(nb == nbod);
    ASSERT(ng == ngeom);

    delete model;
    delete modelCopy;
    delete cloneModel;
    delete modelSerialized;

    // New memory footprint.
    const size_t mem2 = getCurrentRSS();
    // Increase in memory footprint.
    const int64_t memory_increase = mem2 > mem1 ? mem2-mem1 : 0;

    cout << "Memory increase AFTER copy and init and delete:  "
         << double(memory_increase)/mem1*100 << "%." << endl;
}
<|endoftext|>


<commit_before>/*
 * DistanceGTest.cpp
 *
 *  Created on: Sep 04, 2015
 *      Author: Maximilian Vogel
 */
#ifndef NOGTEST

#include "DistanceGTest.h"

#include "../Diameter.h"
#include "../EffectiveDiameter.h"

#include "../../generators/DorogovtsevMendesGenerator.h"
#include "../../generators/ErdosRenyiGenerator.h"
#include "../../io/METISGraphReader.h"

namespace NetworKit {

TEST_F(DistanceGTest, testVertexDiameterPedantically) {
    DorogovtsevMendesGenerator generator(1000);
    Graph G1 = generator.generate();
    Graph G = Graph(G1, true, false);
    count vd = Diameter::estimatedVertexDiameterPedantic(G);
    EXPECT_EQ(1000, vd);
}

TEST_F(DistanceGTest, testExactDiameter) {

   using namespace std;

   vector<pair<string, count>> testInstances= {pair<string, count>("lesmis", 14),
                                               pair<string, count>("jazz", 6),
                                               pair<string, count>("celegans_metabolic", 7)
                                              };

   for (auto testInstance : testInstances) {
       METISGraphReader reader;
       Graph G = reader.read("input/" + testInstance.first + ".graph");
       count diameter = Diameter::exactDiameter(G);
       EXPECT_EQ(diameter, testInstance.second);
   }
}

TEST_F(DistanceGTest, testEstimatedDiameterRange) {

   using namespace std;

   vector<pair<string, count>> testInstances= {
                                               pair<string, count>("celegans_metabolic", 7),
                                               pair<string, count>("jazz", 6)
                                              };

   for (auto testInstance : testInstances) {
       METISGraphReader reader;
       Graph G = reader.read("input/" + testInstance.first + ".graph");
       std::pair<count, count> range = Diameter::estimatedDiameterRange(G, 0.1);
       EXPECT_GE(testInstance.second, range.first);
       EXPECT_LE(testInstance.second, range.second);
   }
}
TEST_F(DistanceGTest, testPedanticDiameterErdos) {
	count n = 5000;
	ErdosRenyiGenerator gen(n,0.001);
	Graph G1 = gen.generate();
	count diameter = Diameter::estimatedVertexDiameterPedantic(G1);
	ASSERT_LE(diameter, n);
}

TEST_F(DistanceGTest, testEffectiveDiameter) {

using namespace std;

vector<string> testInstances= {"celegans_metabolic", "jazz", "lesmis"};

for (auto testInstance : testInstances) {
	METISGraphReader reader;
	Graph G = reader.read("input/" + testInstance + ".graph");
	double effective = EffectiveDiameter::effectiveDiameter(G);
	count exact = Diameter::estimatedDiameterRange(G, 0).first;
	EXPECT_LE(effective, exact);
}
}

TEST_F(DistanceGTest, testEffectiveDiameterExact) {

using namespace std;

vector<string> testInstances= {"celegans_metabolic", "jazz", "lesmis"};

for (auto testInstance : testInstances) {
	METISGraphReader reader;
	Graph G = reader.read("input/" + testInstance + ".graph");
	double effective = EffectiveDiameter::effectiveDiameterExact(G);
	count exact = Diameter::estimatedDiameterRange(G, 0).first;
	EXPECT_LE(effective, exact);
}

const double tol = 1e-3;

/* Graph: n=20, threshold: 20*0.9 = 18 nodes
	1--3--5--7---9
	|  |  |  |   |
	2--4--6--8--10
		|     |
		11----12
			|
		13--14--15
			|
		18--16--17--19
				|
				20
Number of steps needed per node: (1-20)
(7+6+6+5+6+5+5+4+6+5+4+4+5+4+5+5+6+6+7+7) / 20 = 5.4
*/
	count n1 = 20;
	Graph G1(n1);

	G1.addEdge(0,1);
	G1.addEdge(0,2);
	G1.addEdge(1,3);
	G1.addEdge(2,3);
	G1.addEdge(2,4);
	G1.addEdge(3,5);
	G1.addEdge(3,10);
	G1.addEdge(4,5);
	G1.addEdge(4,6);
	G1.addEdge(5,7);
	G1.addEdge(6,8);
	G1.addEdge(6,7);
	G1.addEdge(7,9);
	G1.addEdge(7,11);
	G1.addEdge(8,9);
	G1.addEdge(10,11);
	G1.addEdge(11,13);
	G1.addEdge(12,13);
	G1.addEdge(13,14);
	G1.addEdge(13,15);
	G1.addEdge(15,16);
	G1.addEdge(15,17);
	G1.addEdge(16,18);
	G1.addEdge(16,19);

	double effective1 = EffectiveDiameter::effectiveDiameterExact(G1);
	EXPECT_NEAR(5.4, effective1, tol);

	/* Graph: n=21, threshold: 21*0.9 = 18.9 => 19 nodes
				13---------------3
					|               |
				---14--12--|        |
				|   |   |  |        |
	1--21--18--16--15   |  |        |
				|       |  |        |
		20--17------10--8        |
				|       |  |        |
			19       9--7--5--6--4--11
									|
									2
Number of steps needed per node: (1-21)
(8+7+5+6+6+6+5+5+5+5+7+5+4+4+5+5+5+6+6+6+7) / 21 = 5.619047
*/
	count n2 = 21;
	Graph G2(n2);

	G2.addEdge(0,20);
	G2.addEdge(1,3);
	G2.addEdge(2,3);
	G2.addEdge(2,12);
	G2.addEdge(3,5);
	G2.addEdge(3,10);
	G2.addEdge(4,5);
	G2.addEdge(4,6);
	G2.addEdge(6,7);
	G2.addEdge(6,8);
	G2.addEdge(7,9);
	G2.addEdge(7,11);
	G2.addEdge(8,9);
	G2.addEdge(9,11);
	G2.addEdge(9,16);
	G2.addEdge(11,13);
	G2.addEdge(12,13);
	G2.addEdge(13,14);
	G2.addEdge(13,15);
	G2.addEdge(14,15);
	G2.addEdge(15,16);
	G2.addEdge(15,17);
	G2.addEdge(16,18);
	G2.addEdge(16,19);
	G2.addEdge(17,20);

	double effective2 = EffectiveDiameter::effectiveDiameterExact(G2);
	EXPECT_NEAR(5.619047, effective2, tol);
}

TEST_F(DistanceGTest, testHopPlot) {
	using namespace std;

	vector<string> testInstances= {"celegans_metabolic", "power", "lesmis"};

	const double tol = 1e-2;

	for (auto& testInstance : testInstances) {
		METISGraphReader reader;
		Graph G = reader.read("input/" + testInstance + ".graph");
		map<count, double> hopPlot = EffectiveDiameter::hopPlot(G);
		for (count i=1; i < hopPlot.size(); i++) {
			EXPECT_LE(hopPlot[i-1], hopPlot[i]+tol);
		}
	}
}

} /* namespace NetworKit */

#endif /*NOGTEST */
<commit_msg>DistanceGTest: use exact diameter (supports weighted graphs)<commit_after>/*
 * DistanceGTest.cpp
 *
 *  Created on: Sep 04, 2015
 *      Author: Maximilian Vogel
 */
#ifndef NOGTEST

#include "DistanceGTest.h"

#include "../Diameter.h"
#include "../EffectiveDiameter.h"

#include "../../generators/DorogovtsevMendesGenerator.h"
#include "../../generators/ErdosRenyiGenerator.h"
#include "../../io/METISGraphReader.h"

namespace NetworKit {

TEST_F(DistanceGTest, testVertexDiameterPedantically) {
    DorogovtsevMendesGenerator generator(1000);
    Graph G1 = generator.generate();
    Graph G = Graph(G1, true, false);
    count vd = Diameter::estimatedVertexDiameterPedantic(G);
    EXPECT_EQ(1000, vd);
}

TEST_F(DistanceGTest, testExactDiameter) {

   using namespace std;

   vector<pair<string, count>> testInstances= {pair<string, count>("lesmis", 14),
                                               pair<string, count>("jazz", 6),
                                               pair<string, count>("celegans_metabolic", 7)
                                              };

   for (auto testInstance : testInstances) {
       METISGraphReader reader;
       Graph G = reader.read("input/" + testInstance.first + ".graph");
       count diameter = Diameter::exactDiameter(G);
       EXPECT_EQ(diameter, testInstance.second);
   }
}

TEST_F(DistanceGTest, testEstimatedDiameterRange) {

   using namespace std;

   vector<pair<string, count>> testInstances= {
                                               pair<string, count>("celegans_metabolic", 7),
                                               pair<string, count>("jazz", 6)
                                              };

   for (auto testInstance : testInstances) {
       METISGraphReader reader;
       Graph G = reader.read("input/" + testInstance.first + ".graph");
       std::pair<count, count> range = Diameter::estimatedDiameterRange(G, 0.1);
       EXPECT_GE(testInstance.second, range.first);
       EXPECT_LE(testInstance.second, range.second);
   }
}
TEST_F(DistanceGTest, testPedanticDiameterErdos) {
	count n = 5000;
	ErdosRenyiGenerator gen(n,0.001);
	Graph G1 = gen.generate();
	count diameter = Diameter::estimatedVertexDiameterPedantic(G1);
	ASSERT_LE(diameter, n);
}

TEST_F(DistanceGTest, testEffectiveDiameter) {

using namespace std;

vector<string> testInstances= {"celegans_metabolic", "jazz", "lesmis"};

for (auto testInstance : testInstances) {
	METISGraphReader reader;
	Graph G = reader.read("input/" + testInstance + ".graph");
	double effective = EffectiveDiameter::effectiveDiameter(G);
	count exact = Diameter::exactDiameter(G);
	EXPECT_LE(effective, exact);
}
}

TEST_F(DistanceGTest, testEffectiveDiameterExact) {

using namespace std;

vector<string> testInstances= {"celegans_metabolic", "jazz", "lesmis"};

for (auto testInstance : testInstances) {
	METISGraphReader reader;
	Graph G = reader.read("input/" + testInstance + ".graph");
	double effective = EffectiveDiameter::effectiveDiameterExact(G);
	count exact = Diameter::exactDiameter(G);
	EXPECT_LE(effective, exact);
}

const double tol = 1e-3;

/* Graph: n=20, threshold: 20*0.9 = 18 nodes
	1--3--5--7---9
	|  |  |  |   |
	2--4--6--8--10
		|     |
		11----12
			|
		13--14--15
			|
		18--16--17--19
				|
				20
Number of steps needed per node: (1-20)
(7+6+6+5+6+5+5+4+6+5+4+4+5+4+5+5+6+6+7+7) / 20 = 5.4
*/
	count n1 = 20;
	Graph G1(n1);

	G1.addEdge(0,1);
	G1.addEdge(0,2);
	G1.addEdge(1,3);
	G1.addEdge(2,3);
	G1.addEdge(2,4);
	G1.addEdge(3,5);
	G1.addEdge(3,10);
	G1.addEdge(4,5);
	G1.addEdge(4,6);
	G1.addEdge(5,7);
	G1.addEdge(6,8);
	G1.addEdge(6,7);
	G1.addEdge(7,9);
	G1.addEdge(7,11);
	G1.addEdge(8,9);
	G1.addEdge(10,11);
	G1.addEdge(11,13);
	G1.addEdge(12,13);
	G1.addEdge(13,14);
	G1.addEdge(13,15);
	G1.addEdge(15,16);
	G1.addEdge(15,17);
	G1.addEdge(16,18);
	G1.addEdge(16,19);

	double effective1 = EffectiveDiameter::effectiveDiameterExact(G1);
	EXPECT_NEAR(5.4, effective1, tol);

	/* Graph: n=21, threshold: 21*0.9 = 18.9 => 19 nodes
				13---------------3
					|               |
				---14--12--|        |
				|   |   |  |        |
	1--21--18--16--15   |  |        |
				|       |  |        |
		20--17------10--8        |
				|       |  |        |
			19       9--7--5--6--4--11
									|
									2
Number of steps needed per node: (1-21)
(8+7+5+6+6+6+5+5+5+5+7+5+4+4+5+5+5+6+6+6+7) / 21 = 5.619047
*/
	count n2 = 21;
	Graph G2(n2);

	G2.addEdge(0,20);
	G2.addEdge(1,3);
	G2.addEdge(2,3);
	G2.addEdge(2,12);
	G2.addEdge(3,5);
	G2.addEdge(3,10);
	G2.addEdge(4,5);
	G2.addEdge(4,6);
	G2.addEdge(6,7);
	G2.addEdge(6,8);
	G2.addEdge(7,9);
	G2.addEdge(7,11);
	G2.addEdge(8,9);
	G2.addEdge(9,11);
	G2.addEdge(9,16);
	G2.addEdge(11,13);
	G2.addEdge(12,13);
	G2.addEdge(13,14);
	G2.addEdge(13,15);
	G2.addEdge(14,15);
	G2.addEdge(15,16);
	G2.addEdge(15,17);
	G2.addEdge(16,18);
	G2.addEdge(16,19);
	G2.addEdge(17,20);

	double effective2 = EffectiveDiameter::effectiveDiameterExact(G2);
	EXPECT_NEAR(5.619047, effective2, tol);
}

TEST_F(DistanceGTest, testHopPlot) {
	using namespace std;

	vector<string> testInstances= {"celegans_metabolic", "power", "lesmis"};

	const double tol = 1e-2;

	for (auto& testInstance : testInstances) {
		METISGraphReader reader;
		Graph G = reader.read("input/" + testInstance + ".graph");
		map<count, double> hopPlot = EffectiveDiameter::hopPlot(G);
		for (count i=1; i < hopPlot.size(); i++) {
			EXPECT_LE(hopPlot[i-1], hopPlot[i]+tol);
		}
	}
}

} /* namespace NetworKit */

#endif /*NOGTEST */
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm 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.
 *
 * glosm 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 glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#if defined(__APPLE__)
#	include <OpenGL/gl.h>
#	include <OpenGL/glu.h>
#else
#	include <GL/gl.h>
#	include <GL/glu.h>
#endif

#include <stdio.h>

#include <glosm/Math.hh>
#include <glosm/Projection.hh>
#include <glosm/geomath.h>

#include <glosm/FirstPersonViewer.hh>

FirstPersonViewer::FirstPersonViewer(): pos_(), yaw_(0), pitch_(0), fov_(90.0), aspect_(1.0) {
}

FirstPersonViewer::FirstPersonViewer(const Vector3i& pos): pos_(pos), yaw_(0), pitch_(0), fov_(90.0), aspect_(1.0) {
}

FirstPersonViewer::FirstPersonViewer(const Vector3i& pos, float yaw, float pitch): pos_(pos), yaw_(yaw), pitch_(pitch), fov_(90.0), aspect_(1.0) {
}

void FirstPersonViewer::SetupViewerMatrix(const Projection& projection) const {
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* length of a meter in local units */
	float meterlen = projection.Project(pos_.Flattened() + Vector3i(0, 0, GEOM_UNITSINMETER), pos_.Flattened()).z;

	/* viewer height in meters */
	float height = pos_.z / (float)GEOM_UNITSINMETER;
	if (height < 100.0f)
		height = 100.0f;

	/* viewing distances is [1meter..100km] at under 100m height
	 * and increases linearly with going higher */
	float near = 0.01f * height * meterlen;
	float far = 1000.0f * height * meterlen;

	gluPerspective(fov_ / M_PI * 180.0f, aspect_, near, far);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	Vector3f dir = GetDirection();
	Vector3f up = Vector3f(0.0f, 0.0f, 1.0f);

	gluLookAt(0.0f, 0.0f, 0.0f, dir.x, dir.y, dir.z, up.x, up.y, up.z);
}

Vector3i FirstPersonViewer::GetPos(const Projection& /* unused*/) const {
	return pos_;
}

void FirstPersonViewer::SetFov(float fov) {
	fov_ = fov;
}

void FirstPersonViewer::SetAspect(float aspect) {
	aspect_ = aspect;
}

Vector3f FirstPersonViewer::GetDirection() const {
	return Vector3f::FromYawPitch(yaw_, pitch_);
}

void FirstPersonViewer::SetPos(Vector3i pos) {
	pos_ = pos;
}

void FirstPersonViewer::Move(int flags, float speed, float time) {
	/* 1 meter direction-collinear vector in OSM coordinate space */
	Vector3f dirbasis = Vector3f(
			GEOM_LONSPAN / WGS84_EARTH_EQ_LENGTH / cos(pos_.y * GEOM_DEG_TO_RAD),
			GEOM_LONSPAN / WGS84_EARTH_EQ_LENGTH,
			GEOM_UNITSINMETER
		);

	Vector3f dir = GetDirection();
	Vector3f worldup = Vector3f(0.0f, 0.0f, 1.0f);
	Vector3f right = dir.CrossProduct(worldup).Normalized();
	Vector3f relup = right.CrossProduct(dir).Normalized();

	if (flags & FORWARD)
		pos_ += dirbasis * dir * speed * time;
	if (flags & BACKWARD)
		pos_ -= dirbasis * dir * speed * time;
	if (flags & LEFT)
		pos_ -= dirbasis * right * speed * time;
	if (flags & RIGHT)
		pos_ += dirbasis * right * speed * time;
	if (flags & UP)
		pos_ += dirbasis * relup * speed * time;
	if (flags & DOWN)
		pos_ -= dirbasis * relup * speed * time;
	if (flags & HIGHER)
		pos_ += dirbasis * worldup * speed * time;
	if (flags & LOWER)
		pos_ -= dirbasis * worldup * speed * time;

	/* Wrap around */
	if (pos_.x > GEOM_MAXLON)
		pos_.x -= GEOM_LONSPAN;
	if (pos_.x < GEOM_MINLON)
		pos_.x += GEOM_LONSPAN;

	/* Limit poles */
	if (pos_.y > GEOM_MERCATOR_MAXLAT)
		pos_.y = GEOM_MERCATOR_MAXLAT;
	if (pos_.y < GEOM_MERCATOR_MINLAT)
		pos_.y = GEOM_MERCATOR_MINLAT;

	/* Limit height */
	if (pos_.z < 0.0)
		pos_.z = 0.0;
	if (pos_.z > std::numeric_limits<osmint_t>::max())
		pos_.z = std::numeric_limits<osmint_t>::max();
}

void FirstPersonViewer::HardRotate(float yawdelta, float pitchdelta) {
	static const float PitchLimit = M_PI/2.0*0.9;

	yaw_ += yawdelta;
	pitch_ += pitchdelta;

	if (pitch_ > PitchLimit)
		pitch_ = PitchLimit;
	if (pitch_ < -PitchLimit)
		pitch_ = -PitchLimit;
	if (yaw_ > M_PI)
		yaw_ -= M_PI*2.0;
	if (yaw_ < -M_PI)
		yaw_ += M_PI*2.0;
}

Vector3d& FirstPersonViewer::MutablePos() {
	return pos_;
}
<commit_msg>Fix namespace clashes (?)<commit_after>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm 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.
 *
 * glosm 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 glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#if defined(__APPLE__)
#	include <OpenGL/gl.h>
#	include <OpenGL/glu.h>
#else
#	include <GL/gl.h>
#	include <GL/glu.h>
#endif

#include <stdio.h>

#include <glosm/Math.hh>
#include <glosm/Projection.hh>
#include <glosm/geomath.h>

#include <glosm/FirstPersonViewer.hh>

FirstPersonViewer::FirstPersonViewer(): pos_(), yaw_(0), pitch_(0), fov_(90.0), aspect_(1.0) {
}

FirstPersonViewer::FirstPersonViewer(const Vector3i& pos): pos_(pos), yaw_(0), pitch_(0), fov_(90.0), aspect_(1.0) {
}

FirstPersonViewer::FirstPersonViewer(const Vector3i& pos, float yaw, float pitch): pos_(pos), yaw_(yaw), pitch_(pitch), fov_(90.0), aspect_(1.0) {
}

void FirstPersonViewer::SetupViewerMatrix(const Projection& projection) const {
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* length of a meter in local units */
	float meterlen = projection.Project(pos_.Flattened() + Vector3i(0, 0, GEOM_UNITSINMETER), pos_.Flattened()).z;

	/* viewer height in meters */
	float height = pos_.z / (float)GEOM_UNITSINMETER;
	if (height < 100.0f)
		height = 100.0f;

	/* viewing distances is [1meter..100km] at under 100m height
	 * and increases linearly with going higher */
	float znear = 0.01f * height * meterlen;
	float zfar = 1000.0f * height * meterlen;

	gluPerspective(fov_ / M_PI * 180.0f, aspect_, znear, zfar);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	Vector3f dir = GetDirection();
	Vector3f up = Vector3f(0.0f, 0.0f, 1.0f);

	gluLookAt(0.0f, 0.0f, 0.0f, dir.x, dir.y, dir.z, up.x, up.y, up.z);
}

Vector3i FirstPersonViewer::GetPos(const Projection& /* unused*/) const {
	return pos_;
}

void FirstPersonViewer::SetFov(float fov) {
	fov_ = fov;
}

void FirstPersonViewer::SetAspect(float aspect) {
	aspect_ = aspect;
}

Vector3f FirstPersonViewer::GetDirection() const {
	return Vector3f::FromYawPitch(yaw_, pitch_);
}

void FirstPersonViewer::SetPos(Vector3i pos) {
	pos_ = pos;
}

void FirstPersonViewer::Move(int flags, float speed, float time) {
	/* 1 meter direction-collinear vector in OSM coordinate space */
	Vector3f dirbasis = Vector3f(
			GEOM_LONSPAN / WGS84_EARTH_EQ_LENGTH / cos(pos_.y * GEOM_DEG_TO_RAD),
			GEOM_LONSPAN / WGS84_EARTH_EQ_LENGTH,
			GEOM_UNITSINMETER
		);

	Vector3f dir = GetDirection();
	Vector3f worldup = Vector3f(0.0f, 0.0f, 1.0f);
	Vector3f right = dir.CrossProduct(worldup).Normalized();
	Vector3f relup = right.CrossProduct(dir).Normalized();

	if (flags & FORWARD)
		pos_ += dirbasis * dir * speed * time;
	if (flags & BACKWARD)
		pos_ -= dirbasis * dir * speed * time;
	if (flags & LEFT)
		pos_ -= dirbasis * right * speed * time;
	if (flags & RIGHT)
		pos_ += dirbasis * right * speed * time;
	if (flags & UP)
		pos_ += dirbasis * relup * speed * time;
	if (flags & DOWN)
		pos_ -= dirbasis * relup * speed * time;
	if (flags & HIGHER)
		pos_ += dirbasis * worldup * speed * time;
	if (flags & LOWER)
		pos_ -= dirbasis * worldup * speed * time;

	/* Wrap around */
	if (pos_.x > GEOM_MAXLON)
		pos_.x -= GEOM_LONSPAN;
	if (pos_.x < GEOM_MINLON)
		pos_.x += GEOM_LONSPAN;

	/* Limit poles */
	if (pos_.y > GEOM_MERCATOR_MAXLAT)
		pos_.y = GEOM_MERCATOR_MAXLAT;
	if (pos_.y < GEOM_MERCATOR_MINLAT)
		pos_.y = GEOM_MERCATOR_MINLAT;

	/* Limit height */
	if (pos_.z < 0.0)
		pos_.z = 0.0;
	if (pos_.z > std::numeric_limits<osmint_t>::max())
		pos_.z = std::numeric_limits<osmint_t>::max();
}

void FirstPersonViewer::HardRotate(float yawdelta, float pitchdelta) {
	static const float PitchLimit = M_PI/2.0*0.9;

	yaw_ += yawdelta;
	pitch_ += pitchdelta;

	if (pitch_ > PitchLimit)
		pitch_ = PitchLimit;
	if (pitch_ < -PitchLimit)
		pitch_ = -PitchLimit;
	if (yaw_ > M_PI)
		yaw_ -= M_PI*2.0;
	if (yaw_ < -M_PI)
		yaw_ += M_PI*2.0;
}

Vector3d& FirstPersonViewer::MutablePos() {
	return pos_;
}
<|endoftext|>


<commit_before>#include "ADA_LIS3DH.h"

// #define NOISE_PWM
// #define NOISE_WIFI
#define NOISE_RTC

#ifdef NOISE_PWM
#include "ledctrl.h"
LedCtrl status_led;
#endif

#ifdef NOISE_WIFI
#define USE_SERIAL 1
#include "RTCLib.h"
#include "netcfg.h"
WiFiClient wifi_client;
MQTT_Client mqtt_client(wifi_client);
DateTime ltime(2017, 11, 11, 8, 0, 0);
#endif

#ifdef NOISE_RTC
#include "RTCLib.h"
RTC_DS3231 rtc;
#endif

// Initialize the accelerometer with the default parameter
// --> use default I2C address
ADA_LIS3DH accel_sensor = ADA_LIS3DH();

bool ext_int = false;

void accelReady() { ext_int = true; }

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Testing Accelerometer");

  if (!accel_sensor.begin(
          0x18)) {  // change this to 0x19 for alternative i2c address
    Serial.println("Couldnt start");
    while (1)
      ;
  }
  Serial.println("LIS3DH found!");

  // Set data rate
  accel_sensor.setDataRate(LIS3DH_DATARATE_25_HZ);

  // Set accelerometer range
  accel_sensor.setRange(LIS3DH_RANGE_2_G);

  // attach hardware interrupt
  pinMode(A2, INPUT_PULLUP);
  attachInterrupt(A2, accelReady, RISING);
  delay(1);
  accel_sensor.read();

#ifdef NOISE_PWM
  pwm_configure();
  status_led.pulse(5000);
#endif

#ifdef NOISE_WIFI
  // Configure pins for Adafruit ATWINC1500 Feather
  WiFi.setPins(8, 7, 4, 2);
  // Check for the presence of the shield
  Serial.println("Connecting to the Wifi module...");
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    return;  // don't continue
  }

  connect_wifi(wifi_client, status_led);
  mqtt_client.setServer(MQTT_SERVER, MQTT_PORT);
  if (!mqtt_client.connect_client()) {
    Serial.println("Failed to connect MQTT client!");
    while (1) {
      delay(20);
    }
  }
  Serial.println("MQTT client connected.");
  const char *msg = "Accel with WIFI test started.";
  mqtt_client.publish_timed_msg(ltime, TOPIC_MESSAGE, msg);
#endif

#ifdef NOISE_RTC
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC!");
    while (1)
      ;
  }
#endif
}

void loop() {
  static unsigned long last = millis();

  if (ext_int) {
    // Serial.println("Reading data...");
    accel_sensor.read();
    // Serial.println("OK");
    Serial.print(accel_sensor.accel[0]);
    Serial.print("\t");
    // Serial.print(accel_sensor.accel[1]);
    // Serial.print("\t");
    Serial.print(accel_sensor.accel[2]);
    Serial.print("\t");
    if (accel_sensor.accel[2] < -400) {
      Serial.print("!!!");
    }
    // Serial.print("maxCount=");
    // Serial.print(accel_sensor.getMaxCount());
    // Serial.print("\t");
    // Serial.print("elapsed=");
    // Serial.print(now - last);
    Serial.println();
    ext_int = false;
  }
#ifdef NOISE_PWM
  status_led.update();
#endif

#ifdef NOISE_WIFI
  unsigned long now = millis();
  if (now - last > 2000) {
    mqtt_client.publish_timed_msg(ltime, TOPIC_HEARTBEAT, "ACCEL");
    last = now;
  }
  mqtt_client.loop();
#endif

#ifdef NOISE_RTC
  DateTime utc = rtc.now();
#endif

  delay(25);
}
<commit_msg>updated to work with the lates Accel class<commit_after>#include "accel.h"

// #define USE_PWM
// #define USE_RTC

#ifdef USE_PWM
#include "ledctrl.h"
#include "m0_hf_pwm.h"
LedCtrl& status_led = LedCtrl::Instance();
#endif

#ifdef USE_RTC
#include "RTCLib.h"
RTC_DS3231 rtc;
#endif

// Initialize the accelerometer with the default parameter
// --> use default I2C address
Accel accel_sensor;

bool ext_int = false;

void accelReady() { accel_sensor.data_ready = true; }

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Testing Accelerometer");

  if (!accel_sensor.begin(
          0x18)) {  // change this to 0x19 for alternative i2c address
    Serial.println("Couldnt start");
    while (1)
      ;
  }
  Serial.println("LIS3DH found!");

  // Set data rate
  accel_sensor.setDataRate(LIS3DH_DATARATE_10_HZ);

  // Set accelerometer range
  accel_sensor.setRange(LIS3DH_RANGE_2_G);

  // attach hardware interrupt
  pinMode(A2, INPUT_PULLUP);
  attachInterrupt(A2, accelReady, RISING);
  delay(1);
  accel_sensor.read();

#ifdef USE_PWM
  pwm_configure();
  status_led.pulse(5000);
#endif

#ifdef USE_RTC
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC!");
    while (1)
      ;
  }
#endif
}

void loop() {
  // static unsigned long last = millis();

  if (accel_sensor.data_ready) {
    // Serial.println("Reading data...");
    accel_sensor.process();
    if (accel_sensor.new_state) {
      Serial.println(ACCEL_STATES_NAMES[(uint8_t)accel_sensor.state]);
      accel_sensor.new_state = false;
    }
    // Serial.println("OK");
    Serial.print(accel_sensor.accel[0]);
    Serial.print("\t");
    // Serial.print(accel_sensor.accel[1]);
    // Serial.print("\t");
    Serial.print(accel_sensor.accel[2]);
    Serial.print("\t");
    if (accel_sensor.accel[2] < -400) {
      Serial.print("!!!");
    }
    // Serial.print("maxCount=");
    // Serial.print(accel_sensor.getMaxCount());
    // Serial.print("\t");
    // Serial.print("elapsed=");
    // Serial.print(now - last);
    Serial.println();
    ext_int = false;
  }

#ifdef USE_PWM
  status_led.update();
#endif

#ifdef USE_RTC
  DateTime utc = rtc.now();
  utc = utc + TimeSpan(1);
#endif

  delay(25);
}
<|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.
 *
 */

#ifdef MAIN_EXECUTABLE

#include <fstream>
#include "bitstream.h"
#include "command.h"
#include "design_utils.h"
#include "log.h"
#include "timing.h"
#include "util.h"

USING_NEXTPNR_NAMESPACE

class ECP5CommandHandler : public CommandHandler
{
  public:
    ECP5CommandHandler(int argc, char **argv);
    virtual ~ECP5CommandHandler(){};
    std::unique_ptr<Context> createContext(std::unordered_map<std::string,Property> &values) override;
    void setupArchContext(Context *ctx) override{};
    void customAfterLoad(Context *ctx) override;
    void validate() override;
    void customBitstream(Context *ctx) override;

  protected:
    po::options_description getArchOptions() override;
};

ECP5CommandHandler::ECP5CommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {}

po::options_description ECP5CommandHandler::getArchOptions()
{
    po::options_description specific("Architecture specific options");
    specific.add_options()("25k", "set device type to LFE5U-25F");
    specific.add_options()("45k", "set device type to LFE5U-45F");
    specific.add_options()("85k", "set device type to LFE5U-85F");
    specific.add_options()("um-25k", "set device type to LFE5UM-25F");
    specific.add_options()("um-45k", "set device type to LFE5UM-45F");
    specific.add_options()("um-85k", "set device type to LFE5UM-85F");
    specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F");
    specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F");
    specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F");

    specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)");
    specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)");

    specific.add_options()("basecfg", po::value<std::string>(),
                           "base chip configuration in Trellis text format (deprecated)");
    specific.add_options()("override-basecfg", po::value<std::string>(),
                           "base chip configuration in Trellis text format");
    specific.add_options()("textcfg", po::value<std::string>(), "textual configuration in Trellis format to write");

    specific.add_options()("lpf", po::value<std::vector<std::string>>(), "LPF pin constraint file(s)");
    specific.add_options()("lpf-allow-unconstrained", "don't require LPF file(s) to constrain all IO");

    return specific;
}
void ECP5CommandHandler::validate()
{
    if ((vm.count("25k") + vm.count("45k") + vm.count("85k")) > 1)
        log_error("Only one device type can be set\n");
}

void ECP5CommandHandler::customBitstream(Context *ctx)
{
    std::string basecfg;
    if (vm.count("basecfg")) {
        log_warning("--basecfg is deprecated.\nIf you are using a default baseconfig (from prjtrellis/misc/basecfgs), "
                    "these are now embedded in nextpnr - please remove --basecfg.\nIf you are using a non-standard "
                    "baseconfig in a special application, switch to using --override-basecfg.\n");
        basecfg = vm["basecfg"].as<std::string>();
    } else if (vm.count("override-basecfg")) {
        basecfg = vm["basecfg"].as<std::string>();
    }

    std::string textcfg;
    if (vm.count("textcfg"))
        textcfg = vm["textcfg"].as<std::string>();

    write_bitstream(ctx, basecfg, textcfg);
}

static std::string speedString(ArchArgs::SpeedGrade speed)
{
    switch(speed){
        case ArchArgs::SPEED_6: return "6";
        case ArchArgs::SPEED_7: return "7";
        case ArchArgs::SPEED_8: return "8";
        case ArchArgs::SPEED_8_5G: return "8";
    }
    return "";
}

std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<std::string,Property> &values)
{
    ArchArgs chipArgs;
    chipArgs.type = ArchArgs::NONE;

    if (vm.count("25k"))
        chipArgs.type = ArchArgs::LFE5U_25F;
    if (vm.count("45k"))
        chipArgs.type = ArchArgs::LFE5U_45F;
    if (vm.count("85k"))
        chipArgs.type = ArchArgs::LFE5U_85F;
    if (vm.count("um-25k"))
        chipArgs.type = ArchArgs::LFE5UM_25F;
    if (vm.count("um-45k"))
        chipArgs.type = ArchArgs::LFE5UM_45F;
    if (vm.count("um-85k"))
        chipArgs.type = ArchArgs::LFE5UM_85F;
    if (vm.count("um5g-25k"))
        chipArgs.type = ArchArgs::LFE5UM5G_25F;
    if (vm.count("um5g-45k"))
        chipArgs.type = ArchArgs::LFE5UM5G_45F;
    if (vm.count("um5g-85k"))
        chipArgs.type = ArchArgs::LFE5UM5G_85F;
    if (vm.count("package"))
        chipArgs.package = vm["package"].as<std::string>();

    if (vm.count("speed")) {
        int speed = vm["speed"].as<int>();
        switch (speed) {
        case 6:
            chipArgs.speed = ArchArgs::SPEED_6;
            break;
        case 7:
            chipArgs.speed = ArchArgs::SPEED_7;
            break;
        case 8:
            chipArgs.speed = ArchArgs::SPEED_8;
            break;
        default:
            log_error("Unsupported speed grade '%d'\n", speed);
        }
    } else {
        chipArgs.speed = ArchArgs::SPEED_6;
    }
    if (values.find("arch.name")!=values.end()) {
        std::string arch_name = values["arch.name"].str;
        if (arch_name != "ecp5")
            log_error("Unsuported architecture '%s'.\n", arch_name.c_str());
    }
    if (values.find("arch.type")!=values.end()) {
        std::string arch_type = values["arch.type"].str;
        if (chipArgs.type != ArchArgs::NONE)
            log_error("Overriding architecture is unsuported.\n");

        if (arch_type == "lfe5u_25f")
            chipArgs.type = ArchArgs::LFE5U_25F;
        if (arch_type == "lfe5u_45f")
            chipArgs.type = ArchArgs::LFE5U_45F;
        if (arch_type == "lfe5u_85f")
            chipArgs.type = ArchArgs::LFE5U_85F;
        if (arch_type == "lfe5um_25f")
            chipArgs.type = ArchArgs::LFE5UM_25F;
        if (arch_type == "lfe5um_45f")
            chipArgs.type = ArchArgs::LFE5UM_45F;
        if (arch_type == "lfe5um_85f")
            chipArgs.type = ArchArgs::LFE5UM_85F;
        if (arch_type == "lfe5um5g_25f")
            chipArgs.type = ArchArgs::LFE5UM5G_25F;
        if (arch_type == "lfe5um5g_45f")
            chipArgs.type = ArchArgs::LFE5UM5G_45F;
        if (arch_type == "lfe5um5g_85f")
            chipArgs.type = ArchArgs::LFE5UM5G_85F;

        if (chipArgs.type == ArchArgs::NONE)
            log_error("Unsuported FPGA type '%s'.\n",arch_type.c_str());
    }
    if (values.find("arch.package")!=values.end()) {
        if (vm.count("package"))
            log_error("Overriding architecture is unsuported.\n");
        chipArgs.package = values["arch.package"].str;
    }
    if (values.find("arch.speed")!=values.end()) {
        std::string arch_speed = values["arch.speed"].str;
        if (arch_speed == "6")
            chipArgs.speed = ArchArgs::SPEED_6;
        else if (arch_speed == "7")
            chipArgs.speed = ArchArgs::SPEED_7;
        else if (arch_speed == "8")
            chipArgs.speed = ArchArgs::SPEED_8;
        else
            log_error("Unsuported speed '%s'.\n",arch_speed.c_str());
    }
    if (chipArgs.type == ArchArgs::NONE)
        chipArgs.type = ArchArgs::LFE5U_45F;

    if (chipArgs.package.empty())
        chipArgs.package = "CABGA381";

    if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F ||
        chipArgs.type == ArchArgs::LFE5UM5G_85F) {
        if (chipArgs.speed != ArchArgs::SPEED_8)
            log_error("Only speed grade 8 is available for 5G parts\n");
        else
            chipArgs.speed = ArchArgs::SPEED_8_5G;
    }

    auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
    for(auto &val : values)
        ctx->settings[ctx->id(val.first)] = val.second;
    ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package;
    ctx->settings[ctx->id("arch.speed")] = speedString(ctx->archArgs().speed);
    return ctx;
}

void ECP5CommandHandler::customAfterLoad(Context *ctx)
{
    if (vm.count("lpf")) {
        std::vector<std::string> files = vm["lpf"].as<std::vector<std::string>>();
        for (const auto &filename : files) {
            std::ifstream in(filename);
            if (!in)
                log_error("failed to open LPF file '%s'\n", filename.c_str());
            if (!ctx->applyLPF(filename, in))
                log_error("failed to parse LPF file '%s'\n", filename.c_str());
        }

        for (auto cell : sorted(ctx->cells)) {
            CellInfo *ci = cell.second;
            if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
                ci->type == ctx->id("$nextpnr_iobuf")) {
                if (!ci->attrs.count(ctx->id("LOC"))) {
                    if (vm.count("lpf-allow-unconstrained"))
                        log_warning("IO '%s' is unconstrained in LPF and will be automatically placed\n",
                                    cell.first.c_str(ctx));
                    else
                        log_error("IO '%s' is unconstrained in LPF (override this error with "
                                  "--lpf-allow-unconstrained)\n",
                                  cell.first.c_str(ctx));
                }
            }
        }
    }
}

int main(int argc, char *argv[])
{
    ECP5CommandHandler handler(argc, argv);
    return handler.exec();
}

#endif
<commit_msg>default for 5G is speed 8<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.
 *
 */

#ifdef MAIN_EXECUTABLE

#include <fstream>
#include "bitstream.h"
#include "command.h"
#include "design_utils.h"
#include "log.h"
#include "timing.h"
#include "util.h"

USING_NEXTPNR_NAMESPACE

class ECP5CommandHandler : public CommandHandler
{
  public:
    ECP5CommandHandler(int argc, char **argv);
    virtual ~ECP5CommandHandler(){};
    std::unique_ptr<Context> createContext(std::unordered_map<std::string,Property> &values) override;
    void setupArchContext(Context *ctx) override{};
    void customAfterLoad(Context *ctx) override;
    void validate() override;
    void customBitstream(Context *ctx) override;

  protected:
    po::options_description getArchOptions() override;
};

ECP5CommandHandler::ECP5CommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {}

po::options_description ECP5CommandHandler::getArchOptions()
{
    po::options_description specific("Architecture specific options");
    specific.add_options()("25k", "set device type to LFE5U-25F");
    specific.add_options()("45k", "set device type to LFE5U-45F");
    specific.add_options()("85k", "set device type to LFE5U-85F");
    specific.add_options()("um-25k", "set device type to LFE5UM-25F");
    specific.add_options()("um-45k", "set device type to LFE5UM-45F");
    specific.add_options()("um-85k", "set device type to LFE5UM-85F");
    specific.add_options()("um5g-25k", "set device type to LFE5UM5G-25F");
    specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F");
    specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F");

    specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)");
    specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)");

    specific.add_options()("basecfg", po::value<std::string>(),
                           "base chip configuration in Trellis text format (deprecated)");
    specific.add_options()("override-basecfg", po::value<std::string>(),
                           "base chip configuration in Trellis text format");
    specific.add_options()("textcfg", po::value<std::string>(), "textual configuration in Trellis format to write");

    specific.add_options()("lpf", po::value<std::vector<std::string>>(), "LPF pin constraint file(s)");
    specific.add_options()("lpf-allow-unconstrained", "don't require LPF file(s) to constrain all IO");

    return specific;
}
void ECP5CommandHandler::validate()
{
    if ((vm.count("25k") + vm.count("45k") + vm.count("85k")) > 1)
        log_error("Only one device type can be set\n");
}

void ECP5CommandHandler::customBitstream(Context *ctx)
{
    std::string basecfg;
    if (vm.count("basecfg")) {
        log_warning("--basecfg is deprecated.\nIf you are using a default baseconfig (from prjtrellis/misc/basecfgs), "
                    "these are now embedded in nextpnr - please remove --basecfg.\nIf you are using a non-standard "
                    "baseconfig in a special application, switch to using --override-basecfg.\n");
        basecfg = vm["basecfg"].as<std::string>();
    } else if (vm.count("override-basecfg")) {
        basecfg = vm["basecfg"].as<std::string>();
    }

    std::string textcfg;
    if (vm.count("textcfg"))
        textcfg = vm["textcfg"].as<std::string>();

    write_bitstream(ctx, basecfg, textcfg);
}

static std::string speedString(ArchArgs::SpeedGrade speed)
{
    switch(speed){
        case ArchArgs::SPEED_6: return "6";
        case ArchArgs::SPEED_7: return "7";
        case ArchArgs::SPEED_8: return "8";
        case ArchArgs::SPEED_8_5G: return "8";
    }
    return "";
}

std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<std::string,Property> &values)
{
    ArchArgs chipArgs;
    chipArgs.type = ArchArgs::NONE;

    if (vm.count("25k"))
        chipArgs.type = ArchArgs::LFE5U_25F;
    if (vm.count("45k"))
        chipArgs.type = ArchArgs::LFE5U_45F;
    if (vm.count("85k"))
        chipArgs.type = ArchArgs::LFE5U_85F;
    if (vm.count("um-25k"))
        chipArgs.type = ArchArgs::LFE5UM_25F;
    if (vm.count("um-45k"))
        chipArgs.type = ArchArgs::LFE5UM_45F;
    if (vm.count("um-85k"))
        chipArgs.type = ArchArgs::LFE5UM_85F;
    if (vm.count("um5g-25k"))
        chipArgs.type = ArchArgs::LFE5UM5G_25F;
    if (vm.count("um5g-45k"))
        chipArgs.type = ArchArgs::LFE5UM5G_45F;
    if (vm.count("um5g-85k"))
        chipArgs.type = ArchArgs::LFE5UM5G_85F;
    if (vm.count("package"))
        chipArgs.package = vm["package"].as<std::string>();

    if (vm.count("speed")) {
        int speed = vm["speed"].as<int>();
        switch (speed) {
        case 6:
            chipArgs.speed = ArchArgs::SPEED_6;
            break;
        case 7:
            chipArgs.speed = ArchArgs::SPEED_7;
            break;
        case 8:
            chipArgs.speed = ArchArgs::SPEED_8;
            break;
        default:
            log_error("Unsupported speed grade '%d'\n", speed);
        }
    } else {
        if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F ||
            chipArgs.type == ArchArgs::LFE5UM5G_85F) {
            chipArgs.speed = ArchArgs::SPEED_8;
        } else
            chipArgs.speed = ArchArgs::SPEED_6;
    }
    if (values.find("arch.name")!=values.end()) {
        std::string arch_name = values["arch.name"].str;
        if (arch_name != "ecp5")
            log_error("Unsuported architecture '%s'.\n", arch_name.c_str());
    }
    if (values.find("arch.type")!=values.end()) {
        std::string arch_type = values["arch.type"].str;
        if (chipArgs.type != ArchArgs::NONE)
            log_error("Overriding architecture is unsuported.\n");

        if (arch_type == "lfe5u_25f")
            chipArgs.type = ArchArgs::LFE5U_25F;
        if (arch_type == "lfe5u_45f")
            chipArgs.type = ArchArgs::LFE5U_45F;
        if (arch_type == "lfe5u_85f")
            chipArgs.type = ArchArgs::LFE5U_85F;
        if (arch_type == "lfe5um_25f")
            chipArgs.type = ArchArgs::LFE5UM_25F;
        if (arch_type == "lfe5um_45f")
            chipArgs.type = ArchArgs::LFE5UM_45F;
        if (arch_type == "lfe5um_85f")
            chipArgs.type = ArchArgs::LFE5UM_85F;
        if (arch_type == "lfe5um5g_25f")
            chipArgs.type = ArchArgs::LFE5UM5G_25F;
        if (arch_type == "lfe5um5g_45f")
            chipArgs.type = ArchArgs::LFE5UM5G_45F;
        if (arch_type == "lfe5um5g_85f")
            chipArgs.type = ArchArgs::LFE5UM5G_85F;

        if (chipArgs.type == ArchArgs::NONE)
            log_error("Unsuported FPGA type '%s'.\n",arch_type.c_str());
    }
    if (values.find("arch.package")!=values.end()) {
        if (vm.count("package"))
            log_error("Overriding architecture is unsuported.\n");
        chipArgs.package = values["arch.package"].str;
    }
    if (values.find("arch.speed")!=values.end()) {
        std::string arch_speed = values["arch.speed"].str;
        if (arch_speed == "6")
            chipArgs.speed = ArchArgs::SPEED_6;
        else if (arch_speed == "7")
            chipArgs.speed = ArchArgs::SPEED_7;
        else if (arch_speed == "8")
            chipArgs.speed = ArchArgs::SPEED_8;
        else
            log_error("Unsuported speed '%s'.\n",arch_speed.c_str());
    }
    if (chipArgs.type == ArchArgs::NONE)
        chipArgs.type = ArchArgs::LFE5U_45F;

    if (chipArgs.package.empty())
        chipArgs.package = "CABGA381";

    if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F ||
        chipArgs.type == ArchArgs::LFE5UM5G_85F) {
        if (chipArgs.speed != ArchArgs::SPEED_8)
            log_error("Only speed grade 8 is available for 5G parts\n");
        else
            chipArgs.speed = ArchArgs::SPEED_8_5G;
    }

    auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
    for(auto &val : values)
        ctx->settings[ctx->id(val.first)] = val.second;
    ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package;
    ctx->settings[ctx->id("arch.speed")] = speedString(ctx->archArgs().speed);
    return ctx;
}

void ECP5CommandHandler::customAfterLoad(Context *ctx)
{
    if (vm.count("lpf")) {
        std::vector<std::string> files = vm["lpf"].as<std::vector<std::string>>();
        for (const auto &filename : files) {
            std::ifstream in(filename);
            if (!in)
                log_error("failed to open LPF file '%s'\n", filename.c_str());
            if (!ctx->applyLPF(filename, in))
                log_error("failed to parse LPF file '%s'\n", filename.c_str());
        }

        for (auto cell : sorted(ctx->cells)) {
            CellInfo *ci = cell.second;
            if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
                ci->type == ctx->id("$nextpnr_iobuf")) {
                if (!ci->attrs.count(ctx->id("LOC"))) {
                    if (vm.count("lpf-allow-unconstrained"))
                        log_warning("IO '%s' is unconstrained in LPF and will be automatically placed\n",
                                    cell.first.c_str(ctx));
                    else
                        log_error("IO '%s' is unconstrained in LPF (override this error with "
                                  "--lpf-allow-unconstrained)\n",
                                  cell.first.c_str(ctx));
                }
            }
        }
    }
}

int main(int argc, char *argv[])
{
    ECP5CommandHandler handler(argc, argv);
    return handler.exec();
}

#endif
<|endoftext|>