<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 OWNER 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.
 *
 *********************************************************************************/

#include <inviwo/core/util/logcentral.h>
#include <inviwo/core/util/stacktrace.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/processors/processor.h>
#include <inviwo/core/network/processornetwork.h>

namespace inviwo {

void Logger::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                          std::string msg, const char* file, const char* function, int line) {
    log("Processor " + processor->getIdentifier(), level, audience, file, function, line, msg);
}

void Logger::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                        const char* function, int line) {
    log("ProcessorNetwork", level, audience, file, function, line, msg);
}

ConsoleLogger::ConsoleLogger() : Logger() {}
ConsoleLogger::~ConsoleLogger() {}

void ConsoleLogger::log(std::string logSource, LogLevel logLevel, LogAudience audience,
                        const char* fileName, const char* functionName, int lineNumber,
                        std::string logMsg) {
    IVW_UNUSED_PARAM(fileName);
    IVW_UNUSED_PARAM(logLevel);
    IVW_UNUSED_PARAM(functionName);
    IVW_UNUSED_PARAM(lineNumber);
    std::cout << "(" << logSource << ") " << logMsg << std::endl;
}

FileLogger::FileLogger(std::string logPath) : Logger() {
    if (filesystem::getFileExtension(logPath) != "") {
        fileStream_ = new std::ofstream(logPath.c_str());
    } else {
        fileStream_ = new std::ofstream(logPath.append("/inviwo-log.html").c_str());
    }
    (*fileStream_) << "
Inviwo (V " << IVW_VERSION << ") Log File
"
                   << std::endl;
}

FileLogger::~FileLogger() {
    fileStream_->close();
    delete fileStream_;
}

void FileLogger::log(std::string logSource, LogLevel logLevel, LogAudience audience,
                     const char* fileName, const char* functionName, int lineNumber,
                     std::string logMsg) {
    IVW_UNUSED_PARAM(fileName);
    IVW_UNUSED_PARAM(logLevel);
    IVW_UNUSED_PARAM(functionName);
    IVW_UNUSED_PARAM(lineNumber);

    switch (logLevel) {
        case LogLevel::Info:
            (*fileStream_) << "
Info: ";
            break;

        case LogLevel::Warn:
            (*fileStream_) << "
Warn: ";
            break;

        case LogLevel::Error:
            (*fileStream_) << "
Error: ";
            break;
    }

    logMsg = htmlEncode(logMsg);

    replaceInString(logMsg, " ", " ");
    replaceInString(logMsg, "\n", "
");
    replaceInString(logMsg, "\t", "    ");

    (*fileStream_) << "(" << logSource << ":" << lineNumber << ") " << logMsg;
    (*fileStream_) << "
" << std::endl;
}

LogCentral::LogCentral() :
    logLevel_(LogLevel::Info),
    logStacktrace_(false) {}

LogCentral::~LogCentral() {
    for (auto& logger : loggers_) delete logger;
}

void LogCentral::registerLogger(Logger* logger) { loggers_.push_back(logger); }

void LogCentral::unregisterLogger(Logger* logger) {
    auto it = std::find(loggers_.begin(), loggers_.end(), logger);
    if (it != loggers_.end()) {
        delete logger;
        loggers_.erase(it);
    }
}

void LogCentral::log(std::string source, LogLevel level, LogAudience audience, const char* file,
                     const char* function, int line, std::string msg) {
    if (logStacktrace_ && level == LogLevel::Error && audience == LogAudience::Developer) {
        std::stringstream ss;
        ss << msg;

        std::vector<std::string> stacktrace = getStackTrace();
        // start at i == 3 to remove log and getStacktrace from stackgrace
        for (size_t i = 3; i < stacktrace.size(); ++i) {
            ss << std::endl << stacktrace[i];
        }
        // append an extra line break to easier seperate several stacktraces in a row
        ss << std::endl;

        msg = ss.str();
    }

    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->log(source, level, audience, file, function, line, msg);
        }
    }
}

void LogCentral::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                              std::string msg, const char* file, const char* function, int line) {
    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->logProcessor(processor, level, audience, msg, file, function, line);
        }
    }
}

void LogCentral::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                            const char* function, int line) {
    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->logNetwork(level, audience, msg, file, function, line);
        }
    }
}

void LogCentral::setLogStacktrace(const bool& logStacktrace) { logStacktrace_ = logStacktrace; }

bool LogCentral::getLogStacktrace() const { return logStacktrace_; }

void util::log(ExceptionContext context, std::string message, LogLevel level,
               LogAudience audience) {
    LogCentral::getPtr()->log(context.getCaller(), level, audience, context.getFile().c_str(),
                              context.getFunction().c_str(), context.getLine(), message);
}

}  // namespace<commit_msg>Core: ConsoleLogger now prints error messages to cerr instead of cout<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 OWNER 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.
 *
 *********************************************************************************/

#include <inviwo/core/util/logcentral.h>
#include <inviwo/core/util/stacktrace.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/processors/processor.h>
#include <inviwo/core/network/processornetwork.h>

namespace inviwo {

void Logger::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                          std::string msg, const char* file, const char* function, int line) {
    log("Processor " + processor->getIdentifier(), level, audience, file, function, line, msg);
}

void Logger::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                        const char* function, int line) {
    log("ProcessorNetwork", level, audience, file, function, line, msg);
}

ConsoleLogger::ConsoleLogger() : Logger() {}
ConsoleLogger::~ConsoleLogger() {}

void ConsoleLogger::log(std::string logSource, LogLevel logLevel, LogAudience audience,
                        const char* fileName, const char* functionName, int lineNumber,
                        std::string logMsg) {
    IVW_UNUSED_PARAM(fileName);
    IVW_UNUSED_PARAM(logLevel);
    IVW_UNUSED_PARAM(functionName);
    IVW_UNUSED_PARAM(lineNumber);
    if (logLevel == LogLevel::Error) {
        std::cerr << "(" << logSource << ") " << logMsg << std::endl;
    } else {
        std::cout << "(" << logSource << ") " << logMsg << std::endl;
    }
}

FileLogger::FileLogger(std::string logPath) : Logger() {
    if (filesystem::getFileExtension(logPath) != "") {
        fileStream_ = new std::ofstream(logPath.c_str());
    } else {
        fileStream_ = new std::ofstream(logPath.append("/inviwo-log.html").c_str());
    }
    (*fileStream_) << "
Inviwo (V " << IVW_VERSION << ") Log File
"
                   << std::endl;
}

FileLogger::~FileLogger() {
    fileStream_->close();
    delete fileStream_;
}

void FileLogger::log(std::string logSource, LogLevel logLevel, LogAudience audience,
                     const char* fileName, const char* functionName, int lineNumber,
                     std::string logMsg) {
    IVW_UNUSED_PARAM(fileName);
    IVW_UNUSED_PARAM(logLevel);
    IVW_UNUSED_PARAM(functionName);
    IVW_UNUSED_PARAM(lineNumber);

    switch (logLevel) {
        case LogLevel::Info:
            (*fileStream_) << "
Info: ";
            break;

        case LogLevel::Warn:
            (*fileStream_) << "
Warn: ";
            break;

        case LogLevel::Error:
            (*fileStream_) << "
Error: ";
            break;
    }

    logMsg = htmlEncode(logMsg);

    replaceInString(logMsg, " ", " ");
    replaceInString(logMsg, "\n", "
");
    replaceInString(logMsg, "\t", "    ");

    (*fileStream_) << "(" << logSource << ":" << lineNumber << ") " << logMsg;
    (*fileStream_) << "
" << std::endl;
}

LogCentral::LogCentral() :
    logLevel_(LogLevel::Info),
    logStacktrace_(false) {}

LogCentral::~LogCentral() {
    for (auto& logger : loggers_) delete logger;
}

void LogCentral::registerLogger(Logger* logger) { loggers_.push_back(logger); }

void LogCentral::unregisterLogger(Logger* logger) {
    auto it = std::find(loggers_.begin(), loggers_.end(), logger);
    if (it != loggers_.end()) {
        delete logger;
        loggers_.erase(it);
    }
}

void LogCentral::log(std::string source, LogLevel level, LogAudience audience, const char* file,
                     const char* function, int line, std::string msg) {
    if (logStacktrace_ && level == LogLevel::Error && audience == LogAudience::Developer) {
        std::stringstream ss;
        ss << msg;

        std::vector<std::string> stacktrace = getStackTrace();
        // start at i == 3 to remove log and getStacktrace from stackgrace
        for (size_t i = 3; i < stacktrace.size(); ++i) {
            ss << std::endl << stacktrace[i];
        }
        // append an extra line break to easier seperate several stacktraces in a row
        ss << std::endl;

        msg = ss.str();
    }

    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->log(source, level, audience, file, function, line, msg);
        }
    }
}

void LogCentral::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                              std::string msg, const char* file, const char* function, int line) {
    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->logProcessor(processor, level, audience, msg, file, function, line);
        }
    }
}

void LogCentral::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                            const char* function, int line) {
    if (level >= logLevel_) {
        for (const auto& logger : loggers_) {
            logger->logNetwork(level, audience, msg, file, function, line);
        }
    }
}

void LogCentral::setLogStacktrace(const bool& logStacktrace) { logStacktrace_ = logStacktrace; }

bool LogCentral::getLogStacktrace() const { return logStacktrace_; }

void util::log(ExceptionContext context, std::string message, LogLevel level,
               LogAudience audience) {
    LogCentral::getPtr()->log(context.getCaller(), level, audience, context.getFile().c_str(),
                              context.getFunction().c_str(), context.getLine(), message);
}

}  // namespace<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-----------------------------------------------------------------------------
/// \class AliMUONTriggerLut
///
/// Local Trigger Look Up Table
/// reading interface LUT data is stored into TH3S histograms and readout
/// from the Local Trigger algorithm
///
/// Histograms structure is :
/// X 234 bins, 1 to 235   = local board number
/// Y  31 bins, 0 to  31   = x strip
/// Z  31 bins, 0 to  31   = x deviation
/// content = Short_t      = y strip mask
///
///  overflow bin is used !
///
/// \author Philippe Crochet
//-----------------------------------------------------------------------------

