<commit_before>/*
 * Copyright (c) 2017, 2020 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * 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.
 */

#ifndef __CPU_STATIC_INST_HH__
#define __CPU_STATIC_INST_HH__

#include <bitset>
#include <memory>
#include <string>

#include "arch/registers.hh"
#include "arch/types.hh"
#include "base/logging.hh"
#include "base/refcnt.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
#include "cpu/op_class.hh"
#include "cpu/reg_class.hh"
#include "cpu/static_inst_fwd.hh"
#include "cpu/thread_context.hh"
#include "enums/StaticInstFlags.hh"
#include "sim/byteswap.hh"

// forward declarations
class Packet;

class ExecContext;

namespace Loader
{
class SymbolTable;
} // namespace Loader

namespace Trace
{
class InstRecord;
} // namespace Trace

/**
 * Base, ISA-independent static instruction class.
 *
 * The main component of this class is the vector of flags and the
 * associated methods for reading them.  Any object that can rely
 * solely on these flags can process instructions without being
 * recompiled for multiple ISAs.
 */
class StaticInst : public RefCounted, public StaticInstFlags
{
  public:
    /// Binary extended machine instruction type.
    typedef TheISA::ExtMachInst ExtMachInst;

    enum {
        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,        //< Max source regs
        MaxInstDestRegs = TheISA::MaxInstDestRegs       //< Max dest regs
    };

    using RegIdArrayPtr = RegId (StaticInst:: *)[];

  private:
    /// See srcRegIdx().
    RegId _srcRegIdx[MaxInstSrcRegs];
    RegIdArrayPtr _srcRegIdxPtr = nullptr;

    /// See destRegIdx().
    RegId _destRegIdx[MaxInstDestRegs];
    RegIdArrayPtr _destRegIdxPtr = nullptr;

  protected:

    /// Flag values for this instruction.
    std::bitset<Num_Flags> flags;

    /// See opClass().
    OpClass _opClass;

    /// See numSrcRegs().
    int8_t _numSrcRegs;

    /// See numDestRegs().
    int8_t _numDestRegs;

    /// The following are used to track physical register usage
    /// for machines with separate int & FP reg files.
    //@{
    int8_t _numFPDestRegs;
    int8_t _numIntDestRegs;
    int8_t _numCCDestRegs;
    //@}

    /** To use in architectures with vector register file. */
    /** @{ */
    int8_t _numVecDestRegs;
    int8_t _numVecElemDestRegs;
    int8_t _numVecPredDestRegs;
    /** @} */

  public:

    /// @name Register information.
    /// The sum of numFPDestRegs(), numIntDestRegs(), numVecDestRegs(),
    /// numVecElemDestRegs() and numVecPredDestRegs() equals numDestRegs().
    /// The former two functions are used to track physical register usage for
    /// machines with separate int & FP reg files, the next three are for
    /// machines with vector and predicate register files.
    //@{
    /// Number of source registers.
    int8_t numSrcRegs()  const { return _numSrcRegs; }
    /// Number of destination registers.
    int8_t numDestRegs() const { return _numDestRegs; }
    /// Number of floating-point destination regs.
    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
    /// Number of integer destination regs.
    int8_t numIntDestRegs() const { return _numIntDestRegs; }
    /// Number of vector destination regs.
    int8_t numVecDestRegs() const { return _numVecDestRegs; }
    /// Number of vector element destination regs.
    int8_t numVecElemDestRegs() const { return _numVecElemDestRegs; }
    /// Number of predicate destination regs.
    int8_t numVecPredDestRegs() const { return _numVecPredDestRegs; }
    /// Number of coprocesor destination regs.
    int8_t numCCDestRegs() const { return _numCCDestRegs; }
    //@}

    /// @name Flag accessors.
    /// These functions are used to access the values of the various
    /// instruction property flags.  See StaticInst::Flags for descriptions
    /// of the individual flags.
    //@{

    bool isNop()          const { return flags[IsNop]; }

    bool
    isMemRef() const
    {
        return flags[IsLoad] || flags[IsStore] || flags[IsAtomic];
    }
    bool isLoad()         const { return flags[IsLoad]; }
    bool isStore()        const { return flags[IsStore]; }
    bool isAtomic()       const { return flags[IsAtomic]; }
    bool isStoreConditional()     const { return flags[IsStoreConditional]; }
    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
    bool isPrefetch()     const { return isInstPrefetch() ||
                                         isDataPrefetch(); }

    bool isInteger()      const { return flags[IsInteger]; }
    bool isFloating()     const { return flags[IsFloating]; }
    bool isVector()       const { return flags[IsVector]; }

    bool isControl()      const { return flags[IsControl]; }
    bool isCall()         const { return flags[IsCall]; }
    bool isReturn()       const { return flags[IsReturn]; }
    bool isDirectCtrl()   const { return flags[IsDirectControl]; }
    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
    bool isCondCtrl()     const { return flags[IsCondControl]; }
    bool isUncondCtrl()   const { return flags[IsUncondControl]; }

    bool isSerializing()  const { return flags[IsSerializing] ||
                                      flags[IsSerializeBefore] ||
                                      flags[IsSerializeAfter]; }
    bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
    bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
    bool isSquashAfter() const { return flags[IsSquashAfter]; }
    bool
    isFullMemBarrier() const
    {
        return flags[IsReadBarrier] && flags[IsWriteBarrier];
    }
    bool isReadBarrier() const { return flags[IsReadBarrier]; }
    bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
    bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
    bool isQuiesce() const { return flags[IsQuiesce]; }
    bool isUnverifiable() const { return flags[IsUnverifiable]; }
    bool isSyscall() const { return flags[IsSyscall]; }
    bool isMacroop() const { return flags[IsMacroop]; }
    bool isMicroop() const { return flags[IsMicroop]; }
    bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
    bool isLastMicroop() const { return flags[IsLastMicroop]; }
    bool isFirstMicroop() const { return flags[IsFirstMicroop]; }
    // hardware transactional memory
    // HtmCmds must be identified as such in order
    // to provide them with necessary memory ordering semantics.
    bool isHtmStart() const { return flags[IsHtmStart]; }
    bool isHtmStop() const { return flags[IsHtmStop]; }
    bool isHtmCancel() const { return flags[IsHtmCancel]; }

    bool
    isHtmCmd() const
    {
        return isHtmStart() || isHtmStop() || isHtmCancel();
    }
    //@}

    void setFirstMicroop() { flags[IsFirstMicroop] = true; }
    void setLastMicroop() { flags[IsLastMicroop] = true; }
    void setDelayedCommit() { flags[IsDelayedCommit] = true; }
    void setFlag(Flags f) { flags[f] = true; }

    /// Operation class.  Used to select appropriate function unit in issue.
    OpClass opClass()     const { return _opClass; }

    /// Return logical index (architectural reg num) of i'th destination reg.
    /// Only the entries from 0 through numDestRegs()-1 are valid.
    const RegId &destRegIdx(int i) const { return (this->*_destRegIdxPtr)[i]; }

    void
    setDestRegIdx(int i, const RegId &val)
    {
        (this->*_destRegIdxPtr)[i] = val;
    }

    /// Return logical index (architectural reg num) of i'th source reg.
    /// Only the entries from 0 through numSrcRegs()-1 are valid.
    const RegId &srcRegIdx(int i) const { return (this->*_srcRegIdxPtr)[i]; }

    void
    setSrcRegIdx(int i, const RegId &val)
    {
        (this->*_srcRegIdxPtr)[i] = val;
    }

    /// Pointer to a statically allocated "null" instruction object.
    static StaticInstPtr nullStaticInstPtr;

    /// Pointer to a statically allocated generic "nop" instruction object.
    static StaticInstPtr nopStaticInstPtr;

    /// The binary machine instruction.
    const ExtMachInst machInst;

  protected:

    /**
     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
     * methods.  Also useful to readily identify instructions from
     * within the debugger when #cachedDisassembly has not been
     * initialized.
     */
    const char *mnemonic;

    /**
     * String representation of disassembly (lazily evaluated via
     * disassemble()).
     */
    mutable std::string *cachedDisassembly;

    /**
     * Internal function to generate disassembly string.
     */
    virtual std::string
    generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const = 0;

    /// Constructor.
    /// It's important to initialize everything here to a sane
    /// default, since the decoder generally only overrides
    /// the fields that are meaningful for the particular
    /// instruction.
    StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
        : _srcRegIdxPtr(
                reinterpret_cast<RegIdArrayPtr>(&StaticInst::_srcRegIdx)),
          _destRegIdxPtr(
                reinterpret_cast<RegIdArrayPtr>(&StaticInst::_destRegIdx)),
          _opClass(__opClass),
          _numSrcRegs(0), _numDestRegs(0), _numFPDestRegs(0),
          _numIntDestRegs(0), _numCCDestRegs(0), _numVecDestRegs(0),
          _numVecElemDestRegs(0), _numVecPredDestRegs(0), machInst(_machInst),
          mnemonic(_mnemonic), cachedDisassembly(0)
    { }

  public:
    virtual ~StaticInst();

    virtual Fault execute(ExecContext *xc,
                          Trace::InstRecord *traceData) const = 0;

    virtual Fault initiateAcc(ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("initiateAcc not defined!");
    }

    virtual Fault completeAcc(Packet *pkt, ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("completeAcc not defined!");
    }

    virtual void advancePC(TheISA::PCState &pcState) const = 0;

    /**
     * Return the microop that goes with a particular micropc. This should
     * only be defined/used in macroops which will contain microops
     */
    virtual StaticInstPtr fetchMicroop(MicroPC upc) const;

    /**
     * Return the target address for a PC-relative branch.
     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
     * should be true).
     */
    virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const;

    /**
     * Return the target address for an indirect branch (jump).  The
     * register value is read from the supplied thread context, so
     * the result is valid only if the thread context is about to
     * execute the branch in question.  Invalid if not an indirect
     * branch (i.e. isIndirectCtrl() should be true).
     */
    virtual TheISA::PCState branchTarget(ThreadContext *tc) const;

    /**
     * Return true if the instruction is a control transfer, and if so,
     * return the target address as well.
     */
    bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
                         TheISA::PCState &tgt) const;

    /**
     * Return string representation of disassembled instruction.
     * The default version of this function will call the internal
     * virtual generateDisassembly() function to get the string,
     * then cache it in #cachedDisassembly.  If the disassembly
     * should not be cached, this function should be overridden directly.
     */
    virtual const std::string &disassemble(Addr pc,
        const Loader::SymbolTable *symtab=nullptr) const;

    /**
     * Print a separator separated list of this instruction's set flag
     * names on the given stream.
     */
    void printFlags(std::ostream &outs, const std::string &separator) const;

    /// Return name of machine instruction
    std::string getName() { return mnemonic; }

  protected:
    template<typename T>
    size_t
    simpleAsBytes(void *buf, size_t max_size, const T &t)
    {
        size_t size = sizeof(T);
        if (size <= max_size)
            *reinterpret_cast<T *>(buf) = htole<T>(t);
        return size;
    }

  public:
    /**
     * Instruction classes can override this function to return a
     * a representation of themselves as a blob of bytes, generally assumed to
     * be that instructions ExtMachInst.
     *
     * buf is a buffer to hold the bytes.
     * max_size is the size allocated for that buffer by the caller.
     * The return value is how much data was actually put into the buffer,
     * zero if no data was put in the buffer, or the necessary size of the
     * buffer if there wasn't enough space.
     */
    virtual size_t asBytes(void *buf, size_t max_size) { return 0; }
};