#include "AliMUONTriggerLut.h"

#include "AliLog.h"

#include <TFile.h>
#include <TH3.h>
#include <TMap.h>
#include <TObjString.h>

/// \cond CLASSIMP
ClassImp(AliMUONTriggerLut)
/// \endcond

//----------------------------------------------------------------------
AliMUONTriggerLut::AliMUONTriggerLut()
    : TNamed(),
      fLptPlus(0),
      fLptMinu(0),
      fLptUnde(0),
      fHptPlus(0),
      fHptMinu(0),
      fHptUnde(0),
      fAptPlus(0),
      fAptMinu(0),
      fAptUnde(0),
  fMap(0x0)
{
/// ctor
}

//----------------------------------------------------------------------
AliMUONTriggerLut::~AliMUONTriggerLut()
{
/// Destructor

  delete fLptPlus;
  delete fLptMinu;
  delete fLptUnde;
  delete fHptPlus;
  delete fHptMinu;
  delete fHptUnde;
  delete fAptPlus;
  delete fAptMinu;
  delete fAptUnde;
  delete fMap;
}

//----------------------------------------------------------------------
Int_t
AliMUONTriggerLut::Compare(TH3* h1, TH3* h2) const
{
/// Return 0 if both histograms are strictly equal (at the bin-by-bin level)

  AliDebug(1,Form("h1 %s h2 %s",h1 ? h1->GetName() : "null", h2 ? h2->GetName() : "null"));

  if (!h1 || !h2)
  {
    return 0;
  }
  Int_t bin;
  for ( Int_t ix = 0; ix <= h1->GetNbinsX()+1; ix++ )
    for ( Int_t iy = 0; iy <= h1->GetNbinsY()+1; iy++ )
      for ( Int_t iz = 0; iz <= h1->GetNbinsZ()+1; iz++ )
	{
	  {
	    {
	      bin = h1->GetBin(ix,iy,iz);
	      Double_t x1 = h1->GetBinContent(bin);
	      Double_t x2 = h2->GetBinContent(bin);
	      if ( x1 != x2 ) return 0;
	    }
	  }
	}

  AliDebug(1,"same");

  return 1;
}

//----------------------------------------------------------------------
Int_t
AliMUONTriggerLut::Compare(const TObject* object) const
{
/// Return 0 if the two luts are strictly equal

  const AliMUONTriggerLut* lut = static_cast<const AliMUONTriggerLut*>(object);

  Int_t rvLpt(0);

  rvLpt += Compare(fLptPlus,lut->fLptPlus);
  rvLpt += Compare(fLptMinu,lut->fLptMinu);
  rvLpt += Compare(fLptUnde,lut->fLptUnde);

  Int_t rvHpt(0);

  rvHpt += Compare(fHptPlus,lut->fHptPlus);
  rvHpt += Compare(fHptMinu,lut->fHptMinu);
  rvHpt += Compare(fHptUnde,lut->fHptUnde);

  Int_t rv(0);

  rv += Compare(fAptPlus,lut->fAptPlus);
  rv += Compare(fAptMinu,lut->fAptMinu);
  rv += Compare(fAptUnde,lut->fAptUnde);

  AliDebug(1,Form("Same Lpt %d Hpt %d Apt %d",rvLpt,rvHpt,rv));

  if ( rvLpt == 3 && rvHpt == 3 )
  {
    return 0;
  }

  return 1;
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::ReadFromFile(const char* filename)
{
/// Return output of LuT for corresponding TH3S

  TFile f(filename);

  if ( f.IsZombie() )
  {
    AliFatal(Form("Could not open file %s",filename));
  }

  AliDebug(1,Form("filename=%s",filename));

  fLptPlus = (TH3*)(f.Get("LptPlus"));
  fLptMinu = (TH3*)(f.Get("LptMinu"));
  fLptUnde = (TH3*)(f.Get("LptUnde"));
  fHptPlus = (TH3*)(f.Get("HptPlus"));
  fHptMinu = (TH3*)(f.Get("HptMinu"));
  fHptUnde = (TH3*)(f.Get("HptUnde"));
  fAptPlus = (TH3*)(f.Get("AptPlus"));
  fAptMinu = (TH3*)(f.Get("AptMinu"));
  fAptUnde = (TH3*)(f.Get("AptUnde"));

  // insure we "detach" those histograms from file f
  fLptPlus->SetDirectory(0);
  fLptMinu->SetDirectory(0);
  fLptUnde->SetDirectory(0);
  fHptPlus->SetDirectory(0);
  fHptMinu->SetDirectory(0);
  fHptUnde->SetDirectory(0);
  fAptPlus->SetDirectory(0);
  fAptMinu->SetDirectory(0);
  fAptUnde->SetDirectory(0);

  RegisterHistos();
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::RegisterHistos()
{
/// Add histos to our internal map

  Add(fLptPlus);
  Add(fLptMinu);
  Add(fLptUnde);

  Add(fHptPlus);
  Add(fHptMinu);
  Add(fHptUnde);

  Add(fAptPlus);
  Add(fAptMinu);
  Add(fAptUnde);
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::Add(TH3* h)
{
  /// Update internal map
  if (!fMap)
  {
    fMap = new TMap;
    fMap->SetOwner(kTRUE);
  }

  if (h) fMap->Add(new TObjString(h->GetName()),h);
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::SetContent(const char* hname, Int_t icirc, UChar_t istripX,
                              UChar_t idev, Short_t value)
{
  /// Set the content of one bin of one histogram

  if (!fMap)
  {
    //..........................................circuit/stripX/deviation
    fLptPlus = new TH3S("LptPlus","LptPlus",234,0,234,31,0,31,31,0,31);
    fLptMinu = new TH3S("LptMinu","LptMinu",234,0,234,31,0,31,31,0,31);
    fLptUnde = new TH3S("LptUnde","LptUnde",234,0,234,31,0,31,31,0,31);

    fHptPlus = new TH3S("HptPlus","HptPlus",234,0,234,31,0,31,31,0,31);
    fHptMinu = new TH3S("HptMinu","HptMinu",234,0,234,31,0,31,31,0,31);
    fHptUnde = new TH3S("HptUnde","HptUnde",234,0,234,31,0,31,31,0,31);

    fAptPlus = new TH3S("AptPlus","AptPlus",234,0,234,31,0,31,31,0,31);
    fAptMinu = new TH3S("AptMinu","AptMinu",234,0,234,31,0,31,31,0,31);
    fAptUnde = new TH3S("AptUnde","AptUnde",234,0,234,31,0,31,31,0,31);

    RegisterHistos();
  }

  TH3* h = static_cast<TH3*>(fMap->GetValue(hname));

  Int_t bin = h->GetBin(icirc,istripX,idev);
  h->SetBinContent(bin,value);
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::GetLutOutput(Int_t circuit, Int_t xstrip, Int_t idev,
                                     Int_t ystrip, Int_t lutLpt[2],
                                     Int_t lutHpt[2]) const
{
/// Return output of LuT for corresponding TH3S

  if ( !fLptPlus )
  {
    AliError("LUT not initialized");
//    ReadFromFile("$(ALICE_ROOT)/MUON/data/MUONTriggerLut.root");
  }

  Int_t bin;
  Short_t binc;
  Int_t mask = GetMask(ystrip);        // get ystrip mask

  // Low pt..............................................
  bin    =          fLptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[1]=1;

  bin    =          fLptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[0]=1;

  bin    =          fLptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[0]=lutLpt[1]=1;

  // High pt.............................................
  bin    =          fHptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[1]=1;

  bin    =          fHptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[0]=1;

  bin    =          fHptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[0]=lutHpt[1]=1;
/*
  // All pts.............................................
  bin    =          fAptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[1]=1;

  bin    =          fAptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[0]=1;

  bin    =          fAptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[0]=lutApt[1]=1;
*/
}

//----------------------------------------------------------------------
Int_t AliMUONTriggerLut::GetMask(Int_t ystrip) const
{
/// Return the mask corresponding to ystrip

    return (Int_t)(1<<ystrip);
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::SetLutCode(const UChar_t lutCode)
{
/// Set the LUT code for the pair of cuts
/// see AliMUONTriggerIO::ReadLUT for the definitions

  if (!fMap) {
    AliWarning("Nothing registered in the map ?... ");
    return;
  }
  TH3* h = static_cast<TH3*>(fMap->GetValue("LptPlus"));
  h->SetTitle(Form("LptPlus 0x%02x",lutCode));

}

//----------------------------------------------------------------------
void AliMUONTriggerLut::PrintLutCode()
{
/// Print out the LUT code for the pair of cuts
/// see AliMUONTriggerIO::ReadLUT for the definitions

  TString lutCode = fLptPlus->GetTitle();
  lutCode.Remove(0,8);
  if (lutCode.Length() == 0) {
    AliInfo("No code stored (older version).");
  } else {
    AliInfo(lutCode.Data());

    AliInfo("---------------------------------");
    AliInfo("1st/2nd cut code   pt cut [GeV/c]");
    AliInfo("                                 ");
    AliInfo(" 0                 0.5 (a.k.a. Apt)");
    AliInfo(" 1                 1.0 (a.k.a. Lpt)");
    AliInfo(" 2                 1.7 (a.k.a. Hpt)");
    AliInfo(" 3                 4.2 (a.k.a. infinity)");
    AliInfo(" 4                 free");
    AliInfo(" .");
    AliInfo(" .");
    AliInfo(" .");
    AliInfo("15 default (for backward compatibility)");
    AliInfo("---------------------------------------");

  }

}
<commit_msg>Print LUT code with extended information (new LUT for larger "undef" in order to avoid loss of misidentified charge sign).<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-----------------------------------------------------------------------------
/// \class AliMUONTriggerLut
///
/// Local Trigger Look Up Table
/// reading interface LUT data is stored into TH3S histograms and readout
/// from the Local Trigger algorithm
///
/// Histograms structure is :
/// X 234 bins, 1 to 235   = local board number
/// Y  31 bins, 0 to  31   = x strip
/// Z  31 bins, 0 to  31   = x deviation
/// content = Short_t      = y strip mask
///
///  overflow bin is used !
///
/// \author Philippe Crochet
//-----------------------------------------------------------------------------

#include "AliMUONTriggerLut.h"

#include "AliLog.h"

#include <TFile.h>
#include <TH3.h>
#include <TMap.h>
#include <TObjString.h>

/// \cond CLASSIMP
ClassImp(AliMUONTriggerLut)
/// \endcond

//----------------------------------------------------------------------
AliMUONTriggerLut::AliMUONTriggerLut()
    : TNamed(),
      fLptPlus(0),
      fLptMinu(0),
      fLptUnde(0),
      fHptPlus(0),
      fHptMinu(0),
      fHptUnde(0),
      fAptPlus(0),
      fAptMinu(0),
      fAptUnde(0),
  fMap(0x0)
{
/// ctor
}

//----------------------------------------------------------------------
AliMUONTriggerLut::~AliMUONTriggerLut()
{
/// Destructor

  delete fLptPlus;
  delete fLptMinu;
  delete fLptUnde;
  delete fHptPlus;
  delete fHptMinu;
  delete fHptUnde;
  delete fAptPlus;
  delete fAptMinu;
  delete fAptUnde;
  delete fMap;
}

//----------------------------------------------------------------------
Int_t
AliMUONTriggerLut::Compare(TH3* h1, TH3* h2) const
{
/// Return 0 if both histograms are strictly equal (at the bin-by-bin level)

  AliDebug(1,Form("h1 %s h2 %s",h1 ? h1->GetName() : "null", h2 ? h2->GetName() : "null"));

  if (!h1 || !h2)
  {
    return 0;
  }
  Int_t bin;
  for ( Int_t ix = 0; ix <= h1->GetNbinsX()+1; ix++ )
    for ( Int_t iy = 0; iy <= h1->GetNbinsY()+1; iy++ )
      for ( Int_t iz = 0; iz <= h1->GetNbinsZ()+1; iz++ )
	{
	  {
	    {
	      bin = h1->GetBin(ix,iy,iz);
	      Double_t x1 = h1->GetBinContent(bin);
	      Double_t x2 = h2->GetBinContent(bin);
	      if ( x1 != x2 ) return 0;
	    }
	  }
	}

  AliDebug(1,"same");

  return 1;
}

//----------------------------------------------------------------------
Int_t
AliMUONTriggerLut::Compare(const TObject* object) const
{
/// Return 0 if the two luts are strictly equal

  const AliMUONTriggerLut* lut = static_cast<const AliMUONTriggerLut*>(object);

  Int_t rvLpt(0);

  rvLpt += Compare(fLptPlus,lut->fLptPlus);
  rvLpt += Compare(fLptMinu,lut->fLptMinu);
  rvLpt += Compare(fLptUnde,lut->fLptUnde);

  Int_t rvHpt(0);

  rvHpt += Compare(fHptPlus,lut->fHptPlus);
  rvHpt += Compare(fHptMinu,lut->fHptMinu);
  rvHpt += Compare(fHptUnde,lut->fHptUnde);

  Int_t rv(0);

  rv += Compare(fAptPlus,lut->fAptPlus);
  rv += Compare(fAptMinu,lut->fAptMinu);
  rv += Compare(fAptUnde,lut->fAptUnde);

  AliDebug(1,Form("Same Lpt %d Hpt %d Apt %d",rvLpt,rvHpt,rv));

  if ( rvLpt == 3 && rvHpt == 3 )
  {
    return 0;
  }

  return 1;
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::ReadFromFile(const char* filename)
{
/// Return output of LuT for corresponding TH3S

  TFile f(filename);

  if ( f.IsZombie() )
  {
    AliFatal(Form("Could not open file %s",filename));
  }

  AliDebug(1,Form("filename=%s",filename));

  fLptPlus = (TH3*)(f.Get("LptPlus"));
  fLptMinu = (TH3*)(f.Get("LptMinu"));
  fLptUnde = (TH3*)(f.Get("LptUnde"));
  fHptPlus = (TH3*)(f.Get("HptPlus"));
  fHptMinu = (TH3*)(f.Get("HptMinu"));
  fHptUnde = (TH3*)(f.Get("HptUnde"));
  fAptPlus = (TH3*)(f.Get("AptPlus"));
  fAptMinu = (TH3*)(f.Get("AptMinu"));
  fAptUnde = (TH3*)(f.Get("AptUnde"));

  // insure we "detach" those histograms from file f
  fLptPlus->SetDirectory(0);
  fLptMinu->SetDirectory(0);
  fLptUnde->SetDirectory(0);
  fHptPlus->SetDirectory(0);
  fHptMinu->SetDirectory(0);
  fHptUnde->SetDirectory(0);
  fAptPlus->SetDirectory(0);
  fAptMinu->SetDirectory(0);
  fAptUnde->SetDirectory(0);

  RegisterHistos();
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::RegisterHistos()
{
/// Add histos to our internal map

  Add(fLptPlus);
  Add(fLptMinu);
  Add(fLptUnde);

  Add(fHptPlus);
  Add(fHptMinu);
  Add(fHptUnde);

  Add(fAptPlus);
  Add(fAptMinu);
  Add(fAptUnde);
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::Add(TH3* h)
{
  /// Update internal map
  if (!fMap)
  {
    fMap = new TMap;
    fMap->SetOwner(kTRUE);
  }

  if (h) fMap->Add(new TObjString(h->GetName()),h);
}

//----------------------------------------------------------------------
void
AliMUONTriggerLut::SetContent(const char* hname, Int_t icirc, UChar_t istripX,
                              UChar_t idev, Short_t value)
{
  /// Set the content of one bin of one histogram

  if (!fMap)
  {
    //..........................................circuit/stripX/deviation
    fLptPlus = new TH3S("LptPlus","LptPlus",234,0,234,31,0,31,31,0,31);
    fLptMinu = new TH3S("LptMinu","LptMinu",234,0,234,31,0,31,31,0,31);
    fLptUnde = new TH3S("LptUnde","LptUnde",234,0,234,31,0,31,31,0,31);

    fHptPlus = new TH3S("HptPlus","HptPlus",234,0,234,31,0,31,31,0,31);
    fHptMinu = new TH3S("HptMinu","HptMinu",234,0,234,31,0,31,31,0,31);
    fHptUnde = new TH3S("HptUnde","HptUnde",234,0,234,31,0,31,31,0,31);

    fAptPlus = new TH3S("AptPlus","AptPlus",234,0,234,31,0,31,31,0,31);
    fAptMinu = new TH3S("AptMinu","AptMinu",234,0,234,31,0,31,31,0,31);
    fAptUnde = new TH3S("AptUnde","AptUnde",234,0,234,31,0,31,31,0,31);

    RegisterHistos();
  }

  TH3* h = static_cast<TH3*>(fMap->GetValue(hname));

  Int_t bin = h->GetBin(icirc,istripX,idev);
  h->SetBinContent(bin,value);
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::GetLutOutput(Int_t circuit, Int_t xstrip, Int_t idev,
                                     Int_t ystrip, Int_t lutLpt[2],
                                     Int_t lutHpt[2]) const
{
/// Return output of LuT for corresponding TH3S

  if ( !fLptPlus )
  {
    AliError("LUT not initialized");
//    ReadFromFile("$(ALICE_ROOT)/MUON/data/MUONTriggerLut.root");
  }

  Int_t bin;
  Short_t binc;
  Int_t mask = GetMask(ystrip);        // get ystrip mask

  // Low pt..............................................
  bin    =          fLptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[1]=1;

  bin    =          fLptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[0]=1;

  bin    =          fLptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fLptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutLpt[0]=lutLpt[1]=1;

  // High pt.............................................
  bin    =          fHptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[1]=1;

  bin    =          fHptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[0]=1;

  bin    =          fHptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fHptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutHpt[0]=lutHpt[1]=1;
/*
  // All pts.............................................
  bin    =          fAptPlus->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptPlus->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[1]=1;

  bin    =          fAptMinu->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptMinu->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[0]=1;

  bin    =          fAptUnde->GetBin(circuit,xstrip,idev);
  binc   = (Short_t)fAptUnde->GetBinContent(bin);
  if ((binc & mask)!=0) lutApt[0]=lutApt[1]=1;
*/
}

//----------------------------------------------------------------------
Int_t AliMUONTriggerLut::GetMask(Int_t ystrip) const
{
/// Return the mask corresponding to ystrip

    return (Int_t)(1<<ystrip);
}

//----------------------------------------------------------------------
void AliMUONTriggerLut::SetLutCode(const UChar_t lutCode)
{
/// Set the LUT code for the pair of cuts
/// see AliMUONTriggerIO::ReadLUT for the definitions

  if (!fMap) {
    AliWarning("Nothing registered in the map ?... ");
    return;
  }
  TH3* h = static_cast<TH3*>(fMap->GetValue("LptPlus"));
  h->SetTitle(Form("LptPlus 0x%02x",lutCode));

}

//----------------------------------------------------------------------
void AliMUONTriggerLut::PrintLutCode()
{
/// Print out the LUT code for the pair of cuts
/// see AliMUONTriggerIO::ReadLUT for the definitions

  TString lutCode = fLptPlus->GetTitle();
  lutCode.Remove(0,8);
  if (lutCode.Length() == 0) {
    AliInfo("No code stored (older version).");
  } else {
    AliInfo(lutCode.Data());

    AliInfo("---------------------------------");
    AliInfo("1st/2nd cut code   pt cut [GeV/c]");
    AliInfo("                                 ");
    AliInfo(" 0                 0.5 (a.k.a. Apt)");
    AliInfo(" 1                 1.0 (a.k.a. Lpt)");
    AliInfo(" 2                 1.7 (a.k.a. Hpt)");
    AliInfo(" 3                 4.2 (a.k.a. infinity)");
    AliInfo(" 4                 0 with extended \"undef\"");
    AliInfo(" 5                 1 with extended \"undef\"");
    AliInfo(" 6                 2 with extended \"undef\"");
    AliInfo(" 7                 3 with extended \"undef\"");
    AliInfo("15 default (for backward compatibility)");
    AliInfo("---------------------------------------");

  }

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004-2006 The Regents of The University of Michigan
 * 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 holders 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
 * OWNER 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.
 *
 * Authors: Kevin Lim
 */

#ifndef __CPU_O3_THREAD_CONTEXT_HH__
#define __CPU_O3_THREAD_CONTEXT_HH__

#include "cpu/thread_context.hh"
#include "cpu/o3/isa_specific.hh"

class EndQuiesceEvent;
namespace Kernel {
    class Statistics;
};

class TranslatingPort;

/**
 * Derived ThreadContext class for use with the O3CPU.  It
 * provides the interface for any external objects to access a
 * single thread's state and some general CPU state.  Any time
 * external objects try to update state through this interface,
 * the CPU will create an event to squash all in-flight
 * instructions in order to ensure state is maintained correctly.
 * It must be defined specifically for the O3CPU because
 * not all architectural state is located within the O3ThreadState
 * (such as the commit PC, and registers), and specific actions
 * must be taken when using this interface (such as squashing all
 * in-flight instructions when doing a write to this interface).
 */
template <class Impl>
class O3ThreadContext : public ThreadContext
{
  public:
    typedef typename Impl::O3CPU O3CPU;

   /** Pointer to the CPU. */
    O3CPU *cpu;

    /** Pointer to the thread state that this TC corrseponds to. */
    O3ThreadState<Impl> *thread;

    /** Returns a pointer to the ITB. */
    TheISA::ITB *getITBPtr() { return cpu->itb; }

    /** Returns a pointer to the DTB. */
    TheISA::DTB *getDTBPtr() { return cpu->dtb; }

    /** Returns a pointer to this CPU. */
    virtual BaseCPU *getCpuPtr() { return cpu; }

    /** Sets this CPU's ID. */
    virtual void setCpuId(int id) { cpu->setCpuId(id); }

    /** Reads this CPU's ID. */
    virtual int readCpuId() { return cpu->readCpuId(); }

#if FULL_SYSTEM
    /** Returns a pointer to the system. */
    virtual System *getSystemPtr() { return cpu->system; }

    /** Returns a pointer to physical memory. */
    virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }

    /** Returns a pointer to this thread's kernel statistics. */
    virtual TheISA::Kernel::Statistics *getKernelStats()
    { return thread->kernelStats; }

    virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); }

    virtual VirtualPort *getVirtPort(ThreadContext *src_tc = NULL);

    void delVirtPort(VirtualPort *vp);

    virtual void connectMemPorts() { thread->connectMemPorts(); }
#else
    virtual TranslatingPort *getMemPort() { return thread->getMemPort(); }

    /** Returns a pointer to this thread's process. */
    virtual Process *getProcessPtr() { return thread->getProcessPtr(); }
#endif
    /** Returns this thread's status. */
    virtual Status status() const { return thread->status(); }

    /** Sets this thread's status. */
    virtual void setStatus(Status new_status)
    { thread->setStatus(new_status); }

    /** Set the status to Active.  Optional delay indicates number of
     * cycles to wait before beginning execution. */
    virtual void activate(int delay = 1);

    /** Set the status to Suspended. */
    virtual void suspend(int delay = 0);

    /** Set the status to Unallocated. */
    virtual void deallocate(int delay = 0);

    /** Set the status to Halted. */
    virtual void halt(int delay = 0);

#if FULL_SYSTEM
    /** Dumps the function profiling information.
     * @todo: Implement.
     */
    virtual void dumpFuncProfile();
#endif
    /** Takes over execution of a thread from another CPU. */
    virtual void takeOverFrom(ThreadContext *old_context);

    /** Registers statistics associated with this TC. */
    virtual void regStats(const std::string &name);

    /** Serializes state. */
    virtual void serialize(std::ostream &os);
    /** Unserializes state. */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#if FULL_SYSTEM
    /** Reads the last tick that this thread was activated on. */
    virtual Tick readLastActivate();
    /** Reads the last tick that this thread was suspended on. */
    virtual Tick readLastSuspend();

    /** Clears the function profiling information. */
    virtual void profileClear();
    /** Samples the function profiling information. */
    virtual void profileSample();
#endif
    /** Returns this thread's ID number. */
    virtual int getThreadNum() { return thread->readTid(); }

    /** Returns the instruction this thread is currently committing.
     *  Only used when an instruction faults.
     */
    virtual TheISA::MachInst getInst();

    /** Copies the architectural registers from another TC into this TC. */
    virtual void copyArchRegs(ThreadContext *tc);

    /** Resets all architectural registers to 0. */
    virtual void clearArchRegs();

    /** Reads an integer register. */
    virtual uint64_t readIntReg(int reg_idx);

    virtual FloatReg readFloatReg(int reg_idx, int width);

    virtual FloatReg readFloatReg(int reg_idx);

    virtual FloatRegBits readFloatRegBits(int reg_idx, int width);

    virtual FloatRegBits readFloatRegBits(int reg_idx);

    /** Sets an integer register to a value. */
    virtual void setIntReg(int reg_idx, uint64_t val);

    virtual void setFloatReg(int reg_idx, FloatReg val, int width);

    virtual void setFloatReg(int reg_idx, FloatReg val);

    virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);

    virtual void setFloatRegBits(int reg_idx, FloatRegBits val);

    /** Reads this thread's PC. */
    virtual uint64_t readPC()
    { return cpu->readPC(thread->readTid()); }

    /** Sets this thread's PC. */
    virtual void setPC(uint64_t val);

    /** Reads this thread's next PC. */
    virtual uint64_t readNextPC()
    { return cpu->readNextPC(thread->readTid()); }

    /** Sets this thread's next PC. */
    virtual void setNextPC(uint64_t val);

    /** Reads a miscellaneous register. */
    virtual MiscReg readMiscRegNoEffect(int misc_reg)
    { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); }

    /** Reads a misc. register, including any side-effects the
     * read might have as defined by the architecture. */
    virtual MiscReg readMiscReg(int misc_reg)
    { return cpu->readMiscReg(misc_reg, thread->readTid()); }

    /** Sets a misc. register. */
    virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val);

    /** Sets a misc. register, including any side-effects the
     * write might have as defined by the architecture. */
    virtual void setMiscReg(int misc_reg, const MiscReg &val);

    /** Returns the number of consecutive store conditional failures. */
    // @todo: Figure out where these store cond failures should go.
    virtual unsigned readStCondFailures()
    { return thread->storeCondFailures; }

    /** Sets the number of consecutive store conditional failures. */
    virtual void setStCondFailures(unsigned sc_failures)
    { thread->storeCondFailures = sc_failures; }

    // Only really makes sense for old CPU model.  Lots of code
    // outside the CPU still checks this function, so it will
    // always return false to keep everything working.
    /** Checks if the thread is misspeculating.  Because it is
     * very difficult to determine if the thread is
     * misspeculating, this is set as false. */
    virtual bool misspeculating() { return false; }

#if !FULL_SYSTEM
    /** Gets a syscall argument by index. */
    virtual IntReg getSyscallArg(int i);

    /** Sets a syscall argument. */
    virtual void setSyscallArg(int i, IntReg val);

    /** Sets the syscall return value. */
    virtual void setSyscallReturn(SyscallReturn return_value);

    /** Executes a syscall in SE mode. */
    virtual void syscall(int64_t callnum)
    { return cpu->syscall(callnum, thread->readTid()); }

    /** Reads the funcExeInst counter. */
    virtual Counter readFuncExeInst() { return thread->funcExeInst; }
#endif
};

#endif
<commit_msg>add microPC stuff back in. got deleted on changeset propragation somehow.<commit_after>/*
 * Copyright (c) 2004-2006 The Regents of The University of Michigan
 * 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 holders 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
 * OWNER 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.
 *
 * Authors: Kevin Lim
 */

#ifndef __CPU_O3_THREAD_CONTEXT_HH__
#define __CPU_O3_THREAD_CONTEXT_HH__

#include "cpu/thread_context.hh"
#include "cpu/o3/isa_specific.hh"

class EndQuiesceEvent;
namespace Kernel {
    class Statistics;
};

class TranslatingPort;

/**
 * Derived ThreadContext class for use with the O3CPU.  It
 * provides the interface for any external objects to access a
 * single thread's state and some general CPU state.  Any time
 * external objects try to update state through this interface,
 * the CPU will create an event to squash all in-flight
 * instructions in order to ensure state is maintained correctly.
 * It must be defined specifically for the O3CPU because
 * not all architectural state is located within the O3ThreadState
 * (such as the commit PC, and registers), and specific actions
 * must be taken when using this interface (such as squashing all
 * in-flight instructions when doing a write to this interface).
 */
template <class Impl>
class O3ThreadContext : public ThreadContext
{
  public:
    typedef typename Impl::O3CPU O3CPU;

   /** Pointer to the CPU. */
    O3CPU *cpu;

    /** Pointer to the thread state that this TC corrseponds to. */
    O3ThreadState<Impl> *thread;

    /** Returns a pointer to the ITB. */
    TheISA::ITB *getITBPtr() { return cpu->itb; }

    /** Returns a pointer to the DTB. */
    TheISA::DTB *getDTBPtr() { return cpu->dtb; }

    /** Returns a pointer to this CPU. */
    virtual BaseCPU *getCpuPtr() { return cpu; }

    /** Sets this CPU's ID. */
    virtual void setCpuId(int id) { cpu->setCpuId(id); }

    /** Reads this CPU's ID. */
    virtual int readCpuId() { return cpu->readCpuId(); }

#if FULL_SYSTEM
    /** Returns a pointer to the system. */
    virtual System *getSystemPtr() { return cpu->system; }

    /** Returns a pointer to physical memory. */
    virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }

    /** Returns a pointer to this thread's kernel statistics. */
    virtual TheISA::Kernel::Statistics *getKernelStats()
    { return thread->kernelStats; }

    virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); }

    virtual VirtualPort *getVirtPort(ThreadContext *src_tc = NULL);

    void delVirtPort(VirtualPort *vp);

    virtual void connectMemPorts() { thread->connectMemPorts(); }
#else
    virtual TranslatingPort *getMemPort() { return thread->getMemPort(); }

    /** Returns a pointer to this thread's process. */
    virtual Process *getProcessPtr() { return thread->getProcessPtr(); }
#endif
    /** Returns this thread's status. */
    virtual Status status() const { return thread->status(); }

    /** Sets this thread's status. */
    virtual void setStatus(Status new_status)
    { thread->setStatus(new_status); }

    /** Set the status to Active.  Optional delay indicates number of
     * cycles to wait before beginning execution. */
    virtual void activate(int delay = 1);

    /** Set the status to Suspended. */
    virtual void suspend(int delay = 0);

    /** Set the status to Unallocated. */
    virtual void deallocate(int delay = 0);

    /** Set the status to Halted. */
    virtual void halt(int delay = 0);

#if FULL_SYSTEM
    /** Dumps the function profiling information.
     * @todo: Implement.
     */
    virtual void dumpFuncProfile();
#endif
    /** Takes over execution of a thread from another CPU. */
    virtual void takeOverFrom(ThreadContext *old_context);

    /** Registers statistics associated with this TC. */
    virtual void regStats(const std::string &name);

    /** Serializes state. */
    virtual void serialize(std::ostream &os);
    /** Unserializes state. */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#if FULL_SYSTEM
    /** Reads the last tick that this thread was activated on. */
    virtual Tick readLastActivate();
    /** Reads the last tick that this thread was suspended on. */
    virtual Tick readLastSuspend();

    /** Clears the function profiling information. */
    virtual void profileClear();
    /** Samples the function profiling information. */
    virtual void profileSample();
#endif
    /** Returns this thread's ID number. */
    virtual int getThreadNum() { return thread->readTid(); }

    /** Returns the instruction this thread is currently committing.
     *  Only used when an instruction faults.
     */
    virtual TheISA::MachInst getInst();

    /** Copies the architectural registers from another TC into this TC. */
    virtual void copyArchRegs(ThreadContext *tc);

    /** Resets all architectural registers to 0. */
    virtual void clearArchRegs();

    /** Reads an integer register. */
    virtual uint64_t readIntReg(int reg_idx);

    virtual FloatReg readFloatReg(int reg_idx, int width);

    virtual FloatReg readFloatReg(int reg_idx);

    virtual FloatRegBits readFloatRegBits(int reg_idx, int width);

    virtual FloatRegBits readFloatRegBits(int reg_idx);

    /** Sets an integer register to a value. */
    virtual void setIntReg(int reg_idx, uint64_t val);

    virtual void setFloatReg(int reg_idx, FloatReg val, int width);

    virtual void setFloatReg(int reg_idx, FloatReg val);

    virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);

    virtual void setFloatRegBits(int reg_idx, FloatRegBits val);

    /** Reads this thread's PC. */
    virtual uint64_t readPC()
    { return cpu->readPC(thread->readTid()); }

    /** Sets this thread's PC. */
    virtual void setPC(uint64_t val);

    /** Reads this thread's next PC. */
    virtual uint64_t readNextPC()
    { return cpu->readNextPC(thread->readTid()); }

    /** Sets this thread's next PC. */
    virtual void setNextPC(uint64_t val);

    virtual uint64_t readMicroPC()
    { return cpu->readMicroPC(thread->readTid()); }

    virtual void setMicroPC(uint64_t val);

    virtual uint64_t readNextMicroPC()
    { return cpu->readNextMicroPC(thread->readTid()); }

    virtual void setNextMicroPC(uint64_t val);

    /** Reads a miscellaneous register. */
    virtual MiscReg readMiscRegNoEffect(int misc_reg)
    { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); }

    /** Reads a misc. register, including any side-effects the
     * read might have as defined by the architecture. */
    virtual MiscReg readMiscReg(int misc_reg)
    { return cpu->readMiscReg(misc_reg, thread->readTid()); }

    /** Sets a misc. register. */
    virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val);

    /** Sets a misc. register, including any side-effects the
     * write might have as defined by the architecture. */
    virtual void setMiscReg(int misc_reg, const MiscReg &val);

    /** Returns the number of consecutive store conditional failures. */
    // @todo: Figure out where these store cond failures should go.
    virtual unsigned readStCondFailures()
    { return thread->storeCondFailures; }

    /** Sets the number of consecutive store conditional failures. */
    virtual void setStCondFailures(unsigned sc_failures)
    { thread->storeCondFailures = sc_failures; }

    // Only really makes sense for old CPU model.  Lots of code
    // outside the CPU still checks this function, so it will
    // always return false to keep everything working.
    /** Checks if the thread is misspeculating.  Because it is
     * very difficult to determine if the thread is
     * misspeculating, this is set as false. */
    virtual bool misspeculating() { return false; }