#endif // __CPU_STATIC_INST_HH__
<commit_msg>cpu: Add an StaticInst accessor for setting register index storage.<commit_after>/*
 * Copyright (c) 2017, 2020 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * 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.
 */

#ifndef __CPU_STATIC_INST_HH__
#define __CPU_STATIC_INST_HH__

#include <bitset>
#include <memory>
#include <string>

#include "arch/registers.hh"
#include "arch/types.hh"
#include "base/logging.hh"
#include "base/refcnt.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
#include "cpu/op_class.hh"
#include "cpu/reg_class.hh"
#include "cpu/static_inst_fwd.hh"
#include "cpu/thread_context.hh"
#include "enums/StaticInstFlags.hh"
#include "sim/byteswap.hh"

// forward declarations
class Packet;

class ExecContext;

namespace Loader
{
class SymbolTable;
} // namespace Loader

namespace Trace
{
class InstRecord;
} // namespace Trace

/**
 * Base, ISA-independent static instruction class.
 *
 * The main component of this class is the vector of flags and the
 * associated methods for reading them.  Any object that can rely
 * solely on these flags can process instructions without being
 * recompiled for multiple ISAs.
 */
class StaticInst : public RefCounted, public StaticInstFlags
{
  public:
    /// Binary extended machine instruction type.
    typedef TheISA::ExtMachInst ExtMachInst;

    enum {
        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,        //< Max source regs
        MaxInstDestRegs = TheISA::MaxInstDestRegs       //< Max dest regs
    };

    using RegIdArrayPtr = RegId (StaticInst:: *)[];

  private:
    /// See srcRegIdx().
    RegId _srcRegIdx[MaxInstSrcRegs];
    RegIdArrayPtr _srcRegIdxPtr = nullptr;

    /// See destRegIdx().
    RegId _destRegIdx[MaxInstDestRegs];
    RegIdArrayPtr _destRegIdxPtr = nullptr;

  protected:

    /// Flag values for this instruction.
    std::bitset<Num_Flags> flags;

    /// See opClass().
    OpClass _opClass;

    /// See numSrcRegs().
    int8_t _numSrcRegs;

    /// See numDestRegs().
    int8_t _numDestRegs;

    /// The following are used to track physical register usage
    /// for machines with separate int & FP reg files.
    //@{
    int8_t _numFPDestRegs;
    int8_t _numIntDestRegs;
    int8_t _numCCDestRegs;
    //@}

    /** To use in architectures with vector register file. */
    /** @{ */
    int8_t _numVecDestRegs;
    int8_t _numVecElemDestRegs;
    int8_t _numVecPredDestRegs;
    /** @} */

  public:

    /// @name Register information.
    /// The sum of numFPDestRegs(), numIntDestRegs(), numVecDestRegs(),
    /// numVecElemDestRegs() and numVecPredDestRegs() equals numDestRegs().
    /// The former two functions are used to track physical register usage for
    /// machines with separate int & FP reg files, the next three are for
    /// machines with vector and predicate register files.
    //@{
    /// Number of source registers.
    int8_t numSrcRegs()  const { return _numSrcRegs; }
    /// Number of destination registers.
    int8_t numDestRegs() const { return _numDestRegs; }
    /// Number of floating-point destination regs.
    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
    /// Number of integer destination regs.
    int8_t numIntDestRegs() const { return _numIntDestRegs; }
    /// Number of vector destination regs.
    int8_t numVecDestRegs() const { return _numVecDestRegs; }
    /// Number of vector element destination regs.
    int8_t numVecElemDestRegs() const { return _numVecElemDestRegs; }
    /// Number of predicate destination regs.
    int8_t numVecPredDestRegs() const { return _numVecPredDestRegs; }
    /// Number of coprocesor destination regs.
    int8_t numCCDestRegs() const { return _numCCDestRegs; }
    //@}

    /// @name Flag accessors.
    /// These functions are used to access the values of the various
    /// instruction property flags.  See StaticInst::Flags for descriptions
    /// of the individual flags.
    //@{

    bool isNop()          const { return flags[IsNop]; }

    bool
    isMemRef() const
    {
        return flags[IsLoad] || flags[IsStore] || flags[IsAtomic];
    }
    bool isLoad()         const { return flags[IsLoad]; }
    bool isStore()        const { return flags[IsStore]; }
    bool isAtomic()       const { return flags[IsAtomic]; }
    bool isStoreConditional()     const { return flags[IsStoreConditional]; }
    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
    bool isPrefetch()     const { return isInstPrefetch() ||
                                         isDataPrefetch(); }

    bool isInteger()      const { return flags[IsInteger]; }
    bool isFloating()     const { return flags[IsFloating]; }
    bool isVector()       const { return flags[IsVector]; }

    bool isControl()      const { return flags[IsControl]; }
    bool isCall()         const { return flags[IsCall]; }
    bool isReturn()       const { return flags[IsReturn]; }
    bool isDirectCtrl()   const { return flags[IsDirectControl]; }
    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
    bool isCondCtrl()     const { return flags[IsCondControl]; }
    bool isUncondCtrl()   const { return flags[IsUncondControl]; }

    bool isSerializing()  const { return flags[IsSerializing] ||
                                      flags[IsSerializeBefore] ||
                                      flags[IsSerializeAfter]; }
    bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
    bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
    bool isSquashAfter() const { return flags[IsSquashAfter]; }
    bool
    isFullMemBarrier() const
    {
        return flags[IsReadBarrier] && flags[IsWriteBarrier];
    }
    bool isReadBarrier() const { return flags[IsReadBarrier]; }
    bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
    bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
    bool isQuiesce() const { return flags[IsQuiesce]; }
    bool isUnverifiable() const { return flags[IsUnverifiable]; }
    bool isSyscall() const { return flags[IsSyscall]; }
    bool isMacroop() const { return flags[IsMacroop]; }
    bool isMicroop() const { return flags[IsMicroop]; }
    bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
    bool isLastMicroop() const { return flags[IsLastMicroop]; }
    bool isFirstMicroop() const { return flags[IsFirstMicroop]; }
    // hardware transactional memory
    // HtmCmds must be identified as such in order
    // to provide them with necessary memory ordering semantics.
    bool isHtmStart() const { return flags[IsHtmStart]; }
    bool isHtmStop() const { return flags[IsHtmStop]; }
    bool isHtmCancel() const { return flags[IsHtmCancel]; }

    bool
    isHtmCmd() const
    {
        return isHtmStart() || isHtmStop() || isHtmCancel();
    }
    //@}

    void setFirstMicroop() { flags[IsFirstMicroop] = true; }
    void setLastMicroop() { flags[IsLastMicroop] = true; }
    void setDelayedCommit() { flags[IsDelayedCommit] = true; }
    void setFlag(Flags f) { flags[f] = true; }

    /// Operation class.  Used to select appropriate function unit in issue.
    OpClass opClass()     const { return _opClass; }

    /// Return logical index (architectural reg num) of i'th destination reg.
    /// Only the entries from 0 through numDestRegs()-1 are valid.
    const RegId &destRegIdx(int i) const { return (this->*_destRegIdxPtr)[i]; }

    void
    setDestRegIdx(int i, const RegId &val)
    {
        (this->*_destRegIdxPtr)[i] = val;
    }

    /// Return logical index (architectural reg num) of i'th source reg.
    /// Only the entries from 0 through numSrcRegs()-1 are valid.
    const RegId &srcRegIdx(int i) const { return (this->*_srcRegIdxPtr)[i]; }

    void
    setSrcRegIdx(int i, const RegId &val)
    {
        (this->*_srcRegIdxPtr)[i] = val;
    }

    /// Pointer to a statically allocated "null" instruction object.
    static StaticInstPtr nullStaticInstPtr;

    /// Pointer to a statically allocated generic "nop" instruction object.
    static StaticInstPtr nopStaticInstPtr;

    /// The binary machine instruction.
    const ExtMachInst machInst;

  protected:

    /**
     * Set the pointers which point to the arrays of source and destination
     * register indices. These will be defined in derived classes which know
     * what size they need to be, and installed here so they can be accessed
     * with the base class accessors.
     */
    void
    setRegIdxArrays(RegIdArrayPtr src, RegIdArrayPtr dest)
    {
        _srcRegIdxPtr = src;
        _destRegIdxPtr = dest;
    }

    /**
     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
     * methods.  Also useful to readily identify instructions from
     * within the debugger when #cachedDisassembly has not been
     * initialized.
     */
    const char *mnemonic;

    /**
     * String representation of disassembly (lazily evaluated via
     * disassemble()).
     */
    mutable std::string *cachedDisassembly;

    /**
     * Internal function to generate disassembly string.
     */
    virtual std::string
    generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const = 0;

    /// Constructor.
    /// It's important to initialize everything here to a sane
    /// default, since the decoder generally only overrides
    /// the fields that are meaningful for the particular
    /// instruction.
    StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
        : _srcRegIdxPtr(
                reinterpret_cast<RegIdArrayPtr>(&StaticInst::_srcRegIdx)),
          _destRegIdxPtr(
                reinterpret_cast<RegIdArrayPtr>(&StaticInst::_destRegIdx)),
          _opClass(__opClass),
          _numSrcRegs(0), _numDestRegs(0), _numFPDestRegs(0),
          _numIntDestRegs(0), _numCCDestRegs(0), _numVecDestRegs(0),
          _numVecElemDestRegs(0), _numVecPredDestRegs(0), machInst(_machInst),
          mnemonic(_mnemonic), cachedDisassembly(0)
    { }

  public:
    virtual ~StaticInst();

    virtual Fault execute(ExecContext *xc,
                          Trace::InstRecord *traceData) const = 0;

    virtual Fault initiateAcc(ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("initiateAcc not defined!");
    }

    virtual Fault completeAcc(Packet *pkt, ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("completeAcc not defined!");
    }

    virtual void advancePC(TheISA::PCState &pcState) const = 0;

    /**
     * Return the microop that goes with a particular micropc. This should
     * only be defined/used in macroops which will contain microops
     */
    virtual StaticInstPtr fetchMicroop(MicroPC upc) const;

    /**
     * Return the target address for a PC-relative branch.
     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
     * should be true).
     */
    virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const;

    /**
     * Return the target address for an indirect branch (jump).  The
     * register value is read from the supplied thread context, so
     * the result is valid only if the thread context is about to
     * execute the branch in question.  Invalid if not an indirect
     * branch (i.e. isIndirectCtrl() should be true).
     */
    virtual TheISA::PCState branchTarget(ThreadContext *tc) const;