#if !FULL_SYSTEM
    /** Gets a syscall argument by index. */
    virtual IntReg getSyscallArg(int i);

    /** Sets a syscall argument. */
    virtual void setSyscallArg(int i, IntReg val);

    /** Sets the syscall return value. */
    virtual void setSyscallReturn(SyscallReturn return_value);

    /** Executes a syscall in SE mode. */
    virtual void syscall(int64_t callnum)
    { return cpu->syscall(callnum, thread->readTid()); }

    /** Reads the funcExeInst counter. */
    virtual Counter readFuncExeInst() { return thread->funcExeInst; }
#endif
};

#endif
<|endoftext|>


<commit_before>#include "PrimeTower.h"

#include <limits>

#include "ExtruderTrain.h"
#include "sliceDataStorage.h"
#include "gcodeExport.h"
#include "gcodePlanner.h"
#include "infill.h"
#include "PrintFeature.h"

namespace cura
{

PrimeTower::PrimeTower(const SliceDataStorage& storage)
: is_hollow(false)
, wipe_from_middle(false)
, current_pre_wipe_location_idx(0)
{
    for (int extruder_nr = 0; extruder_nr < MAX_EXTRUDERS; extruder_nr++)
    {
        last_prime_tower_poly_printed[extruder_nr] = -1;
    }
    enabled = storage.getSettingBoolean("prime_tower_enable")
           && storage.getSettingInMicrons("prime_tower_wall_thickness") > 10
           && storage.getSettingInMicrons("prime_tower_size") > 10;
    if (enabled)
    {
        generateGroundpoly(storage);
    }
}

void PrimeTower::initConfigs(const MeshGroup* meshgroup)
{
    extruder_count = meshgroup->getExtruderCount();

    for (int extr = 0; extr < extruder_count; extr++)
    {
        config_per_extruder.emplace_back(PrintFeatureType::Support);// so that visualization in the old Cura still works (TODO)
    }
    for (int extr = 0; extr < extruder_count; extr++)
    {
        const ExtruderTrain* train = meshgroup->getExtruderTrain(extr);
        config_per_extruder[extr].init(train->getSettingInMillimetersPerSecond("speed_prime_tower"), train->getSettingInMillimetersPerSecond("acceleration_prime_tower"), train->getSettingInMillimetersPerSecond("jerk_prime_tower"), train->getSettingInMicrons("prime_tower_line_width"), train->getSettingInPercentage("prime_tower_flow"));
    }
}

void PrimeTower::setConfigs(const MeshGroup* meshgroup, const int layer_thickness)
{
    extruder_count = meshgroup->getExtruderCount();

    for (int extr = 0; extr < extruder_count; extr++)
    {
        GCodePathConfig& conf = config_per_extruder[extr];
        conf.setLayerHeight(layer_thickness);
    }
}

void PrimeTower::generateGroundpoly(const SliceDataStorage& storage)
{
    extruder_count = storage.meshgroup->getExtruderCount();

    int64_t prime_tower_wall_thickness = storage.getSettingInMicrons("prime_tower_wall_thickness");
    int64_t tower_size = storage.getSettingInMicrons("prime_tower_size");

    if (prime_tower_wall_thickness * 2 < tower_size)
    {
        is_hollow = true;
    }

    PolygonRef p = ground_poly.newPoly();
    int tower_distance = 0;
    int x = storage.getSettingInMicrons("prime_tower_position_x"); // storage.model_max.x
    int y = storage.getSettingInMicrons("prime_tower_position_y"); // storage.model_max.y
    p.add(Point(x + tower_distance, y + tower_distance));
    p.add(Point(x + tower_distance, y + tower_distance + tower_size));
    p.add(Point(x + tower_distance - tower_size, y + tower_distance + tower_size));
    p.add(Point(x + tower_distance - tower_size, y + tower_distance));
    middle = Point(x - tower_size / 2, y + tower_size / 2);

    if (is_hollow)
    {
        ground_poly = ground_poly.difference(ground_poly.offset(-prime_tower_wall_thickness));
    }

    post_wipe_point = Point(x + tower_distance - tower_size / 2, y + tower_distance + tower_size / 2);
}

void PrimeTower::generatePaths(const SliceDataStorage& storage)
{
    enabled &= storage.max_print_height_second_to_last_extruder >= 0; //Maybe it turns out that we don't need a prime tower after all because there are no layer switches.
    if (enabled)
    {
        generatePaths_denseInfill(storage);
        generateWipeLocations(storage);
    }
}

void PrimeTower::generatePaths_denseInfill(const SliceDataStorage& storage)
{
    int n_patterns = 2; // alternating patterns between layers
    int infill_overlap = 60; // so that it can't be zero; EDIT: wtf?
    int extra_infill_shift = 0;

    int64_t z = 0; // (TODO) because the prime tower stores the paths for each extruder for once instead of generating each layer, we don't know the z position

    for (int extruder = 0; extruder < extruder_count; extruder++)
    {
        int line_width = storage.meshgroup->getExtruderTrain(extruder)->getSettingInMicrons("prime_tower_line_width");
        patterns_per_extruder.emplace_back(n_patterns);
        std::vector<ExtrusionMoves>& patterns = patterns_per_extruder.back();
        patterns.resize(n_patterns);
        for (int pattern_idx = 0; pattern_idx < n_patterns; pattern_idx++)
        {
            patterns[pattern_idx].polygons = ground_poly.offset(-line_width / 2);
            Polygons& result_lines = patterns[pattern_idx].lines;
            int outline_offset = -line_width;
            int line_distance = line_width;
            double fill_angle = 45 + pattern_idx * 90;
            Polygons result_polygons; // should remain empty, since we generate lines pattern!
            Infill infill_comp(EFillMethod::LINES, ground_poly, outline_offset, line_width, line_distance, infill_overlap, fill_angle, z, extra_infill_shift);
            infill_comp.generate(result_polygons, result_lines);
        }
    }
}

void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder)
{
    if (!enabled)
    {
        return;
    }
    bool prime_tower_added = false;
    for (int extruder = 0; extruder <  storage.meshgroup->getExtruderCount() && !prime_tower_added; extruder++)
    {
        prime_tower_added = last_prime_tower_poly_printed[extruder] == int(layer_nr);
    }
    if (prime_tower_added)
    { // don't print the prime tower if it has been printed already
        return;
    }

    if (layer_nr > storage.max_print_height_second_to_last_extruder + 1)
    {
        return;
    }

    bool pre_wipe = storage.meshgroup->getExtruderTrain(new_extruder)->getSettingBoolean("dual_pre_wipe");
    bool post_wipe = storage.meshgroup->getExtruderTrain(prev_extruder)->getSettingBoolean("prime_tower_wipe_enabled");

    if (prev_extruder == new_extruder)
    {
        pre_wipe = false;
        post_wipe = false;
    }
    // pre-wipe:
    if (pre_wipe)
    {
        preWipe(storage, gcodeLayer, new_extruder);
    }

    addToGcode_denseInfill(gcodeLayer, layer_nr, new_extruder);

    // post-wipe:
    if (post_wipe)
    { //Make sure we wipe the old extruder on the prime tower.
        gcodeLayer.addTravel(post_wipe_point - gcode.getExtruderOffset(prev_extruder) + gcode.getExtruderOffset(new_extruder));
    }
}

void PrimeTower::addToGcode_denseInfill(GCodePlanner& gcodeLayer, const int layer_nr, const int extruder)
{
    ExtrusionMoves& pattern = patterns_per_extruder[extruder][((layer_nr % 2) + 2) % 2]; // +2) %2 to handle negative layer numbers

    GCodePathConfig& config = config_per_extruder[extruder];

    gcodeLayer.addPolygonsByOptimizer(pattern.polygons, &config);
    gcodeLayer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);

    last_prime_tower_poly_printed[extruder] = layer_nr;
}

Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage)
{
    Point ret(0, 0);
    int absolute_starting_points = 0;
    for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); extruder_nr++)
    {
        ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(0);
        if (train.getSettingBoolean("machine_extruder_start_pos_abs"))
        {
            ret += Point(train.getSettingInMicrons("machine_extruder_start_pos_x"), train.getSettingInMicrons("machine_extruder_start_pos_y"));
            absolute_starting_points++;
        }
    }
    if (absolute_starting_points > 0)
    { // take the average over all absolute starting positions
        ret /= absolute_starting_points;
    }
    else
    { // use the middle of the bed
        if (!storage.getSettingBoolean("machine_center_is_zero"))
        {
            ret = Point(storage.getSettingInMicrons("machine_width"), storage.getSettingInMicrons("machine_depth")) / 2;
        }
        // otherwise keep (0, 0)
    }
    return ret;
}