    /**
     * Return true if the instruction is a control transfer, and if so,
     * return the target address as well.
     */
    bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
                         TheISA::PCState &tgt) const;

    /**
     * Return string representation of disassembled instruction.
     * The default version of this function will call the internal
     * virtual generateDisassembly() function to get the string,
     * then cache it in #cachedDisassembly.  If the disassembly
     * should not be cached, this function should be overridden directly.
     */
    virtual const std::string &disassemble(Addr pc,
        const Loader::SymbolTable *symtab=nullptr) const;

    /**
     * Print a separator separated list of this instruction's set flag
     * names on the given stream.
     */
    void printFlags(std::ostream &outs, const std::string &separator) const;

    /// Return name of machine instruction
    std::string getName() { return mnemonic; }

  protected:
    template<typename T>
    size_t
    simpleAsBytes(void *buf, size_t max_size, const T &t)
    {
        size_t size = sizeof(T);
        if (size <= max_size)
            *reinterpret_cast<T *>(buf) = htole<T>(t);
        return size;
    }

  public:
    /**
     * Instruction classes can override this function to return a
     * a representation of themselves as a blob of bytes, generally assumed to
     * be that instructions ExtMachInst.
     *
     * buf is a buffer to hold the bytes.
     * max_size is the size allocated for that buffer by the caller.
     * The return value is how much data was actually put into the buffer,
     * zero if no data was put in the buffer, or the necessary size of the
     * buffer if there wasn't enough space.
     */
    virtual size_t asBytes(void *buf, size_t max_size) { return 0; }
};

#endif // __CPU_STATIC_INST_HH__
<|endoftext|>


<commit_before><commit_msg>sys/wait for linux<commit_after><|endoftext|>


<commit_before><commit_msg>Slightly better cleanup<commit_after><|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
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 author 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.

*/

#include "libtorrent/create_torrent.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/storage.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/bind.hpp>

#ifndef TORRENT_WINDOWS
#include <sys/types.h>
#include <sys/stat.h>
#endif

namespace gr = boost::gregorian;

namespace libtorrent
{
	namespace detail
	{
		int TORRENT_EXPORT get_file_attributes(boost::filesystem::path const& p)
		{
#ifdef TORRENT_WINDOWS

#ifdef TORRENT_USE_WPATH
			std::wstring path = convert_to_wstring(p.external_file_string());
#else
			std::string path = utf8_native(p.external_file_string());
#endif
			DWORD attr = GetFileAttributes(path.c_str());
			if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
			return 0;
#else
			struct stat s;
			if (stat(p.external_file_string().c_str(), &s) < 0) return 0;
			return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif
		}

		int TORRENT_EXPORT get_file_attributes(boost::filesystem::wpath const& p)
		{
#ifdef TORRENT_WINDOWS
			std::wstring const& path = p.external_file_string();
			DWORD attr = GetFileAttributes(path.c_str());
			if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
			return 0;
#else
			std::string utf8;
			wchar_utf8(p.string(), utf8);
			struct stat s;
			if (stat(utf8.c_str(), &s) < 0) return 0;
			return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif
		}
	}

	create_torrent::create_torrent(file_storage& fs, int piece_size, int pad_file_limit, int flags)
		: m_files(fs)
		, m_creation_date(pt::second_clock::universal_time())
		, m_multifile(fs.num_files() > 1)
		, m_private(false)
		, m_merkle_torrent(flags & merkle)
	{
		TORRENT_ASSERT(fs.num_files() > 0);
#if BOOST_VERSION < 103600
		if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true;
#else
		if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
#endif

		// a piece_size of 0 means automatic
		if (piece_size == 0 && !m_merkle_torrent)
		{
			const int target_size = 40 * 1024;
			piece_size = fs.total_size() / (target_size / 20);

			int i = 16*1024;
			for (; i < 2*1024*1024; i *= 2)
			{
				if (piece_size > i) continue;
				break;
			}
			piece_size = i;
		}
		else if (piece_size == 0 && m_merkle_torrent)
		{
			piece_size = 16*1024;
		}

		// make sure the size is an even power of 2
#ifndef NDEBUG
		for (int i = 0; i < 32; ++i)
		{
			if (piece_size & (1 << i))
			{
				TORRENT_ASSERT((piece_size & ~(1 << i)) == 0);
				break;
			}
		}
#endif
		m_files.set_piece_length(piece_size);
		if (flags & optimize)
			m_files.optimize(pad_file_limit);
		m_files.set_num_pieces(static_cast<int>(
			(m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
		m_piece_hash.resize(m_files.num_pieces());
	}

	create_torrent::create_torrent(torrent_info const& ti)
		: m_files(const_cast<file_storage&>(ti.files()))
		, m_creation_date(pt::second_clock::universal_time())
		, m_multifile(ti.num_files() > 1)
		, m_private(ti.priv())
		, m_merkle_torrent(ti.is_merkle_torrent())
	{
		TORRENT_ASSERT(ti.is_valid());
		if (ti.creation_date()) m_creation_date = *ti.creation_date();

		if (!ti.creator().empty()) set_creator(ti.creator().c_str());
		if (!ti.comment().empty()) set_comment(ti.comment().c_str());

		torrent_info::nodes_t const& nodes = ti.nodes();
		for (torrent_info::nodes_t::const_iterator i = nodes.begin()
			, end(nodes.end()); i != end; ++i)
			add_node(*i);

		std::vector<libtorrent::announce_entry> const& trackers = ti.trackers();
		for (std::vector<libtorrent::announce_entry>::const_iterator i = trackers.begin()
			, end(trackers.end()); i != end; ++i)
			add_tracker(i->url, i->tier);

		std::vector<std::string> const& web_seeds = ti.url_seeds();
		for (std::vector<std::string>::const_iterator i = web_seeds.begin()
			, end(web_seeds.end()); i != end; ++i)
			add_url_seed(*i);

		m_piece_hash.resize(m_files.num_pieces());
		for (int i = 0; i < num_pieces(); ++i) set_hash(i, ti.hash_for_piece(i));

		m_info_dict = bdecode(&ti.metadata()[0], &ti.metadata()[0] + ti.metadata_size());
		m_info_hash = ti.info_hash();
	}

	entry create_torrent::generate() const
	{
		TORRENT_ASSERT(m_files.piece_length() > 0);

		entry dict;

		if (m_files.num_files() == 0)
			return dict;

		if (!m_urls.empty()) dict["announce"] = m_urls.front().first;

		if (!m_nodes.empty())
		{
			entry& nodes = dict["nodes"];
			entry::list_type& nodes_list = nodes.list();
			for (nodes_t::const_iterator i = m_nodes.begin()
				, end(m_nodes.end()); i != end; ++i)
			{
				entry::list_type node;
				node.push_back(entry(i->first));
				node.push_back(entry(i->second));
				nodes_list.push_back(entry(node));
			}
		}

		if (m_urls.size() > 1)
		{
			entry trackers(entry::list_t);
			entry tier(entry::list_t);
			int current_tier = m_urls.front().second;
			for (std::vector<announce_entry>::const_iterator i = m_urls.begin();
				i != m_urls.end(); ++i)
			{
				if (i->second != current_tier)
				{
					current_tier = i->second;
					trackers.list().push_back(tier);
					tier.list().clear();
				}
				tier.list().push_back(entry(i->first));
			}
			trackers.list().push_back(tier);
			dict["announce-list"] = trackers;
		}

		if (!m_comment.empty())
			dict["comment"] = m_comment;

		dict["creation date"] =
			(m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds();

		if (!m_created_by.empty())
			dict["created by"] = m_created_by;

		if (!m_url_seeds.empty())
		{
			if (m_url_seeds.size() == 1)
			{
				dict["url-list"] = m_url_seeds.front();
			}
			else
			{
				entry& list = dict["url-list"];
				for (std::vector<std::string>::const_iterator i
					= m_url_seeds.begin(); i != m_url_seeds.end(); ++i)
				{
					list.list().push_back(entry(*i));
				}
			}
		}

		entry& info = dict["info"];
		if (m_info_dict.type() == entry::dictionary_t)
		{
			info = m_info_dict;
			return dict;
		}

		info["name"] = m_files.name();

		if (m_private) info["private"] = 1;

		if (!m_multifile)
		{
			info["length"] = m_files.at(0).size;
		}
		else
		{
			if (!info.find_key("files"))
			{
				entry& files = info["files"];

				for (file_storage::iterator i = m_files.begin();
					i != m_files.end(); ++i)
				{
					files.list().push_back(entry());
					entry& file_e = files.list().back();
					file_e["length"] = i->size;
					entry& path_e = file_e["path"];

#if BOOST_VERSION < 103600
					TORRENT_ASSERT(i->path.has_branch_path());
#else
					TORRENT_ASSERT(i->path.has_parent_path());
#endif
					TORRENT_ASSERT(*i->path.begin() == m_files.name());

					for (fs::path::iterator j = boost::next(i->path.begin());
						j != i->path.end(); ++j)
					{
						path_e.list().push_back(entry(*j));
					}
					if (i->pad_file || i->hidden_attribute || i->executable_attribute)
					{
						std::string& attr = file_e["attr"].string();
						if (i->pad_file) attr += 'p';
						if (i->hidden_attribute) attr += 'h';
						if (i->executable_attribute) attr += 'x';
					}
				}
			}
		}

		info["piece length"] = m_files.piece_length();
		if (m_merkle_torrent)
		{
			std::vector<sha1_hash> merkle_tree;

			// defined in torrent_info.cpp
			int merkle_num_leafs(int);
			int merkle_num_nodes(int);
			int merkle_get_parent(int);
			int merkle_get_sibling(int);

			int num_leafs = merkle_num_leafs(m_files.num_pieces());
			int num_nodes = merkle_num_nodes(num_leafs);
			int first_leaf = num_nodes - num_leafs;
			merkle_tree.resize(num_nodes);
			int num_pieces = m_piece_hash.size();
			for (int i = 0; i < num_pieces; ++i)
				merkle_tree[first_leaf + i] = m_piece_hash[i];
			sha1_hash filler(0);
			for (int i = num_pieces; i < num_leafs; ++i)
				merkle_tree[first_leaf + i] = filler;

			// now that we have initialized all leaves, build
			// each level bottom-up
			int level_start = first_leaf;
			int level_size = num_leafs;
			while (level_start > 0)
			{
				int parent = merkle_get_parent(level_start);
				for (int i = level_start; i < level_start + level_size; i += 2, ++parent)
				{
					hasher h;
					h.update((char const*)&merkle_tree[i][0], 20);
					h.update((char const*)&merkle_tree[i+1][0], 20);
					merkle_tree[parent] = h.final();
				}
				level_start = merkle_get_parent(level_start);
				level_size /= 2;
			}
			TORRENT_ASSERT(level_size == 1);
			std::string& p = info["root hash"].string();
			p.assign((char const*)&merkle_tree[0][0], 20);
		}
		else
		{
			std::string& p = info["pieces"].string();

			for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
				i != m_piece_hash.end(); ++i)
			{
				p.append((char*)i->begin(), (char*)i->end());
			}
		}

		std::vector<char> buf;
		bencode(std::back_inserter(buf), info);
		m_info_hash = hasher(&buf[0], buf.size()).final();

		return dict;

	}

	void create_torrent::add_tracker(std::string const& url, int tier)
	{
		m_urls.push_back(announce_entry(url, tier));

		using boost::bind;
		std::sort(m_urls.begin(), m_urls.end()
			, bind(&announce_entry::second, _1) < bind(&announce_entry::second, _2));
	}

	void create_torrent::set_hash(int index, sha1_hash const& h)
	{
		TORRENT_ASSERT(index >= 0);
		TORRENT_ASSERT(index < (int)m_piece_hash.size());
		m_piece_hash[index] = h;
	}

	void create_torrent::add_node(std::pair<std::string, int> const& node)
	{
		m_nodes.push_back(node);
	}

	void create_torrent::add_url_seed(std::string const& url)
	{
		m_url_seeds.push_back(url);
	}

	void create_torrent::set_comment(char const* str)
	{
		m_comment = str;
	}

	void create_torrent::set_creator(char const* str)
	{
		m_created_by = str;
	}

}

<commit_msg>fixed windows build<commit_after>/*

Copyright (c) 2008, Arvid Norberg
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 author 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.

*/

#include "libtorrent/create_torrent.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/storage.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/bind.hpp>

#ifndef TORRENT_WINDOWS
#include <sys/types.h>
#include <sys/stat.h>
#endif

namespace gr = boost::gregorian;

namespace libtorrent
{
	// defined in torrent_info.cpp
	int merkle_num_leafs(int);
	int merkle_num_nodes(int);
	int merkle_get_parent(int);
	int merkle_get_sibling(int);

	namespace detail
	{
		int TORRENT_EXPORT get_file_attributes(boost::filesystem::path const& p)
		{
#ifdef TORRENT_WINDOWS

#ifdef TORRENT_USE_WPATH
			std::wstring path = convert_to_wstring(p.external_file_string());
#else
			std::string path = utf8_native(p.external_file_string());
#endif
			DWORD attr = GetFileAttributes(path.c_str());
			if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
			return 0;
#else
			struct stat s;
			if (stat(p.external_file_string().c_str(), &s) < 0) return 0;
			return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif
		}

		int TORRENT_EXPORT get_file_attributes(boost::filesystem::wpath const& p)
		{
#ifdef TORRENT_WINDOWS
			std::wstring const& path = p.external_file_string();
			DWORD attr = GetFileAttributes(path.c_str());
			if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
			return 0;
#else
			std::string utf8;
			wchar_utf8(p.string(), utf8);
			struct stat s;
			if (stat(utf8.c_str(), &s) < 0) return 0;
			return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif
		}
	}

	create_torrent::create_torrent(file_storage& fs, int piece_size, int pad_file_limit, int flags)
		: m_files(fs)
		, m_creation_date(pt::second_clock::universal_time())
		, m_multifile(fs.num_files() > 1)
		, m_private(false)
		, m_merkle_torrent(flags & merkle)
	{
		TORRENT_ASSERT(fs.num_files() > 0);
#if BOOST_VERSION < 103600
		if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true;
#else
		if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
#endif

		// a piece_size of 0 means automatic
		if (piece_size == 0 && !m_merkle_torrent)
		{
			const int target_size = 40 * 1024;
			piece_size = fs.total_size() / (target_size / 20);

			int i = 16*1024;
			for (; i < 2*1024*1024; i *= 2)
			{
				if (piece_size > i) continue;
				break;
			}
			piece_size = i;
		}
		else if (piece_size == 0 && m_merkle_torrent)
		{
			piece_size = 16*1024;
		}

		// make sure the size is an even power of 2
#ifndef NDEBUG
		for (int i = 0; i < 32; ++i)
		{
			if (piece_size & (1 << i))
			{
				TORRENT_ASSERT((piece_size & ~(1 << i)) == 0);
				break;
			}
		}
#endif
		m_files.set_piece_length(piece_size);
		if (flags & optimize)
			m_files.optimize(pad_file_limit);
		m_files.set_num_pieces(static_cast<int>(
			(m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
		m_piece_hash.resize(m_files.num_pieces());
	}

	create_torrent::create_torrent(torrent_info const& ti)
		: m_files(const_cast<file_storage&>(ti.files()))
		, m_creation_date(pt::second_clock::universal_time())
		, m_multifile(ti.num_files() > 1)
		, m_private(ti.priv())
		, m_merkle_torrent(ti.is_merkle_torrent())
	{
		TORRENT_ASSERT(ti.is_valid());
		if (ti.creation_date()) m_creation_date = *ti.creation_date();

		if (!ti.creator().empty()) set_creator(ti.creator().c_str());
		if (!ti.comment().empty()) set_comment(ti.comment().c_str());

		torrent_info::nodes_t const& nodes = ti.nodes();
		for (torrent_info::nodes_t::const_iterator i = nodes.begin()
			, end(nodes.end()); i != end; ++i)
			add_node(*i);

		std::vector<libtorrent::announce_entry> const& trackers = ti.trackers();
		for (std::vector<libtorrent::announce_entry>::const_iterator i = trackers.begin()
			, end(trackers.end()); i != end; ++i)
			add_tracker(i->url, i->tier);

		std::vector<std::string> const& web_seeds = ti.url_seeds();
		for (std::vector<std::string>::const_iterator i = web_seeds.begin()
			, end(web_seeds.end()); i != end; ++i)
			add_url_seed(*i);

		m_piece_hash.resize(m_files.num_pieces());
		for (int i = 0; i < num_pieces(); ++i) set_hash(i, ti.hash_for_piece(i));

		m_info_dict = bdecode(&ti.metadata()[0], &ti.metadata()[0] + ti.metadata_size());
		m_info_hash = ti.info_hash();
	}

	entry create_torrent::generate() const
	{
		TORRENT_ASSERT(m_files.piece_length() > 0);

		entry dict;

		if (m_files.num_files() == 0)
			return dict;

		if (!m_urls.empty()) dict["announce"] = m_urls.front().first;

		if (!m_nodes.empty())
		{
			entry& nodes = dict["nodes"];
			entry::list_type& nodes_list = nodes.list();
			for (nodes_t::const_iterator i = m_nodes.begin()
				, end(m_nodes.end()); i != end; ++i)
			{
				entry::list_type node;
				node.push_back(entry(i->first));
				node.push_back(entry(i->second));
				nodes_list.push_back(entry(node));
			}
		}

		if (m_urls.size() > 1)
		{
			entry trackers(entry::list_t);
			entry tier(entry::list_t);
			int current_tier = m_urls.front().second;
			for (std::vector<announce_entry>::const_iterator i = m_urls.begin();
				i != m_urls.end(); ++i)
			{
				if (i->second != current_tier)
				{
					current_tier = i->second;
					trackers.list().push_back(tier);
					tier.list().clear();
				}
				tier.list().push_back(entry(i->first));
			}
			trackers.list().push_back(tier);
			dict["announce-list"] = trackers;
		}

		if (!m_comment.empty())
			dict["comment"] = m_comment;

		dict["creation date"] =
			(m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds();

		if (!m_created_by.empty())
			dict["created by"] = m_created_by;

		if (!m_url_seeds.empty())
		{
			if (m_url_seeds.size() == 1)
			{
				dict["url-list"] = m_url_seeds.front();
			}
			else
			{
				entry& list = dict["url-list"];
				for (std::vector<std::string>::const_iterator i
					= m_url_seeds.begin(); i != m_url_seeds.end(); ++i)
				{
					list.list().push_back(entry(*i));
				}
			}
		}

		entry& info = dict["info"];
		if (m_info_dict.type() == entry::dictionary_t)
		{
			info = m_info_dict;
			return dict;
		}

		info["name"] = m_files.name();

		if (m_private) info["private"] = 1;

		if (!m_multifile)
		{
			info["length"] = m_files.at(0).size;
		}
		else
		{
			if (!info.find_key("files"))
			{
				entry& files = info["files"];

				for (file_storage::iterator i = m_files.begin();
					i != m_files.end(); ++i)
				{
					files.list().push_back(entry());
					entry& file_e = files.list().back();
					file_e["length"] = i->size;
					entry& path_e = file_e["path"];

#if BOOST_VERSION < 103600
					TORRENT_ASSERT(i->path.has_branch_path());
#else
					TORRENT_ASSERT(i->path.has_parent_path());
#endif
					TORRENT_ASSERT(*i->path.begin() == m_files.name());

					for (fs::path::iterator j = boost::next(i->path.begin());
						j != i->path.end(); ++j)
					{
						path_e.list().push_back(entry(*j));
					}
					if (i->pad_file || i->hidden_attribute || i->executable_attribute)
					{
						std::string& attr = file_e["attr"].string();
						if (i->pad_file) attr += 'p';
						if (i->hidden_attribute) attr += 'h';
						if (i->executable_attribute) attr += 'x';
					}
				}
			}
		}

		info["piece length"] = m_files.piece_length();
		if (m_merkle_torrent)
		{
			std::vector<sha1_hash> merkle_tree;

			int num_leafs = merkle_num_leafs(m_files.num_pieces());
			int num_nodes = merkle_num_nodes(num_leafs);
			int first_leaf = num_nodes - num_leafs;
			merkle_tree.resize(num_nodes);
			int num_pieces = m_piece_hash.size();
			for (int i = 0; i < num_pieces; ++i)
				merkle_tree[first_leaf + i] = m_piece_hash[i];
			sha1_hash filler(0);
			for (int i = num_pieces; i < num_leafs; ++i)
				merkle_tree[first_leaf + i] = filler;

			// now that we have initialized all leaves, build
			// each level bottom-up
			int level_start = first_leaf;
			int level_size = num_leafs;
			while (level_start > 0)
			{
				int parent = merkle_get_parent(level_start);
				for (int i = level_start; i < level_start + level_size; i += 2, ++parent)
				{
					hasher h;
					h.update((char const*)&merkle_tree[i][0], 20);
					h.update((char const*)&merkle_tree[i+1][0], 20);
					merkle_tree[parent] = h.final();
				}
				level_start = merkle_get_parent(level_start);
				level_size /= 2;
			}
			TORRENT_ASSERT(level_size == 1);
			std::string& p = info["root hash"].string();
			p.assign((char const*)&merkle_tree[0][0], 20);
		}
		else
		{
			std::string& p = info["pieces"].string();

			for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
				i != m_piece_hash.end(); ++i)
			{
				p.append((char*)i->begin(), (char*)i->end());
			}
		}

		std::vector<char> buf;
		bencode(std::back_inserter(buf), info);
		m_info_hash = hasher(&buf[0], buf.size()).final();

		return dict;

	}

	void create_torrent::add_tracker(std::string const& url, int tier)
	{
		m_urls.push_back(announce_entry(url, tier));

		using boost::bind;
		std::sort(m_urls.begin(), m_urls.end()
			, bind(&announce_entry::second, _1) < bind(&announce_entry::second, _2));
	}

	void create_torrent::set_hash(int index, sha1_hash const& h)
	{
		TORRENT_ASSERT(index >= 0);
		TORRENT_ASSERT(index < (int)m_piece_hash.size());
		m_piece_hash[index] = h;
	}

	void create_torrent::add_node(std::pair<std::string, int> const& node)
	{
		m_nodes.push_back(node);
	}

	void create_torrent::add_url_seed(std::string const& url)
	{
		m_url_seeds.push_back(url);
	}

	void create_torrent::set_comment(char const* str)
	{
		m_comment = str;
	}

	void create_torrent::set_creator(char const* str)
	{
		m_created_by = str;
	}

}

<|endoftext|>


<commit_before>/*
 * OUTLINE
 * 1. Mark/prepare for sorting.
 *   1. Handle supplementary/secondary
 *     1. How?
 *       1. Make a stack for reads with a given read name
 *         1. Add tags for SU/MU/LM to all reads in the set such that they have the same keys
 *         2. Add a tag to read 1 and read 2 for each (if any) of its supplemental alignments to know what to wait for.
 *           1. Add a tag to the supplementals for their actual position/contig, flag as unmapped, and move to their primaries.
 *         3. Output to stdout
 * 2. Pass to samtools sort and sort by coordinate.
 * 3. Load in a buffer of reads
 *   1. Fill a large stack of buffered reads.
 *   2. Build a hashmap for r1/r2 combinations.
 *   3. Once all reads needed for an alignment signature set have been loaded, collapse them, putting the supplementals in a separate table.
 *     1. If a read name set is not collapsed and there are supplementals, unset the unmapped flag and change the coordinates back to what they should be.
 *     2. Otherwise, ignore the supplementals because they'll be realigned.
 */
#include "bmf_markrsq.h"
#include <getopt.h>

namespace BMF {

    struct markrsq_conf_t {
        struct mark_conf_t {
            samFile *fp;
            bam_hdr_t *hdr;
            samFile *ofp;
            size_t stack_start;
            mark_conf_t() :
                fp(nullptr),
                hdr(nullptr),
                ofp(nullptr),
                stack_start(10)
            {
            }
            ~mark_conf_t() {
                if(fp) sam_close(fp);
                if(hdr) bam_hdr_destroy(hdr);
                if(ofp) sam_close(ofp);
            }
        } m;
        struct sort_conf_t {
            std::string pipe_name;
            std::string sortmem; // Memory per thread
            std::string tmp_prefix;
            uint32_t threads:8;
            sort_conf_t() :
                pipe_name(""),
                sortmem("500M"),
                tmp_prefix(""),
                threads(1)
            {
            }
        } s;
        struct rsq_conf_t {
            std::string pipe_name;
            samFile *fp;
            samFile *ofp;
            uint32_t mismatch_limit:4; // Maximum number of barcode mismatches for a rescue
            uint32_t use_unclipped_start:1; // Use unclipped start for rescue rather than pos
            rsq_conf_t() :
                pipe_name(""),
                fp(nullptr),
                ofp(nullptr),
                mismatch_limit(2),
                use_unclipped_start(1)
            {
            }
            ~rsq_conf_t() {
                if(fp) sam_close(fp), fp = nullptr;
                sam_close(ofp), ofp = nullptr;
            }
        } r;
        FILE *pipe_call;
        int level;
        markrsq_conf_t():
            m(),
            s(),
            r(),
            pipe_call(nullptr),
            level(6)
        {
        }
        void open_pipes(char *infname, char *outfname);
        void mark_core();
        void rsq_core();
        void process(char *infname, char *outfname) {
            open_pipes(infname, outfname);
            mark_core();
            rsq_core();
        }
    };

    /*
     * opens named pipes for mark -> sort + sort -> rsq
     */
    void markrsq_conf_t::open_pipes(char *infname, char *outfname) {
        if(s.pipe_name.empty()) {
            s.pipe_name.reserve(21uL);
            dlib::rand_string(const_cast<char *>(s.pipe_name.data()), 20uL);
            s.pipe_name.resize(20uL);
            s.pipe_name += infname; // Salt in case multiple instances are running in the same folder.
        }
        if(r.pipe_name.empty()) {
            r.pipe_name.reserve(21uL);
            dlib::rand_string(const_cast<char *>(r.pipe_name.data()), 20uL);
            r.pipe_name.resize(20uL);
            r.pipe_name += infname; // Salt in case multiple instances are running in the same folder.
        }
        if(s.tmp_prefix.empty()) {
            s.tmp_prefix.reserve(21uL);
            dlib::rand_string(const_cast<char *>(s.tmp_prefix.data()), 20uL);
            s.tmp_prefix.resize(20uL);
            s.tmp_prefix += infname; // Salt in case multiple instances are running in the same folder.
        }
        if((m.fp = sam_open(infname, "r")) == nullptr)
            LOG_EXIT("Could not open input sam %s.\n", infname);
        if((m.hdr = sam_hdr_read(m.fp)) == nullptr)
            LOG_EXIT("Could not read input sam %s's header.\n", infname);
        if(mkfifo(s.pipe_name.c_str(), 0666))
            LOG_EXIT("Could not open pipe %s.\n", s.pipe_name.c_str());
        if((m.ofp = sam_open(s.pipe_name.c_str(), "wb0")) == nullptr)
            LOG_EXIT("Could not open temporary pipe with name %s from htslib.\n", s.pipe_name.c_str());
        sam_hdr_write(m.ofp, m.hdr);
        if(mkfifo(r.pipe_name.c_str(), 0666))
            LOG_EXIT("Could not open pipe %s.\n", r.pipe_name.c_str());
        kstring_t ks = {0, 0, nullptr};
        ksprintf(&ks, "samtools sort -T%s -Obam -m%s -@%i -l0 -o%s %s",
                 s.tmp_prefix.c_str(),
                 s.sortmem.c_str(),
                 (int)s.threads,
                 r.pipe_name.c_str(),
                 s.pipe_name.c_str()
                 );
        std::string command(ks.s), free(ks.s);
        LOG_DEBUG("Pipe command: %s.\n", command.c_str());
        pipe_call = popen(command.c_str(), "w");
        r.fp = sam_open(r.pipe_name.c_str(), "r");
        r.ofp = sam_open(outfname, ("wb"s + std::to_string(level)).c_str());
        sam_hdr_write(r.ofp, m.hdr);
    }

    void markrsq_usage(int retcode)
    {
        fprintf(stderr,
                        "Unwritten usage. Eh.\n"
                );
        exit(retcode);
    }

    /*
     * Take in a name-sorted bam, marks reads appropriately, and builds a
     * hashmap of information for read pairs for the rescue step.
     * Writes
     */
    void markrsq_conf_t::mark_core() {
        if(!m.fp || !m.hdr) LOG_EXIT("Open pipes before running mark_core!\n");

        bam1_stack stack{(m.stack_start)};
        int c;
        bam1_t *b = bam_init1();
        while((c = sam_read1(m.fp, m.hdr, b) >= 0)) {

        }
        bam_destroy1(b);

        // end
        sam_close(m.fp), m.fp = nullptr;
        sam_close(m.ofp), m.ofp = nullptr;
    }

    void markrsq_conf_t::rsq_core() {
        // Clean up after.
        int ret;
        if((ret = pclose(pipe_call)) != 0) {
            LOG_EXIT("Pipe call failed: %i.\n", ret);
        }
        ~m();
        ~s();
        ~r();
    }

int markrsq_main(int argc, char *argv[]) {
    int c;
    if(argc < 2) markrsq_usage(EXIT_FAILURE);
    struct markrsq_conf_t conf;
    const struct option lopts[] = {
        {0, 0, 0, 0}
    };
    char *outfname(nullptr);
    while ((c = getopt_long(argc, argv, "m:o:T:l:u?h", lopts, nullptr)) >= 0) {
        switch (c) {
            case 'm': conf.s.sortmem = optarg; break;
            case 'T': conf.s.tmp_prefix = optarg; break;
            case 'o': outfname = optarg; break;
            case 'u': conf.r.use_unclipped_start = 1; break;
            case 'l': conf.level = atoi(optarg) % 10; break;
            case 'h': case '?': markrsq_usage(EXIT_SUCCESS);
        }
    }
    if(optind >= argc - 1) LOG_EXIT("Insufficient arguments. Input bam required!\n");
    conf.process(argv[optind], outfname ? outfname: "-");
    LOG_INFO("Successfully complete bmftools stack!\n");
    return 0;
}

}
<commit_msg>Eliminate the undefined behavior. But is it really so bad?<commit_after>/*
 * OUTLINE
 * 1. Mark/prepare for sorting.
 *   1. Handle supplementary/secondary
 *     1. How?
 *       1. Make a stack for reads with a given read name
 *         1. Add tags for SU/MU/LM to all reads in the set such that they have the same keys
 *         2. Add a tag to read 1 and read 2 for each (if any) of its supplemental alignments to know what to wait for.
 *           1. Add a tag to the supplementals for their actual position/contig, flag as unmapped, and move to their primaries.
 *         3. Output to stdout
 * 2. Pass to samtools sort and sort by coordinate.
 * 3. Load in a buffer of reads
 *   1. Fill a large stack of buffered reads.
 *   2. Build a hashmap for r1/r2 combinations.
 *   3. Once all reads needed for an alignment signature set have been loaded, collapse them, putting the supplementals in a separate table.
 *     1. If a read name set is not collapsed and there are supplementals, unset the unmapped flag and change the coordinates back to what they should be.
 *     2. Otherwise, ignore the supplementals because they'll be realigned.
 */
#include "bmf_markrsq.h"
#include <getopt.h>

namespace BMF {

    struct markrsq_conf_t {
        struct mark_conf_t {
            samFile *fp;
            bam_hdr_t *hdr;
            samFile *ofp;
            size_t stack_start;
            mark_conf_t() :
                fp(nullptr),
                hdr(nullptr),
                ofp(nullptr),
                stack_start(10)
            {
            }
            ~mark_conf_t() {
                if(fp) sam_close(fp);
                if(hdr) bam_hdr_destroy(hdr);
                if(ofp) sam_close(ofp);
            }
        } m;
        struct sort_conf_t {
            std::string pipe_name;
            std::string sortmem; // Memory per thread
            std::string tmp_prefix;
            uint32_t threads:8;
            sort_conf_t() :
                pipe_name(""),
                sortmem("500M"),
                tmp_prefix(""),
                threads(1)
            {
            }
        } s;
        struct rsq_conf_t {
            std::string pipe_name;
            samFile *fp;
            samFile *ofp;
            uint32_t mismatch_limit:4; // Maximum number of barcode mismatches for a rescue
            uint32_t use_unclipped_start:1; // Use unclipped start for rescue rather than pos
            rsq_conf_t() :
                pipe_name(""),
                fp(nullptr),
                ofp(nullptr),
                mismatch_limit(2),
                use_unclipped_start(1)
            {
            }
            ~rsq_conf_t() {
                if(fp) sam_close(fp), fp = nullptr;
                sam_close(ofp), ofp = nullptr;
            }
        } r;
        FILE *pipe_call;
        int level;
        markrsq_conf_t():
            m(),
            s(),
            r(),
            pipe_call(nullptr),
            level(6)
        {
        }
        void open_pipes(char *infname, char *outfname);
        void mark_core();
        void rsq_core();
        void process(char *infname, char *outfname) {
            open_pipes(infname, outfname);
            mark_core();
            rsq_core();
        }
    };

    /*
     * opens named pipes for mark -> sort + sort -> rsq
     */
    void markrsq_conf_t::open_pipes(char *infname, char *outfname) {
        if(s.pipe_name.empty()) {
            char buffer[32];
            dlib::rand_string(buffer, 20uL);
            s.pipe_name = buffer;
            s.pipe_name += infname; // Salt in case multiple instances are running in the same folder.
        }
        if(r.pipe_name.empty()) {
            char buffer[32];
            dlib::rand_string(buffer, 20uL);
            r.pipe_name = buffer;
            r.pipe_name += infname; // Salt in case multiple instances are running in the same folder.
        }
        if(s.tmp_prefix.empty()) {
            char buffer[32];
            dlib::rand_string(buffer, 20uL);
            s.tmp_prefix = buffer;
            s.tmp_prefix += infname; // Salt in case multiple instances are running in the same folder.
        }
        if((m.fp = sam_open(infname, "r")) == nullptr)
            LOG_EXIT("Could not open input sam %s.\n", infname);
        if((m.hdr = sam_hdr_read(m.fp)) == nullptr)
            LOG_EXIT("Could not read input sam %s's header.\n", infname);
        if(mkfifo(s.pipe_name.c_str(), 0666))
            LOG_EXIT("Could not open pipe %s.\n", s.pipe_name.c_str());
        if((m.ofp = sam_open(s.pipe_name.c_str(), "wb0")) == nullptr)
            LOG_EXIT("Could not open temporary pipe with name %s from htslib.\n", s.pipe_name.c_str());
        sam_hdr_write(m.ofp, m.hdr);
        if(mkfifo(r.pipe_name.c_str(), 0666))
            LOG_EXIT("Could not open pipe %s.\n", r.pipe_name.c_str());
        kstring_t ks = {0, 0, nullptr};
        ksprintf(&ks, "samtools sort -T%s -Obam -m%s -@%i -l0 -o%s %s",
                 s.tmp_prefix.c_str(),
                 s.sortmem.c_str(),
                 (int)s.threads,
                 r.pipe_name.c_str(),
                 s.pipe_name.c_str()
                 );
        std::string command(ks.s), free(ks.s);
        LOG_DEBUG("Pipe command: %s.\n", command.c_str());
        pipe_call = popen(command.c_str(), "w");
        r.fp = sam_open(r.pipe_name.c_str(), "r");
        r.ofp = sam_open(outfname, ("wb"s + std::to_string(level)).c_str());
        sam_hdr_write(r.ofp, m.hdr);
    }

    void markrsq_usage(int retcode)
    {
        fprintf(stderr,
                        "Unwritten usage. Eh.\n"
                );
        exit(retcode);
    }

    /*
     * Take in a name-sorted bam, marks reads appropriately, and builds a
     * hashmap of information for read pairs for the rescue step.
     * Writes
     */
    void markrsq_conf_t::mark_core() {
        if(!m.fp || !m.hdr) LOG_EXIT("Open pipes before running mark_core!\n");

        bam1_stack stack{(m.stack_start)};
        int c;
        bam1_t *b = bam_init1();
        while((c = sam_read1(m.fp, m.hdr, b) >= 0)) {

        }
        bam_destroy1(b);

        // end
        sam_close(m.fp), m.fp = nullptr;
        sam_close(m.ofp), m.ofp = nullptr;
    }

    void markrsq_conf_t::rsq_core() {
        // Clean up after.
        int ret;
        if((ret = pclose(pipe_call)) != 0) {
            LOG_EXIT("Pipe call failed: %i.\n", ret);
        }
        ~m();
        ~s();
        ~r();
    }

int markrsq_main(int argc, char *argv[]) {
    int c;
    if(argc < 2) markrsq_usage(EXIT_FAILURE);
    struct markrsq_conf_t conf;
    const struct option lopts[] = {
        {0, 0, 0, 0}
    };
    char *outfname(nullptr);
    while ((c = getopt_long(argc, argv, "m:o:T:l:u?h", lopts, nullptr)) >= 0) {
        switch (c) {
            case 'm': conf.s.sortmem = optarg; break;
            case 'T': conf.s.tmp_prefix = optarg; break;
            case 'o': outfname = optarg; break;
            case 'u': conf.r.use_unclipped_start = 1; break;
            case 'l': conf.level = atoi(optarg) % 10; break;
            case 'h': case '?': markrsq_usage(EXIT_SUCCESS);
        }
    }
    if(optind >= argc - 1) LOG_EXIT("Insufficient arguments. Input bam required!\n");
    conf.process(argv[optind], outfname ? outfname: "-");
    LOG_INFO("Successfully complete bmftools stack!\n");
    return 0;
}

}
<|endoftext|>


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

#include "sky/shell/platform/android/sky_main.h"

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/threading/simple_thread.h"
#include "jni/SkyMain_jni.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "sky/shell/shell.h"
#include "ui/gl/gl_surface.h"

using base::LazyInstance;

namespace sky {
namespace shell {

namespace {

LazyInstance<scoped_ptr<base::MessageLoop>> g_java_message_loop =
    LAZY_INSTANCE_INITIALIZER;

void InitializeLogging() {
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  logging::InitLogging(settings);
  // To view log output with IDs and timestamps use "adb logcat -v threadtime".
  logging::SetLogItems(false,   // Process ID
                       false,   // Thread ID
                       false,   // Timestamp
                       false);  // Tick count
}

void InitializeTracing() {
  base::FilePath path;
  bool result = ::PathService::Get(base::DIR_ANDROID_APP_DATA, &path);
  DCHECK(result);
  sky::shell::Shell::Shared()
      .tracing_controller()
      .set_traces_base_path(path);
}

}  // namespace

static void Init(JNIEnv* env,
                 jclass clazz,
                 jobject context,
                 jobjectArray jargs) {
  base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
  base::android::InitApplicationContext(env, scoped_context);

  std::vector<std::string> args;
  args.push_back("sky_shell");
  base::android::AppendJavaStringArrayToStringVector(env, jargs, &args);

  base::CommandLine::Init(0, nullptr);
  base::CommandLine::ForCurrentProcess()->InitFromArgv(args);

  InitializeLogging();

  g_java_message_loop.Get().reset(new base::MessageLoopForUI);
  base::MessageLoopForUI::current()->Start();

  mojo::embedder::Init(std::unique_ptr<mojo::embedder::PlatformSupport>(
      new mojo::embedder::SimplePlatformSupport()));

  CHECK(gfx::GLSurface::InitializeOneOff());
  Shell::InitStandalone();

  InitializeTracing();
}

bool RegisterSkyMain(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

}  // namespace sky
}  // namespace mojo
<commit_msg>Give the java ui thread a name in trace files<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/shell/platform/android/sky_main.h"

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/threading/simple_thread.h"
#include "jni/SkyMain_jni.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "sky/shell/shell.h"
#include "ui/gl/gl_surface.h"

using base::LazyInstance;

namespace sky {
namespace shell {

namespace {

LazyInstance<scoped_ptr<base::MessageLoop>> g_java_message_loop =
    LAZY_INSTANCE_INITIALIZER;

void InitializeLogging() {
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  logging::InitLogging(settings);
  // To view log output with IDs and timestamps use "adb logcat -v threadtime".
  logging::SetLogItems(false,   // Process ID
                       false,   // Thread ID
                       false,   // Timestamp
                       false);  // Tick count
}

void InitializeTracing() {
  base::FilePath path;
  bool result = ::PathService::Get(base::DIR_ANDROID_APP_DATA, &path);
  DCHECK(result);
  sky::shell::Shell::Shared()
      .tracing_controller()
      .set_traces_base_path(path);
}

}  // namespace

static void Init(JNIEnv* env,
                 jclass clazz,
                 jobject context,
                 jobjectArray jargs) {
  base::PlatformThread::SetName("java_ui_thread");
  base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
  base::android::InitApplicationContext(env, scoped_context);

  std::vector<std::string> args;
  args.push_back("sky_shell");
  base::android::AppendJavaStringArrayToStringVector(env, jargs, &args);

  base::CommandLine::Init(0, nullptr);
  base::CommandLine::ForCurrentProcess()->InitFromArgv(args);

  InitializeLogging();

  g_java_message_loop.Get().reset(new base::MessageLoopForUI);
  base::MessageLoopForUI::current()->Start();

  mojo::embedder::Init(std::unique_ptr<mojo::embedder::PlatformSupport>(
      new mojo::embedder::SimplePlatformSupport()));

  CHECK(gfx::GLSurface::InitializeOneOff());
  Shell::InitStandalone();

  InitializeTracing();
}

bool RegisterSkyMain(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

}  // namespace sky
}  // namespace mojo
<|endoftext|>


<commit_before><commit_msg>inverse for Mat3s<commit_after><|endoftext|>


<commit_before>#include <assert.h>
#include "lms7002_mainPanel.h"
#include "lms7002_pnlAFE_view.h"
#include "lms7002_pnlBIAS_view.h"
#include "lms7002_pnlBIST_view.h"
#include "lms7002_pnlCDS_view.h"
#include "lms7002_pnlCLKGEN_view.h"
#include "lms7002_pnlLDO_view.h"
#include "lms7002_pnlLimeLightPAD_view.h"
#include "lms7002_pnlTxTSP_view.h"
#include "lms7002_pnlRxTSP_view.h"
#include "lms7002_pnlRBB_view.h"
#include "lms7002_pnlRFE_view.h"
#include "lms7002_pnlSX_view.h"
#include "lms7002_pnlTBB_view.h"
#include "lms7002_pnlTRF_view.h"
#include "lms7002_pnlXBUF_view.h"
#include "lms7002_pnlCalibrations_view.h"
#include <wx/time.h>
#include <wx/msgdlg.h>
#include <iostream>
#include <wx/filedlg.h>
#include "lms7suiteEvents.h"
#include "lms7002_pnlMCU_BD_view.h"
#include "lms7002_pnlBuffers_view.h"
#include "lms7002_pnlR3.h"
#include "lime/LimeSuite.h"
using namespace std;
using namespace lime;

lms7002_mainPanel::lms7002_mainPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
    :
    mainPanel(parent, id, pos, size, style), lmsControl(nullptr)
{
    mTabMCU = new lms7002_pnlMCU_BD_view(tabsNotebook);
    tabsNotebook->AddPage(mTabMCU, _("MCU"));

    mTabR3 = new lms7002_pnlR3_view(tabsNotebook, wxNewId());
    tabsNotebook->AddPage(mTabR3, _("R3 Controls"));

    chkSyncAB->Hide();
}

lms7002_mainPanel::~lms7002_mainPanel()
{
}

void lms7002_mainPanel::UpdateVisiblePanel()
{
    wxLongLong t1, t2;
    t1 = wxGetUTCTimeMillis();
    long visibleTabId = tabsNotebook->GetCurrentPage()->GetId();
    switch (visibleTabId)
    {
    case ID_TAB_AFE:
        mTabAFE->UpdateGUI();
        break;
    case ID_TAB_BIAS:
        mTabBIAS->UpdateGUI();
        break;
    case ID_TAB_BIST:
        mTabBIST->UpdateGUI();
        break;
    case ID_TAB_CDS:
        mTabCDS->UpdateGUI();
        break;
    case ID_TAB_CGEN:
        mTabCGEN->UpdateGUI();
        break;
    case ID_TAB_LDO:
        mTabLDO->UpdateGUI();
        break;
    case ID_TAB_LIMELIGHT:
        mTabLimeLight->UpdateGUI();
        break;
    case ID_TAB_TXTSP:
        mTabTxTSP->UpdateGUI();
        break;
    case ID_TAB_RXTSP:
        mTabRxTSP->UpdateGUI();
        break;
    case ID_TAB_RBB:
        mTabRBB->UpdateGUI();
        break;
    case ID_TAB_RFE:
        mTabRFE->UpdateGUI();
        break;
    case ID_TAB_SXR:
        mTabSXR->UpdateGUI();
        break;
    case ID_TAB_SXT:
        mTabSXT->UpdateGUI();
        break;
    case ID_TAB_TBB:
        mTabTBB->UpdateGUI();
        break;
    case ID_TAB_TRF:
        mTabTRF->UpdateGUI();
        break;
    case ID_TAB_XBUF:
        mTabXBUF->UpdateGUI();
        break;
    case ID_TAB_CALIBRATIONS:
        mTabCalibrations->UpdateGUI();
        break;
    case ID_TAB_BUFFERS:
        mTabBuffers->UpdateGUI();
        break;
    }
    if(visibleTabId == mTabR3->GetId())
        mTabR3->UpdateGUI();
    t2 = wxGetUTCTimeMillis();
#ifndef NDEBUG
    cout << "Visible GUI update time: " << (t2 - t1).ToString() << endl;
#endif
}

void lms7002_mainPanel::Initialize(lms_device_t* pControl)
{
    assert(pControl != nullptr);
    lmsControl = pControl;
    mTabRFE->Initialize(lmsControl);
    mTabRBB->Initialize(lmsControl);
    mTabTRF->Initialize(lmsControl);
    mTabTBB->Initialize(lmsControl);
    mTabAFE->Initialize(lmsControl);
    mTabBIAS->Initialize(lmsControl);
    mTabLDO->Initialize(lmsControl);
    mTabXBUF->Initialize(lmsControl);
    mTabCGEN->Initialize(lmsControl);
    mTabSXR->Initialize(lmsControl);
    mTabSXT->Initialize(lmsControl);
    mTabLimeLight->Initialize(lmsControl);
    mTabTxTSP->Initialize(lmsControl);
    mTabRxTSP->Initialize(lmsControl);
    mTabCDS->Initialize(lmsControl);
    mTabBIST->Initialize(lmsControl);
    mTabCalibrations->Initialize(lmsControl);
    mTabMCU->Initialize(lmsControl);
    mTabBuffers->Initialize(lmsControl);
    mTabR3->Initialize(lmsControl);
    UpdateGUI();
}

void lms7002_mainPanel::OnResetChip(wxCommandEvent &event)
{
    int status = LMS_Reset(lmsControl);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Chip reset: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    wxNotebookEvent evt;
    Onnotebook_modulesPageChanged(evt); //after reset chip active channel might change, this refresh channel for active tab
}

void lms7002_mainPanel::UpdateGUI()
{
    wxLongLong t1, t2;
    t1 = wxGetUTCTimeMillis();
    t2 = wxGetUTCTimeMillis();
    uint16_t chan;
    LMS_ReadParam(lmsControl,LMS7param(MAC),&chan);
    if (chan == 1)
    {
        rbChannelA->SetValue(true);
        rbChannelB->SetValue(false);
    }
    else if (chan == 2)
    {
        rbChannelA->SetValue(false);
        rbChannelB->SetValue(true);
    }
    else
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),1);
        rbChannelA->SetValue(true);
        rbChannelB->SetValue(false);
    }

    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnNewProject( wxCommandEvent& event )
{
    LMS_Reset(lmsControl);
    LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
    LMS_WriteParam(lmsControl,LMS7param(MAC),1);
    UpdateGUI();
}

void lms7002_mainPanel::OnOpenProject( wxCommandEvent& event )
{
    wxFileDialog dlg(this, _("Open config file"), "", "", "Project-File (*.ini)|*.ini", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
    if (dlg.ShowModal() == wxID_CANCEL)
        return;
    int status = LMS_LoadConfig(lmsControl,dlg.GetPath().To8BitData());
    if (status != 0)
    {
            wxMessageBox(wxString::Format(_("Failed to load file: %s"), LMS_GetLastErrorMessage()), _("Warning"));
    }
    wxCommandEvent tevt;
    LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
    UpdateGUI();
    wxCommandEvent evt;
    evt.SetEventType(CGEN_FREQUENCY_CHANGED);
    wxPostEvent(this, evt);
}

void lms7002_mainPanel::OnSaveProject( wxCommandEvent& event )
{
    wxFileDialog dlg(this, _("Save config file"), "", "", "Project-File (*.ini)|*.ini", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    if (dlg.ShowModal() == wxID_CANCEL)
        return;
    int status = LMS_SaveConfig(lmsControl,dlg.GetPath().To8BitData());
    if (status != 0)
        wxMessageBox(_("Failed to save file"), _("Warning"));
}

void lms7002_mainPanel::OnRegistersTest( wxCommandEvent& event )
{
    int status = LMS_RegisterTest(lmsControl);
    if (status != 0)
        wxMessageBox(_("Registers test failed!"), _("WARNING"));
    else
        wxMessageBox(_("Registers test passed!"), _("INFO"));
}

void lms7002_mainPanel::OnSwitchToChannelA(wxCommandEvent& event)
{
    LMS_WriteParam(lmsControl,LMS7param(MAC),1);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnSwitchToChannelB(wxCommandEvent& event)
{
    LMS_WriteParam(lmsControl,LMS7param(MAC),2);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::Onnotebook_modulesPageChanged( wxNotebookEvent& event )
{
    wxNotebookPage* page = tabsNotebook->GetCurrentPage();
    if (page == mTabAFE || page == mTabBIAS || page == mTabLDO || page == mTabXBUF || page == mTabCGEN || page == mTabCDS || page == mTabBIST)
    {
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else if (page == mTabSXR) //change active channel to A
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),1);
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else if (page == mTabSXT) //change active channel to B
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),2);
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else
    {
        if(chkSyncAB->IsChecked())
            LMS_WriteParam(lmsControl,LMS7param(MAC), 3);
        else
        {
            LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
            rbChannelA->Enable();
            rbChannelB->Enable();
        }
    }

#ifdef __APPLE__
    //force show the page selected by the event (needed on apple)
    if (event.GetSelection() != -1)
    {
        dynamic_cast<wxNotebook*>(event.GetEventObject())->GetPage(event.GetSelection())->Show(true);
    }
#endif

    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnDownloadAll(wxCommandEvent& event)
{
    int status = LMS_Synchronize(lmsControl,false);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Download all registers: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnUploadAll(wxCommandEvent& event)
{
    int status = LMS_Synchronize(lmsControl,true);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Upload all registers: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    wxCommandEvent evt;
    evt.SetEventType(CGEN_FREQUENCY_CHANGED);
    wxPostEvent(this, evt);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnReadTemperature(wxCommandEvent& event)
{
    uint16_t readVal = 0;
    for(int i=0; i<0x3FF; ++i)
    {
        uint16_t wrValue = i;
        LMS_WriteLMSReg(lmsControl, 0x0640, wrValue);
        readVal = 0;
        LMS_ReadLMSReg(lmsControl, 0x0640, &readVal);
        readVal &= 0x03FF;
        wrValue >>= 1;
        if(readVal != wrValue )
        {
            printf("Mismatch wr/rd: 0x%04X, 0x%04X\n", i, readVal);
        }
    }

    return ;
    double t;
    LMS_GetChipTemperature(lmsControl,0,&t);
    txtTemperature->SetLabel(wxString::Format("Temperature: %.0f C", t));
}

void lms7002_mainPanel::OnSyncABchecked(wxCommandEvent& event)
{
    /*
    rbChannelA->Enable(!chkSyncAB->IsChecked());
    rbChannelB->Enable(!chkSyncAB->IsChecked());
    if(chkSyncAB->IsChecked())
    {
        int status = lmsControl->CopyChannelRegisters(LMS7002M::ChA, LMS7002M::ChB, false);
        if(status != 0)
            wxMessageBox(wxString::Format(_("Failed to copy A to B: %s"), wxString::From8BitData(GetLastErrorMessage())), _("Error"));
        wxNotebookPage* page = tabsNotebook->GetCurrentPage();
        if(page != mTabSXR && page != mTabSXT)
            lmsControl->SetActiveChannel(lime::LMS7002M::ChAB);
    }
    else
    {
        if(rbChannelA->GetValue() != 0)
            lmsControl->SetActiveChannel(lime::LMS7002M::ChA);
        else
            lmsControl->SetActiveChannel(lime::LMS7002M::ChB);
    }
    UpdateVisiblePanel();
    */
}

void lms7002_mainPanel::OnEnableMIMOchecked(wxCommandEvent& event)
{
    uint16_t chBck;
    LMS_ReadParam(lmsControl, LMS7param(MAC), &chBck);
    bool enable = chkEnableMIMO->IsChecked();
    LMS_WriteParam(lmsControl, LMS7param(MAC), 1);
    LMS_WriteParam(lmsControl, LMS7param(EN_NEXTRX_RFE), enable);
    LMS_WriteParam(lmsControl, LMS7param(EN_NEXTTX_TRF), enable);
    LMS_WriteParam(lmsControl, LMS7param(PD_RX_AFE1), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_RX_AFE2), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_TX_AFE1), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_TX_AFE2), 0);
    LMS_WriteParam(lmsControl, LMS7param(MIMO_SISO), 0);
    LMS_WriteParam(lmsControl, LMS7param(MAC), chBck);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnCalibrateInternalADC(wxCommandEvent& event)
{
    LMS_CalibrateInternalADC(lmsControl);
}
<commit_msg>Remove debugging leftover code<commit_after>#include <assert.h>
#include "lms7002_mainPanel.h"
#include "lms7002_pnlAFE_view.h"
#include "lms7002_pnlBIAS_view.h"
#include "lms7002_pnlBIST_view.h"
#include "lms7002_pnlCDS_view.h"
#include "lms7002_pnlCLKGEN_view.h"
#include "lms7002_pnlLDO_view.h"
#include "lms7002_pnlLimeLightPAD_view.h"
#include "lms7002_pnlTxTSP_view.h"
#include "lms7002_pnlRxTSP_view.h"
#include "lms7002_pnlRBB_view.h"
#include "lms7002_pnlRFE_view.h"
#include "lms7002_pnlSX_view.h"
#include "lms7002_pnlTBB_view.h"
#include "lms7002_pnlTRF_view.h"
#include "lms7002_pnlXBUF_view.h"
#include "lms7002_pnlCalibrations_view.h"
#include <wx/time.h>
#include <wx/msgdlg.h>
#include <iostream>
#include <wx/filedlg.h>
#include "lms7suiteEvents.h"
#include "lms7002_pnlMCU_BD_view.h"
#include "lms7002_pnlBuffers_view.h"
#include "lms7002_pnlR3.h"
#include "lime/LimeSuite.h"
using namespace std;
using namespace lime;

lms7002_mainPanel::lms7002_mainPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
    :
    mainPanel(parent, id, pos, size, style), lmsControl(nullptr)
{
    mTabMCU = new lms7002_pnlMCU_BD_view(tabsNotebook);
    tabsNotebook->AddPage(mTabMCU, _("MCU"));

    mTabR3 = new lms7002_pnlR3_view(tabsNotebook, wxNewId());
    tabsNotebook->AddPage(mTabR3, _("R3 Controls"));

    chkSyncAB->Hide();
}

lms7002_mainPanel::~lms7002_mainPanel()
{
}

void lms7002_mainPanel::UpdateVisiblePanel()
{
    wxLongLong t1, t2;
    t1 = wxGetUTCTimeMillis();
    long visibleTabId = tabsNotebook->GetCurrentPage()->GetId();
    switch (visibleTabId)
    {
    case ID_TAB_AFE:
        mTabAFE->UpdateGUI();
        break;
    case ID_TAB_BIAS:
        mTabBIAS->UpdateGUI();
        break;
    case ID_TAB_BIST:
        mTabBIST->UpdateGUI();
        break;
    case ID_TAB_CDS:
        mTabCDS->UpdateGUI();
        break;
    case ID_TAB_CGEN:
        mTabCGEN->UpdateGUI();
        break;
    case ID_TAB_LDO:
        mTabLDO->UpdateGUI();
        break;
    case ID_TAB_LIMELIGHT:
        mTabLimeLight->UpdateGUI();
        break;
    case ID_TAB_TXTSP:
        mTabTxTSP->UpdateGUI();
        break;
    case ID_TAB_RXTSP:
        mTabRxTSP->UpdateGUI();
        break;
    case ID_TAB_RBB:
        mTabRBB->UpdateGUI();
        break;
    case ID_TAB_RFE:
        mTabRFE->UpdateGUI();
        break;
    case ID_TAB_SXR:
        mTabSXR->UpdateGUI();
        break;
    case ID_TAB_SXT:
        mTabSXT->UpdateGUI();
        break;
    case ID_TAB_TBB:
        mTabTBB->UpdateGUI();
        break;
    case ID_TAB_TRF:
        mTabTRF->UpdateGUI();
        break;
    case ID_TAB_XBUF:
        mTabXBUF->UpdateGUI();
        break;
    case ID_TAB_CALIBRATIONS:
        mTabCalibrations->UpdateGUI();
        break;
    case ID_TAB_BUFFERS:
        mTabBuffers->UpdateGUI();
        break;
    }
    if(visibleTabId == mTabR3->GetId())
        mTabR3->UpdateGUI();
    t2 = wxGetUTCTimeMillis();
#ifndef NDEBUG
    cout << "Visible GUI update time: " << (t2 - t1).ToString() << endl;
#endif
}

void lms7002_mainPanel::Initialize(lms_device_t* pControl)
{
    assert(pControl != nullptr);
    lmsControl = pControl;
    mTabRFE->Initialize(lmsControl);
    mTabRBB->Initialize(lmsControl);
    mTabTRF->Initialize(lmsControl);
    mTabTBB->Initialize(lmsControl);
    mTabAFE->Initialize(lmsControl);
    mTabBIAS->Initialize(lmsControl);
    mTabLDO->Initialize(lmsControl);
    mTabXBUF->Initialize(lmsControl);
    mTabCGEN->Initialize(lmsControl);
    mTabSXR->Initialize(lmsControl);
    mTabSXT->Initialize(lmsControl);
    mTabLimeLight->Initialize(lmsControl);
    mTabTxTSP->Initialize(lmsControl);
    mTabRxTSP->Initialize(lmsControl);
    mTabCDS->Initialize(lmsControl);
    mTabBIST->Initialize(lmsControl);
    mTabCalibrations->Initialize(lmsControl);
    mTabMCU->Initialize(lmsControl);
    mTabBuffers->Initialize(lmsControl);
    mTabR3->Initialize(lmsControl);
    UpdateGUI();
}

void lms7002_mainPanel::OnResetChip(wxCommandEvent &event)
{
    int status = LMS_Reset(lmsControl);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Chip reset: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    wxNotebookEvent evt;
    Onnotebook_modulesPageChanged(evt); //after reset chip active channel might change, this refresh channel for active tab
}

void lms7002_mainPanel::UpdateGUI()
{
    wxLongLong t1, t2;
    t1 = wxGetUTCTimeMillis();
    t2 = wxGetUTCTimeMillis();
    uint16_t chan;
    LMS_ReadParam(lmsControl,LMS7param(MAC),&chan);
    if (chan == 1)
    {
        rbChannelA->SetValue(true);
        rbChannelB->SetValue(false);
    }
    else if (chan == 2)
    {
        rbChannelA->SetValue(false);
        rbChannelB->SetValue(true);
    }
    else
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),1);
        rbChannelA->SetValue(true);
        rbChannelB->SetValue(false);
    }

    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnNewProject( wxCommandEvent& event )
{
    LMS_Reset(lmsControl);
    LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
    LMS_WriteParam(lmsControl,LMS7param(MAC),1);
    UpdateGUI();
}

void lms7002_mainPanel::OnOpenProject( wxCommandEvent& event )
{
    wxFileDialog dlg(this, _("Open config file"), "", "", "Project-File (*.ini)|*.ini", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
    if (dlg.ShowModal() == wxID_CANCEL)
        return;
    int status = LMS_LoadConfig(lmsControl,dlg.GetPath().To8BitData());
    if (status != 0)
    {
            wxMessageBox(wxString::Format(_("Failed to load file: %s"), LMS_GetLastErrorMessage()), _("Warning"));
    }
    wxCommandEvent tevt;
    LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
    UpdateGUI();
    wxCommandEvent evt;
    evt.SetEventType(CGEN_FREQUENCY_CHANGED);
    wxPostEvent(this, evt);
}

void lms7002_mainPanel::OnSaveProject( wxCommandEvent& event )
{
    wxFileDialog dlg(this, _("Save config file"), "", "", "Project-File (*.ini)|*.ini", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    if (dlg.ShowModal() == wxID_CANCEL)
        return;
    int status = LMS_SaveConfig(lmsControl,dlg.GetPath().To8BitData());
    if (status != 0)
        wxMessageBox(_("Failed to save file"), _("Warning"));
}

void lms7002_mainPanel::OnRegistersTest( wxCommandEvent& event )
{
    int status = LMS_RegisterTest(lmsControl);
    if (status != 0)
        wxMessageBox(_("Registers test failed!"), _("WARNING"));
    else
        wxMessageBox(_("Registers test passed!"), _("INFO"));
}

void lms7002_mainPanel::OnSwitchToChannelA(wxCommandEvent& event)
{
    LMS_WriteParam(lmsControl,LMS7param(MAC),1);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnSwitchToChannelB(wxCommandEvent& event)
{
    LMS_WriteParam(lmsControl,LMS7param(MAC),2);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::Onnotebook_modulesPageChanged( wxNotebookEvent& event )
{
    wxNotebookPage* page = tabsNotebook->GetCurrentPage();
    if (page == mTabAFE || page == mTabBIAS || page == mTabLDO || page == mTabXBUF || page == mTabCGEN || page == mTabCDS || page == mTabBIST)
    {
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else if (page == mTabSXR) //change active channel to A
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),1);
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else if (page == mTabSXT) //change active channel to B
    {
        LMS_WriteParam(lmsControl,LMS7param(MAC),2);
        rbChannelA->Disable();
        rbChannelB->Disable();
    }
    else
    {
        if(chkSyncAB->IsChecked())
            LMS_WriteParam(lmsControl,LMS7param(MAC), 3);
        else
        {
            LMS_WriteParam(lmsControl,LMS7param(MAC),rbChannelA->GetValue() == 1 ? 1: 2);
            rbChannelA->Enable();
            rbChannelB->Enable();
        }
    }

#ifdef __APPLE__
    //force show the page selected by the event (needed on apple)
    if (event.GetSelection() != -1)
    {
        dynamic_cast<wxNotebook*>(event.GetEventObject())->GetPage(event.GetSelection())->Show(true);
    }
#endif

    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnDownloadAll(wxCommandEvent& event)
{
    int status = LMS_Synchronize(lmsControl,false);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Download all registers: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnUploadAll(wxCommandEvent& event)
{
    int status = LMS_Synchronize(lmsControl,true);
    if (status != 0)
        wxMessageBox(wxString::Format(_("Upload all registers: %s"), wxString::From8BitData(LMS_GetLastErrorMessage())), _("Warning"));
    wxCommandEvent evt;
    evt.SetEventType(CGEN_FREQUENCY_CHANGED);
    wxPostEvent(this, evt);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnReadTemperature(wxCommandEvent& event)
{
    double t;
    LMS_GetChipTemperature(lmsControl,0,&t);
    txtTemperature->SetLabel(wxString::Format("Temperature: %.0f C", t));
}

void lms7002_mainPanel::OnSyncABchecked(wxCommandEvent& event)
{
    /*
    rbChannelA->Enable(!chkSyncAB->IsChecked());
    rbChannelB->Enable(!chkSyncAB->IsChecked());
    if(chkSyncAB->IsChecked())
    {
        int status = lmsControl->CopyChannelRegisters(LMS7002M::ChA, LMS7002M::ChB, false);
        if(status != 0)
            wxMessageBox(wxString::Format(_("Failed to copy A to B: %s"), wxString::From8BitData(GetLastErrorMessage())), _("Error"));
        wxNotebookPage* page = tabsNotebook->GetCurrentPage();
        if(page != mTabSXR && page != mTabSXT)
            lmsControl->SetActiveChannel(lime::LMS7002M::ChAB);
    }
    else
    {
        if(rbChannelA->GetValue() != 0)
            lmsControl->SetActiveChannel(lime::LMS7002M::ChA);
        else
            lmsControl->SetActiveChannel(lime::LMS7002M::ChB);
    }
    UpdateVisiblePanel();
    */
}

void lms7002_mainPanel::OnEnableMIMOchecked(wxCommandEvent& event)
{
    uint16_t chBck;
    LMS_ReadParam(lmsControl, LMS7param(MAC), &chBck);
    bool enable = chkEnableMIMO->IsChecked();
    LMS_WriteParam(lmsControl, LMS7param(MAC), 1);
    LMS_WriteParam(lmsControl, LMS7param(EN_NEXTRX_RFE), enable);
    LMS_WriteParam(lmsControl, LMS7param(EN_NEXTTX_TRF), enable);
    LMS_WriteParam(lmsControl, LMS7param(PD_RX_AFE1), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_RX_AFE2), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_TX_AFE1), 0);
    LMS_WriteParam(lmsControl, LMS7param(PD_TX_AFE2), 0);
    LMS_WriteParam(lmsControl, LMS7param(MIMO_SISO), 0);
    LMS_WriteParam(lmsControl, LMS7param(MAC), chBck);
    UpdateVisiblePanel();
}

void lms7002_mainPanel::OnCalibrateInternalADC(wxCommandEvent& event)
{
    LMS_CalibrateInternalADC(lmsControl);
}
<|endoftext|>