void PrimeTower::generateWipeLocations(const SliceDataStorage& storage)
{
    wipe_from_middle = is_hollow;
    // only wipe from the middle of the prime tower if we have a z hop already on the first move after the layer switch
    for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); extruder_nr++)
    {
        const ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr);
        wipe_from_middle &= train.getSettingBoolean("retraction_hop_enabled")
                        && (!train.getSettingBoolean("retraction_hop_only_when_collides") || train.getSettingBoolean("retraction_hop_after_extruder_switch"));
    }

    PolygonsPointIndex segment_start; // from where to start the sequence of wipe points
    PolygonsPointIndex segment_end; // where to end the sequence of wipe points

    if (wipe_from_middle)
    {
        // take the same start as end point so that the whole poly os covered.
        // find the inner polygon.
        segment_start = segment_end = PolygonUtils::findNearestVert(middle, ground_poly);
    }
    else
    {
        // take the closer corner of the wipe tower and generate wipe locations on that side only:
        //
        //     |
        //     |
        //     +-----
        //  .
        //  ^ nozzle switch location
        Point from = getLocationBeforePrimeTower(storage);

        // find the single line segment closest to [from] pointing most toward [from]
        PolygonsPointIndex closest_vert = PolygonUtils::findNearestVert(from, ground_poly);
        PolygonsPointIndex prev = closest_vert.prev();
        PolygonsPointIndex next = closest_vert.next();
        int64_t prev_dot_score = dot(from - closest_vert.p(), turn90CCW(prev.p() - closest_vert.p()));
        int64_t next_dot_score = dot(from - closest_vert.p(), turn90CCW(closest_vert.p() - next.p()));
        if (prev_dot_score > next_dot_score)
        {
            segment_start = prev;
            segment_end = closest_vert;
        }
        else
        {
            segment_start = closest_vert;
            segment_end = next;
        }
    }

    PolygonUtils::spreadDots(segment_start, segment_end, number_of_pre_wipe_locations, pre_wipe_locations);
}

void PrimeTower::preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int extruder_nr)
{
    const ClosestPolygonPoint wipe_location = pre_wipe_locations[current_pre_wipe_location_idx];
    current_pre_wipe_location_idx = (current_pre_wipe_location_idx + pre_wipe_location_skip) % number_of_pre_wipe_locations;

    ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr);
    const int inward_dist = train.getSettingInMicrons("machine_nozzle_size") * 3 / 2 ;
    const int start_dist = train.getSettingInMicrons("machine_nozzle_size") * 2;
    const Point end = PolygonUtils::moveInsideDiagonally(wipe_location, inward_dist);
    const Point outward_dir = wipe_location.location - end;
    const Point start = wipe_location.location + normal(outward_dir, start_dist);
    if (wipe_from_middle)
    {
        // for hollow wipe tower:
        // start from above
        // go to wipe start
        // go to the Z height of the previous/current layer
        // wipe
        // go to normal layer height (automatically on the next extrusion move)...
        GCodePath& toward_middle = gcode_layer.addTravel(middle);
        toward_middle.perform_z_hop = true;
        gcode_layer.forceNewPathStart();
        GCodePath& toward_wipe_start = gcode_layer.addTravel_simple(start);
        toward_wipe_start.perform_z_hop = false;
        toward_wipe_start.retract = true;
    }
    else
    {
        gcode_layer.addTravel(start);
    }
    float flow = 0.0001; // force this path being interpreted as an extrusion path, so that no Z hop will occur (TODO: really separately handle travel and extrusion moves)
    gcode_layer.addExtrusionMove(end, &config_per_extruder[extruder_nr], SpaceFillType::None, flow);
}

void PrimeTower::subtractFromSupport(SliceDataStorage& storage)
{
    for(size_t layer = 0; layer < (size_t)storage.max_print_height_second_to_last_extruder && layer < storage.support.supportLayers.size(); layer++)
    {
        storage.support.supportLayers[layer].supportAreas = storage.support.supportLayers[layer].supportAreas.difference(ground_poly.getOutsidePolygons());
    }
}

}//namespace cura
<commit_msg>Correct height of prime tower to subtract from support<commit_after>#include "PrimeTower.h"

#include <limits>

#include "ExtruderTrain.h"
#include "sliceDataStorage.h"
#include "gcodeExport.h"
#include "gcodePlanner.h"
#include "infill.h"
#include "PrintFeature.h"

namespace cura
{

PrimeTower::PrimeTower(const SliceDataStorage& storage)
: is_hollow(false)
, wipe_from_middle(false)
, current_pre_wipe_location_idx(0)
{
    for (int extruder_nr = 0; extruder_nr < MAX_EXTRUDERS; extruder_nr++)
    {
        last_prime_tower_poly_printed[extruder_nr] = -1;
    }
    enabled = storage.getSettingBoolean("prime_tower_enable")
           && storage.getSettingInMicrons("prime_tower_wall_thickness") > 10
           && storage.getSettingInMicrons("prime_tower_size") > 10;
    if (enabled)
    {
        generateGroundpoly(storage);
    }
}

void PrimeTower::initConfigs(const MeshGroup* meshgroup)
{
    extruder_count = meshgroup->getExtruderCount();

    for (int extr = 0; extr < extruder_count; extr++)
    {
        config_per_extruder.emplace_back(PrintFeatureType::Support);// so that visualization in the old Cura still works (TODO)
    }
    for (int extr = 0; extr < extruder_count; extr++)
    {
        const ExtruderTrain* train = meshgroup->getExtruderTrain(extr);
        config_per_extruder[extr].init(train->getSettingInMillimetersPerSecond("speed_prime_tower"), train->getSettingInMillimetersPerSecond("acceleration_prime_tower"), train->getSettingInMillimetersPerSecond("jerk_prime_tower"), train->getSettingInMicrons("prime_tower_line_width"), train->getSettingInPercentage("prime_tower_flow"));
    }
}

void PrimeTower::setConfigs(const MeshGroup* meshgroup, const int layer_thickness)
{
    extruder_count = meshgroup->getExtruderCount();

    for (int extr = 0; extr < extruder_count; extr++)
    {
        GCodePathConfig& conf = config_per_extruder[extr];
        conf.setLayerHeight(layer_thickness);
    }
}

void PrimeTower::generateGroundpoly(const SliceDataStorage& storage)
{
    extruder_count = storage.meshgroup->getExtruderCount();

    int64_t prime_tower_wall_thickness = storage.getSettingInMicrons("prime_tower_wall_thickness");
    int64_t tower_size = storage.getSettingInMicrons("prime_tower_size");

    if (prime_tower_wall_thickness * 2 < tower_size)
    {
        is_hollow = true;
    }

    PolygonRef p = ground_poly.newPoly();
    int tower_distance = 0;
    int x = storage.getSettingInMicrons("prime_tower_position_x"); // storage.model_max.x
    int y = storage.getSettingInMicrons("prime_tower_position_y"); // storage.model_max.y
    p.add(Point(x + tower_distance, y + tower_distance));
    p.add(Point(x + tower_distance, y + tower_distance + tower_size));
    p.add(Point(x + tower_distance - tower_size, y + tower_distance + tower_size));
    p.add(Point(x + tower_distance - tower_size, y + tower_distance));
    middle = Point(x - tower_size / 2, y + tower_size / 2);

    if (is_hollow)
    {
        ground_poly = ground_poly.difference(ground_poly.offset(-prime_tower_wall_thickness));
    }

    post_wipe_point = Point(x + tower_distance - tower_size / 2, y + tower_distance + tower_size / 2);
}

void PrimeTower::generatePaths(const SliceDataStorage& storage)
{
    enabled &= storage.max_print_height_second_to_last_extruder >= 0; //Maybe it turns out that we don't need a prime tower after all because there are no layer switches.
    if (enabled)
    {
        generatePaths_denseInfill(storage);
        generateWipeLocations(storage);
    }
}

void PrimeTower::generatePaths_denseInfill(const SliceDataStorage& storage)
{
    int n_patterns = 2; // alternating patterns between layers
    int infill_overlap = 60; // so that it can't be zero; EDIT: wtf?
    int extra_infill_shift = 0;

    int64_t z = 0; // (TODO) because the prime tower stores the paths for each extruder for once instead of generating each layer, we don't know the z position

    for (int extruder = 0; extruder < extruder_count; extruder++)
    {
        int line_width = storage.meshgroup->getExtruderTrain(extruder)->getSettingInMicrons("prime_tower_line_width");
        patterns_per_extruder.emplace_back(n_patterns);
        std::vector<ExtrusionMoves>& patterns = patterns_per_extruder.back();
        patterns.resize(n_patterns);
        for (int pattern_idx = 0; pattern_idx < n_patterns; pattern_idx++)
        {
            patterns[pattern_idx].polygons = ground_poly.offset(-line_width / 2);
            Polygons& result_lines = patterns[pattern_idx].lines;
            int outline_offset = -line_width;
            int line_distance = line_width;
            double fill_angle = 45 + pattern_idx * 90;
            Polygons result_polygons; // should remain empty, since we generate lines pattern!
            Infill infill_comp(EFillMethod::LINES, ground_poly, outline_offset, line_width, line_distance, infill_overlap, fill_angle, z, extra_infill_shift);
            infill_comp.generate(result_polygons, result_lines);
        }
    }
}

void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder)
{
    if (!enabled)
    {
        return;
    }
    bool prime_tower_added = false;
    for (int extruder = 0; extruder <  storage.meshgroup->getExtruderCount() && !prime_tower_added; extruder++)
    {
        prime_tower_added = last_prime_tower_poly_printed[extruder] == int(layer_nr);
    }
    if (prime_tower_added)
    { // don't print the prime tower if it has been printed already
        return;
    }

    if (layer_nr > storage.max_print_height_second_to_last_extruder + 1)
    {
        return;
    }

    bool pre_wipe = storage.meshgroup->getExtruderTrain(new_extruder)->getSettingBoolean("dual_pre_wipe");
    bool post_wipe = storage.meshgroup->getExtruderTrain(prev_extruder)->getSettingBoolean("prime_tower_wipe_enabled");

    if (prev_extruder == new_extruder)
    {
        pre_wipe = false;
        post_wipe = false;
    }
    // pre-wipe:
    if (pre_wipe)
    {
        preWipe(storage, gcodeLayer, new_extruder);
    }

    addToGcode_denseInfill(gcodeLayer, layer_nr, new_extruder);

    // post-wipe:
    if (post_wipe)
    { //Make sure we wipe the old extruder on the prime tower.
        gcodeLayer.addTravel(post_wipe_point - gcode.getExtruderOffset(prev_extruder) + gcode.getExtruderOffset(new_extruder));
    }
}

void PrimeTower::addToGcode_denseInfill(GCodePlanner& gcodeLayer, const int layer_nr, const int extruder)
{
    ExtrusionMoves& pattern = patterns_per_extruder[extruder][((layer_nr % 2) + 2) % 2]; // +2) %2 to handle negative layer numbers

    GCodePathConfig& config = config_per_extruder[extruder];

    gcodeLayer.addPolygonsByOptimizer(pattern.polygons, &config);
    gcodeLayer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);

    last_prime_tower_poly_printed[extruder] = layer_nr;
}

Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage)
{
    Point ret(0, 0);
    int absolute_starting_points = 0;
    for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); extruder_nr++)
    {
        ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(0);
        if (train.getSettingBoolean("machine_extruder_start_pos_abs"))
        {
            ret += Point(train.getSettingInMicrons("machine_extruder_start_pos_x"), train.getSettingInMicrons("machine_extruder_start_pos_y"));
            absolute_starting_points++;
        }
    }
    if (absolute_starting_points > 0)
    { // take the average over all absolute starting positions
        ret /= absolute_starting_points;
    }
    else
    { // use the middle of the bed
        if (!storage.getSettingBoolean("machine_center_is_zero"))
        {
            ret = Point(storage.getSettingInMicrons("machine_width"), storage.getSettingInMicrons("machine_depth")) / 2;
        }
        // otherwise keep (0, 0)
    }
    return ret;
}

void PrimeTower::generateWipeLocations(const SliceDataStorage& storage)
{
    wipe_from_middle = is_hollow;
    // only wipe from the middle of the prime tower if we have a z hop already on the first move after the layer switch
    for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); extruder_nr++)
    {
        const ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr);
        wipe_from_middle &= train.getSettingBoolean("retraction_hop_enabled")
                        && (!train.getSettingBoolean("retraction_hop_only_when_collides") || train.getSettingBoolean("retraction_hop_after_extruder_switch"));
    }

    PolygonsPointIndex segment_start; // from where to start the sequence of wipe points
    PolygonsPointIndex segment_end; // where to end the sequence of wipe points

    if (wipe_from_middle)
    {
        // take the same start as end point so that the whole poly os covered.
        // find the inner polygon.
        segment_start = segment_end = PolygonUtils::findNearestVert(middle, ground_poly);
    }
    else
    {
        // take the closer corner of the wipe tower and generate wipe locations on that side only:
        //
        //     |
        //     |
        //     +-----
        //  .
        //  ^ nozzle switch location
        Point from = getLocationBeforePrimeTower(storage);

        // find the single line segment closest to [from] pointing most toward [from]
        PolygonsPointIndex closest_vert = PolygonUtils::findNearestVert(from, ground_poly);
        PolygonsPointIndex prev = closest_vert.prev();
        PolygonsPointIndex next = closest_vert.next();
        int64_t prev_dot_score = dot(from - closest_vert.p(), turn90CCW(prev.p() - closest_vert.p()));
        int64_t next_dot_score = dot(from - closest_vert.p(), turn90CCW(closest_vert.p() - next.p()));
        if (prev_dot_score > next_dot_score)
        {
            segment_start = prev;
            segment_end = closest_vert;
        }
        else
        {
            segment_start = closest_vert;
            segment_end = next;
        }
    }

    PolygonUtils::spreadDots(segment_start, segment_end, number_of_pre_wipe_locations, pre_wipe_locations);
}

void PrimeTower::preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int extruder_nr)
{
    const ClosestPolygonPoint wipe_location = pre_wipe_locations[current_pre_wipe_location_idx];
    current_pre_wipe_location_idx = (current_pre_wipe_location_idx + pre_wipe_location_skip) % number_of_pre_wipe_locations;

    ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr);
    const int inward_dist = train.getSettingInMicrons("machine_nozzle_size") * 3 / 2 ;
    const int start_dist = train.getSettingInMicrons("machine_nozzle_size") * 2;
    const Point end = PolygonUtils::moveInsideDiagonally(wipe_location, inward_dist);
    const Point outward_dir = wipe_location.location - end;
    const Point start = wipe_location.location + normal(outward_dir, start_dist);
    if (wipe_from_middle)
    {
        // for hollow wipe tower:
        // start from above
        // go to wipe start
        // go to the Z height of the previous/current layer
        // wipe
        // go to normal layer height (automatically on the next extrusion move)...
        GCodePath& toward_middle = gcode_layer.addTravel(middle);
        toward_middle.perform_z_hop = true;
        gcode_layer.forceNewPathStart();
        GCodePath& toward_wipe_start = gcode_layer.addTravel_simple(start);
        toward_wipe_start.perform_z_hop = false;
        toward_wipe_start.retract = true;
    }
    else
    {
        gcode_layer.addTravel(start);
    }
    float flow = 0.0001; // force this path being interpreted as an extrusion path, so that no Z hop will occur (TODO: really separately handle travel and extrusion moves)
    gcode_layer.addExtrusionMove(end, &config_per_extruder[extruder_nr], SpaceFillType::None, flow);
}

void PrimeTower::subtractFromSupport(SliceDataStorage& storage)
{
    for(size_t layer = 0; layer <= (size_t)storage.max_print_height_second_to_last_extruder + 1 && layer < storage.support.supportLayers.size(); layer++)
    {
        storage.support.supportLayers[layer].supportAreas = storage.support.supportLayers[layer].supportAreas.difference(ground_poly.getOutsidePolygons());
    }
}

}//namespace cura
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "Properties.h"
#include "logging.h"
#include "utils.h" // tcam_xioctl

#include <algorithm> // find_if
#include <cstring>

using namespace tcam;

PropertyString::PropertyString (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyString::~PropertyString ()
{}

std::string PropertyString::get_default () const
{
    return prop.value.s.default_value;
}

bool PropertyString::set_value (const std::string& new_value)
{
    if (is_read_only())
    {
        return false;
    }

    if (new_value.size() > sizeof(this->prop.value.s.value))
        return false;

    memcpy(this->prop.value.s.value, new_value.c_str(), sizeof(this->prop.value.s.value));

    notify_impl();

    return true;
}

std::string PropertyString::get_value () const
{
    return prop.value.s.value;
}

PropertyEnumeration::PropertyEnumeration (std::shared_ptr<PropertyImpl> prop_impl,
                                          const tcam_device_property& prop,
                                          const std::map<std::string, int>& values,
                                          VALUE_TYPE t)
    : Property(prop, values, t)
{
    impl = prop_impl;
}

PropertyEnumeration::~PropertyEnumeration ()
{}

std::vector<std::string> PropertyEnumeration::get_values () const
{
    std::vector<std::string> vec;

    for (auto m : string_map)
    {
        vec.push_back(std::get<0>(m));
    }

    return vec;
}

std::string PropertyEnumeration::get_default () const
{
    return "";
}

bool PropertyEnumeration::set_value (const std::string& new_value)
{
    if (is_read_only())
    {
        return false;
    }

    auto element = string_map.find(new_value);

    if (element == string_map.end())
    {
        return false;
    }

    notify_impl();

    return false;
}

std::string PropertyEnumeration::get_value () const
{
    return prop.value.s.value;
}

std::map<std::string, int> PropertyEnumeration::get_mapping () const
{
    return string_map;
}

PropertyBoolean::PropertyBoolean (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyBoolean::~PropertyBoolean ()
{}

bool PropertyBoolean::get_default () const
{
    return prop.value.b.default_value;
}

bool PropertyBoolean::set_value (bool value)
{
    if (is_read_only())
    {
        return false;
    }

    prop.value.b.value = value;
    notify_impl();

    return true;
}

bool PropertyBoolean::get_value () const
{
    return prop.value.b.value;
}

PropertyInteger::PropertyInteger (std::shared_ptr<PropertyImpl> prop_impl,
                                  const tcam_device_property& prop,
                                  VALUE_TYPE t)
    : Property (prop, t)
{
    impl = prop_impl;
}

PropertyInteger::~PropertyInteger ()
{}

int64_t PropertyInteger::get_default () const
{
    return prop.value.i.default_value;
}

int64_t PropertyInteger::get_min () const
{
    return this->prop.value.i.min;
}

int64_t PropertyInteger::get_max () const
{
    return this->prop.value.i.max;
}

int64_t PropertyInteger::get_step () const
{
  return this->prop.value.i.step;
}

int64_t PropertyInteger::get_value () const
{
    return this->prop.value.i.value;
}

bool PropertyInteger::set_value (int64_t new_value)
{
    // if (is_read_only())
    // return false;

    tcam_value_int& i = this->prop.value.i;

    if (i.min > new_value || i.max < new_value)
        return false;

    if (i.step > 0 && new_value % i.step != 0)
    {
        return false;
    }

    i.value = new_value;

    notify_impl();

    return true;
}

PropertyDouble::PropertyDouble (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyDouble::~PropertyDouble ()
{}

double PropertyDouble::get_default () const
{
    return prop.value.d.default_value;
}

double PropertyDouble::get_min () const
{
    return this->prop.value.d.min;
}

double PropertyDouble::get_max () const
{
    return this->prop.value.d.max;
}

double PropertyDouble::get_step () const
{
    return this->prop.value.d.step;
}

double PropertyDouble::get_value () const
{
    return this->prop.value.d.value;
}

bool PropertyDouble::set_value (double new_value)
{
    if (is_read_only())
    {
        return false;
    }

    tcam_value_double& d = this->prop.value.d;

    if (d.min > new_value || d.max < new_value)
    {
        return false;
    }

    d.value = new_value;

    notify_impl();

    return false;
}

PropertyButton::PropertyButton (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyButton::~PropertyButton ()
{}

bool PropertyButton::activate ()
{
    if (is_read_only())
        return false;

    notify_impl();

    return true;
}
<commit_msg>Set value for enumerations<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "Properties.h"
#include "logging.h"
#include "utils.h" // tcam_xioctl

#include <algorithm> // find_if
#include <cstring>

using namespace tcam;

PropertyString::PropertyString (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyString::~PropertyString ()
{}

std::string PropertyString::get_default () const
{
    return prop.value.s.default_value;
}

bool PropertyString::set_value (const std::string& new_value)
{
    if (is_read_only())
    {
        return false;
    }

    if (new_value.size() > sizeof(this->prop.value.s.value))
        return false;

    memcpy(this->prop.value.s.value, new_value.c_str(), sizeof(this->prop.value.s.value));

    notify_impl();

    return true;
}

std::string PropertyString::get_value () const
{
    return prop.value.s.value;
}

PropertyEnumeration::PropertyEnumeration (std::shared_ptr<PropertyImpl> prop_impl,
                                          const tcam_device_property& prop,
                                          const std::map<std::string, int>& values,
                                          VALUE_TYPE t)
    : Property(prop, values, t)
{
    impl = prop_impl;
}

PropertyEnumeration::~PropertyEnumeration ()
{}

std::vector<std::string> PropertyEnumeration::get_values () const
{
    std::vector<std::string> vec;

    for (auto m : string_map)
    {
        vec.push_back(std::get<0>(m));
    }

    return vec;
}

std::string PropertyEnumeration::get_default () const
{
    return "";
}

bool PropertyEnumeration::set_value (const std::string& new_value)
{
    if (is_read_only())
    {
        return false;
    }

    auto element = string_map.find(new_value);

    if (element == string_map.end())
    {
        return false;
    }

    prop.value.i.value = element->second;

    notify_impl();

    return false;
}

std::string PropertyEnumeration::get_value () const
{
    return prop.value.s.value;
}

std::map<std::string, int> PropertyEnumeration::get_mapping () const
{
    return string_map;
}

PropertyBoolean::PropertyBoolean (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyBoolean::~PropertyBoolean ()
{}

bool PropertyBoolean::get_default () const
{
    return prop.value.b.default_value;
}

bool PropertyBoolean::set_value (bool value)
{
    if (is_read_only())
    {
        return false;
    }

    prop.value.b.value = value;
    notify_impl();

    return true;
}

bool PropertyBoolean::get_value () const
{
    return prop.value.b.value;
}

PropertyInteger::PropertyInteger (std::shared_ptr<PropertyImpl> prop_impl,
                                  const tcam_device_property& prop,
                                  VALUE_TYPE t)
    : Property (prop, t)
{
    impl = prop_impl;
}

PropertyInteger::~PropertyInteger ()
{}

int64_t PropertyInteger::get_default () const
{
    return prop.value.i.default_value;
}

int64_t PropertyInteger::get_min () const
{
    return this->prop.value.i.min;
}

int64_t PropertyInteger::get_max () const
{
    return this->prop.value.i.max;
}

int64_t PropertyInteger::get_step () const
{
  return this->prop.value.i.step;
}

int64_t PropertyInteger::get_value () const
{
    return this->prop.value.i.value;
}

bool PropertyInteger::set_value (int64_t new_value)
{
    // if (is_read_only())
    // return false;

    tcam_value_int& i = this->prop.value.i;

    if (i.min > new_value || i.max < new_value)
        return false;

    if (i.step > 0 && new_value % i.step != 0)
    {
        return false;
    }

    i.value = new_value;

    notify_impl();

    return true;
}

PropertyDouble::PropertyDouble (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyDouble::~PropertyDouble ()
{}

double PropertyDouble::get_default () const
{
    return prop.value.d.default_value;
}

double PropertyDouble::get_min () const
{
    return this->prop.value.d.min;
}

double PropertyDouble::get_max () const
{
    return this->prop.value.d.max;
}

double PropertyDouble::get_step () const
{
    return this->prop.value.d.step;
}

double PropertyDouble::get_value () const
{
    return this->prop.value.d.value;
}

bool PropertyDouble::set_value (double new_value)
{
    if (is_read_only())
    {
        return false;
    }

    tcam_value_double& d = this->prop.value.d;

    if (d.min > new_value || d.max < new_value)
    {
        return false;
    }

    d.value = new_value;

    notify_impl();

    return false;
}

PropertyButton::PropertyButton (std::shared_ptr<PropertyImpl> prop_impl,
                                const tcam_device_property& prop,
                                VALUE_TYPE t)
    : Property(prop, t)
{
    impl = prop_impl;
}

PropertyButton::~PropertyButton ()
{}

bool PropertyButton::activate ()
{
    if (is_read_only())
        return false;

    notify_impl();

    return true;
}
<|endoftext|>


<commit_before><commit_msg>[HTML5] Fix mouse_mode and fullscreen detection.<commit_after><|endoftext|>