<commit_before>/***************************************
** Tsunagari Tile Engine              **
** character.cpp                      **
** Copyright 2011-2014 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// **********

#include "core/character.h"

#include "core/area.h"
#include "core/client-conf.h"
#include "core/sounds.h"
#include "core/tile.h"

Character::Character() noexcept
        : nowalkFlags(TILE_NOWALK | TILE_NOWALK_NPC),
          nowalkExempt(0),
          fromCoord({0.0, 0.0, 0.0}),
          destExit(nullptr) {
    enterTile();
}

void
Character::tick(time_t dt) noexcept {
    Entity::tick(dt);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Characters don't do anything on tick() for TURN mode.
        break;
    case Conf::TILE:
        moveTowardDestination(dt);
        break;
    case Conf::NOTILE:
        assert_(false && "not implemented");
        break;
    }
}

void
Character::turn() noexcept {}

void
Character::destroy() noexcept {
    leaveTile();
    Entity::destroy();
}

icoord
Character::getTileCoords_i() const noexcept {
    return area->grid.virt2phys(r);
}

vicoord
Character::getTileCoords_vi() const noexcept {
    return area->grid.virt2virt(r);
}

void
Character::setTileCoords(int x, int y) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, r.z});
    enterTile();
}

void
Character::setTileCoords(icoord phys) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.phys2virt_r(phys);
    enterTile();
}

void
Character::setTileCoords(vicoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(virt);
    enterTile();
}

void
Character::setTileCoords(rcoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = virt;
    enterTile();
}

void
Character::setArea(Area* area, vicoord position) noexcept {
    leaveTile();
    Entity::setArea(area);
    r = area->grid.virt2virt(position);
    enterTile();
    redraw = true;
}

void
Character::moveByTile(ivec2 delta) noexcept {
    if (moving) {
        return;
    }

    setFacing(delta);

    icoord dest = moveDest(facing);

    icoord from = getTileCoords_i();
    setDestinationCoordinate(area->grid.phys2virt_r(dest));

    destExit = nullptr;
    if (area->grid.inBounds(from)) {
        destExit = area->grid.exitAt(from, delta);
    }
    else if (area->grid.inBounds(dest)) {
        destExit = area->grid.exits[EXIT_NORMAL].tryAt(from);
    }

    if (!canMove(dest)) {
        setAnimationStanding();
        return;
    }

    setAnimationMoving();
    moving = true;

    // Process triggers.
    runTileExitScript();

    if (area->grid.inBounds(from)) {
        area->runScript(TileGrid::SCRIPT_TYPE_LEAVE, from, this);
    }

    // Modify tile's entity count.
    leaveTile(from);
    enterTile(dest);

    Sounds::play(soundPaths[StringView("step")]);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Movement is instantaneous.
        redraw = true;
        r = destCoord;
        moving = false;
        setAnimationStanding();
        arrived();
        break;
    case Conf::TILE:
    case Conf::NOTILE:
        // Movement happens in Entity::moveTowardDestination() during
        // tick().
        break;
    }
}

icoord
Character::moveDest(ivec2 facing) noexcept {
    icoord here = getTileCoords_i();

    if (area->grid.inBounds(here)) {
        // Handle layermod.
        return area->grid.moveDest(here, facing);
    }
    else {
        return here + icoord{facing.x, facing.y, 0};
    }
}

bool
Character::canMove(icoord dest) noexcept {
    if (destExit && *destExit) {
        // We can always take exits as long as we can take exits.
        // (Even if they would cause us to be out of bounds.)
        if (nowalkExempt & TILE_NOWALK_EXIT) {
            return true;
        }
    }

    bool inBounds = area->grid.inBounds(dest);
    if (inBounds) {
        // Tile is inside map. Can we move?
        if (nowalked(dest)) {
            return false;
        }
        if (area->grid.occupied.contains(dest)) {
            // Space is occupied by another Entity.
            return false;
        }

        return true;
    }

    // The tile is legitimately off the map.
    return (nowalkExempt & TILE_NOWALK_AREA_BOUND) != 0;
}

bool
Character::nowalked(icoord phys) noexcept {
    unsigned flags = nowalkFlags & ~nowalkExempt;
    Optional<unsigned*> tileFlags = area->grid.flags.tryAt(phys);
    return tileFlags && (**tileFlags & flags) != 0;
}

void
Character::arrived() noexcept {
    Entity::arrived();

    icoord dest = area->grid.virt2phys(destCoord);
    bool inBounds = area->grid.inBounds(dest);

    if (inBounds) {
        Optional<float*> layermod =
            area->grid.layermods[EXIT_NORMAL].tryAt(dest);
        if (layermod) {
            r.z = **layermod;
        }

        // Process triggers.
        area->runScript(TileGrid::SCRIPT_TYPE_ENTER, dest, this);
    }

    runTileEntryScript();

    // TODO: move teleportation here
    /*
     * if (onExit()) {
     *      leaveTile();
     *      moveArea(getExit());
     *      Entity::arrived();
     *      enterTile();
     * }
     */
}

void
Character::leaveTile() noexcept {
    if (area) {
        leaveTile(getTileCoords_i());
    }
}

void
Character::leaveTile(icoord phys) noexcept {
    area->grid.occupied.erase(phys);
}

void
Character::enterTile() noexcept {
    if (area) {
        enterTile(getTileCoords_i());
    }
}

void
Character::enterTile(icoord phys) noexcept {
    area->grid.occupied.insert(phys);
}

void
Character::runTileExitScript() noexcept {
    // if (!tileExitScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileExitScript->invoke();
}

void
Character::runTileEntryScript() noexcept {
    // if (!tileEntryScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileEntryScript->invoke();
}
<commit_msg>core/character: Fix Exits of type EXIT_NORMAL<commit_after>/***************************************
** Tsunagari Tile Engine              **
** character.cpp                      **
** Copyright 2011-2014 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// **********

#include "core/character.h"

#include "core/area.h"
#include "core/client-conf.h"
#include "core/sounds.h"
#include "core/tile.h"

Character::Character() noexcept
        : nowalkFlags(TILE_NOWALK | TILE_NOWALK_NPC),
          nowalkExempt(0),
          fromCoord({0.0, 0.0, 0.0}),
          destExit(nullptr) {
    enterTile();
}

void
Character::tick(time_t dt) noexcept {
    Entity::tick(dt);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Characters don't do anything on tick() for TURN mode.
        break;
    case Conf::TILE:
        moveTowardDestination(dt);
        break;
    case Conf::NOTILE:
        assert_(false && "not implemented");
        break;
    }
}

void
Character::turn() noexcept {}

void
Character::destroy() noexcept {
    leaveTile();
    Entity::destroy();
}

icoord
Character::getTileCoords_i() const noexcept {
    return area->grid.virt2phys(r);
}

vicoord
Character::getTileCoords_vi() const noexcept {
    return area->grid.virt2virt(r);
}

void
Character::setTileCoords(int x, int y) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, r.z});
    enterTile();
}

void
Character::setTileCoords(icoord phys) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.phys2virt_r(phys);
    enterTile();
}

void
Character::setTileCoords(vicoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(virt);
    enterTile();
}

void
Character::setTileCoords(rcoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = virt;
    enterTile();
}

void
Character::setArea(Area* area, vicoord position) noexcept {
    leaveTile();
    Entity::setArea(area);
    r = area->grid.virt2virt(position);
    enterTile();
    redraw = true;
}

void
Character::moveByTile(ivec2 delta) noexcept {
    if (moving) {
        return;
    }

    setFacing(delta);

    icoord dest = moveDest(facing);

    icoord from = getTileCoords_i();
    setDestinationCoordinate(area->grid.phys2virt_r(dest));

    destExit = none;
    if (area->grid.inBounds(from)) {
        destExit = area->grid.exitAt(from, delta);
    }
    if (!destExit && area->grid.inBounds(dest)) {
        destExit = area->grid.exits[EXIT_NORMAL].tryAt(dest);
    }

    if (!canMove(dest)) {
        setAnimationStanding();
        return;
    }

    setAnimationMoving();
    moving = true;

    // Process triggers.
    runTileExitScript();

    if (area->grid.inBounds(from)) {
        area->runScript(TileGrid::SCRIPT_TYPE_LEAVE, from, this);
    }

    // Modify tile's entity count.
    leaveTile(from);
    enterTile(dest);

    Sounds::play(soundPaths[StringView("step")]);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Movement is instantaneous.
        redraw = true;
        r = destCoord;
        moving = false;
        setAnimationStanding();
        arrived();
        break;
    case Conf::TILE:
    case Conf::NOTILE:
        // Movement happens in Entity::moveTowardDestination() during
        // tick().
        break;
    }
}

icoord
Character::moveDest(ivec2 facing) noexcept {
    icoord here = getTileCoords_i();

    if (area->grid.inBounds(here)) {
        // Handle layermod.
        return area->grid.moveDest(here, facing);
    }
    else {
        return here + icoord{facing.x, facing.y, 0};
    }
}

bool
Character::canMove(icoord dest) noexcept {
    if (destExit && *destExit) {
        // We can always take exits as long as we can take exits.
        // (Even if they would cause us to be out of bounds.)
        if (nowalkExempt & TILE_NOWALK_EXIT) {
            return true;
        }
    }

    bool inBounds = area->grid.inBounds(dest);
    if (inBounds) {
        // Tile is inside map. Can we move?
        if (nowalked(dest)) {
            return false;
        }
        if (area->grid.occupied.contains(dest)) {
            // Space is occupied by another Entity.
            return false;
        }

        return true;
    }

    // The tile is legitimately off the map.
    return (nowalkExempt & TILE_NOWALK_AREA_BOUND) != 0;
}

bool
Character::nowalked(icoord phys) noexcept {
    unsigned flags = nowalkFlags & ~nowalkExempt;
    Optional<unsigned*> tileFlags = area->grid.flags.tryAt(phys);
    return tileFlags && (**tileFlags & flags) != 0;
}

void
Character::arrived() noexcept {
    Entity::arrived();

    icoord dest = area->grid.virt2phys(destCoord);
    bool inBounds = area->grid.inBounds(dest);

    if (inBounds) {
        Optional<float*> layermod =
            area->grid.layermods[EXIT_NORMAL].tryAt(dest);
        if (layermod) {
            r.z = **layermod;
        }

        // Process triggers.
        area->runScript(TileGrid::SCRIPT_TYPE_ENTER, dest, this);
    }

    runTileEntryScript();

    // TODO: move teleportation here
    /*
     * if (onExit()) {
     *      leaveTile();
     *      moveArea(getExit());
     *      Entity::arrived();
     *      enterTile();
     * }
     */
}

void
Character::leaveTile() noexcept {
    if (area) {
        leaveTile(getTileCoords_i());
    }
}

void
Character::leaveTile(icoord phys) noexcept {
    area->grid.occupied.erase(phys);
}

void
Character::enterTile() noexcept {
    if (area) {
        enterTile(getTileCoords_i());
    }
}

void
Character::enterTile(icoord phys) noexcept {
    area->grid.occupied.insert(phys);
}

void
Character::runTileExitScript() noexcept {
    // if (!tileExitScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileExitScript->invoke();
}

void
Character::runTileEntryScript() noexcept {
    // if (!tileEntryScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileEntryScript->invoke();
}
<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2013, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "coverage_notice.hh"
#include "history.hh"
#include <algorithm>

static std::vector<std::string*> dummy;

std::string _stmp("1");

Coverage_notice::Coverage_notice(Log&l,std::string _cc1,std::string _cc2):
  Coverage_report(l,dummy,dummy,dummy),cc1(_cc1),cc2(_cc2),const1(l,_stmp)
{

}

Coverage_notice::~Coverage_notice()
{

}

void Coverage_notice::foo()
{
  Coverage* c1;
  Coverage* c2;
  if (cc2=="") {
    c2=&const1;
  } else {
    c2=new_coverage(log,cc2);
    if (c2==NULL) {
      status=false;
      errormsg="Can't create coverage \""+cc2+"\"";
      return;
    }
    c2->set_model(model);
  }
  c1=new_coverage(log,cc1);

  if (c1==NULL) {
    status=false;
    errormsg="Can't create coverage \""+cc1+"\"";
    return;
  }
  c1->on_report=true;
  c1->set_model(model);

  if (!c1->status) {
    status=false;
    errormsg="Submodel failure \""+cc1+"\":"+c1->errormsg;
    return;
  }

  if (!c2->status) {
    status=false;
    errormsg="Submodel failure \""+cc2+"\":"+c2->errormsg;
  }

  std::vector<std::pair<int,std::vector<int> > > m;

  subcovs.push_front(std::pair<std::pair<Coverage*,Coverage*>,
				  std::pair<std::pair<struct timeval,struct timeval>,
					    std::vector<std::pair<int,std::vector<int> > > > >
  (std::pair<Coverage*,Coverage*>(c1,c2),
   std::pair<std::pair<struct timeval,struct timeval>,std::vector<std::pair<int,std::vector<int> > > >
   ( std::pair<struct timeval,struct timeval>(History::current_time,History::current_time),m)));

}

bool Coverage_notice::execute(int action)
{
  if (action<=0) {
    return true;
  }
  struct execute_class {
    void operator() (std::pair<std::pair<Coverage*,Coverage*>,
			       std::pair<
				 std::pair<timeval,timeval>,
				 std::vector<std::pair<int,std::vector<int> > > > > &
		     cpair) {
      float f=cpair.first .first ->getCoverage();

      cpair.first .first ->execute(action);
      cpair.first .second->execute(action);

      float f1=cpair.first .first ->getCoverage();
      float f2=cpair.first .second->getCoverage();

      if (f==0.0 && f1>0) {
	// Start of the trace
	cpair.second.first.first=History::current_time;
	// We need to create an other instance...
	r->foo();
      }

      if (f1>0) {
	std::vector<int> t;
	cpair.second.second.push_back(std::pair<int,std::vector<int> >(action,t));
	if (f1>=f2) {
	  r->log.debug("coverage passed... %04f %04f\n",f1,f2);

	  cpair.second.first.second=History::current_time;
	  // trace found!

	  r->traces.push_back(cpair.second.second);
	  r->tcount[cpair.second.second]++;

	  r->times.push_back(cpair.second.first);

	  // Ok. We can delete the coverage objects.
	  delete cpair.first .first;
	  if (cpair.first .second != & r->const1) {
	    delete cpair.first.second;
	  }
	  cpair.first.first =NULL;
	  cpair.first.second=NULL;
	  // Now we need to erase iterator.
	}
      } else {
	// ??
      }
    }
    int action;
    Model* model;
    Coverage_notice* r;
  } callobject;

  callobject.action=action;
  callobject.model =model;
  callobject.r     =this;

  int ff=0;

  std::list<std::pair<std::pair<Coverage*,Coverage*>,
		      std::pair<
			std::pair<struct timeval,struct timeval>,
			std::vector<std::pair<int,std::vector<int> > > > > >
    ::iterator i1;

  //for_each(subcovs.begin(),subcovs.end(),callobject);
  //for_each doesn't work for some reason and I'm too lazy to figure out why. Most likely it's my fault.

  for(i1=subcovs.begin();i1!=subcovs.end();i1++) {
    ff++;
    callobject(*i1);
  }

  // Delete handled elements...
  for(i1=subcovs.begin();i1!=subcovs.end();) {
    if (i1->first.first) {
      i1++;
    } else {
      i1=subcovs.erase(i1);
    }
  }
  return true;
}
<commit_msg>valgrind<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2013, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "coverage_notice.hh"
#include "history.hh"
#include <algorithm>

static std::vector<std::string*> dummy;

std::string _stmp("1");

Coverage_notice::Coverage_notice(Log&l,std::string _cc1,std::string _cc2):
  Coverage_report(l,dummy,dummy,dummy),cc1(_cc1),cc2(_cc2),const1(l,_stmp)
{

}

Coverage_notice::~Coverage_notice()
{
  std::list<std::pair<std::pair<Coverage*,Coverage*>,
		      std::pair<
			std::pair<struct timeval,struct timeval>,
			std::vector<std::pair<int,std::vector<int> > > > > >::iterator i;
  for(i=subcovs.begin();i!=subcovs.end();i++) {
    delete i->first.first;
    if (i->first.second != &const1) {
      delete i->first.second;
    }
  }
}

void Coverage_notice::foo()
{
  Coverage* c1;
  Coverage* c2;
  if (cc2=="") {
    c2=&const1;
  } else {
    c2=new_coverage(log,cc2);
    if (c2==NULL) {
      status=false;
      errormsg="Can't create coverage \""+cc2+"\"";
      return;
    }
    c2->set_model(model);
  }
  c1=new_coverage(log,cc1);

  if (c1==NULL) {
    status=false;
    errormsg="Can't create coverage \""+cc1+"\"";
    return;
  }
  c1->on_report=true;
  c1->set_model(model);

  if (!c1->status) {
    status=false;
    errormsg="Submodel failure \""+cc1+"\":"+c1->errormsg;
    return;
  }

  if (!c2->status) {
    status=false;
    errormsg="Submodel failure \""+cc2+"\":"+c2->errormsg;
  }

  std::vector<std::pair<int,std::vector<int> > > m;

  subcovs.push_front(std::pair<std::pair<Coverage*,Coverage*>,
				  std::pair<std::pair<struct timeval,struct timeval>,
					    std::vector<std::pair<int,std::vector<int> > > > >
  (std::pair<Coverage*,Coverage*>(c1,c2),
   std::pair<std::pair<struct timeval,struct timeval>,std::vector<std::pair<int,std::vector<int> > > >
   ( std::pair<struct timeval,struct timeval>(History::current_time,History::current_time),m)));

}

bool Coverage_notice::execute(int action)
{
  if (action<=0) {
    return true;
  }
  struct execute_class {
    void operator() (std::pair<std::pair<Coverage*,Coverage*>,
			       std::pair<
				 std::pair<timeval,timeval>,
				 std::vector<std::pair<int,std::vector<int> > > > > &
		     cpair) {
      float f=cpair.first .first ->getCoverage();

      cpair.first .first ->execute(action);
      cpair.first .second->execute(action);

      float f1=cpair.first .first ->getCoverage();
      float f2=cpair.first .second->getCoverage();

      if (f==0.0 && f1>0) {
	// Start of the trace
	cpair.second.first.first=History::current_time;
	// We need to create an other instance...
	r->foo();
      }

      if (f1>0) {
	std::vector<int> t;
	cpair.second.second.push_back(std::pair<int,std::vector<int> >(action,t));
	if (f1>=f2) {
	  r->log.debug("coverage passed... %04f %04f\n",f1,f2);

	  cpair.second.first.second=History::current_time;
	  // trace found!

	  r->traces.push_back(cpair.second.second);
	  r->tcount[cpair.second.second]++;

	  r->times.push_back(cpair.second.first);

	  // Ok. We can delete the coverage objects.
	  delete cpair.first .first;
	  if (cpair.first .second != & r->const1) {
	    delete cpair.first.second;
	  }
	  cpair.first.first =NULL;
	  cpair.first.second=NULL;
	  // Now we need to erase iterator.
	}
      } else {
	// ??
      }
    }
    int action;
    Model* model;
    Coverage_notice* r;
  } callobject;

  callobject.action=action;
  callobject.model =model;
  callobject.r     =this;

  int ff=0;

  std::list<std::pair<std::pair<Coverage*,Coverage*>,
		      std::pair<
			std::pair<struct timeval,struct timeval>,
			std::vector<std::pair<int,std::vector<int> > > > > >
    ::iterator i1;

  //for_each(subcovs.begin(),subcovs.end(),callobject);
  //for_each doesn't work for some reason and I'm too lazy to figure out why. Most likely it's my fault.

  for(i1=subcovs.begin();i1!=subcovs.end();i1++) {
    ff++;
    callobject(*i1);
  }

  // Delete handled elements...
  for(i1=subcovs.begin();i1!=subcovs.end();) {
    if (i1->first.first) {
      i1++;
    } else {
      i1=subcovs.erase(i1);
    }
  }
  return true;
}
<|endoftext|>


<commit_before>/*
  Firmata.cpp - Firmata library
  Copyright (c) 2007 Free Software Foundation.  All right reserved.
  Written by Hans-Christoph Steiner <hans@at.or.at>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

//******************************************************************************
//* Includes
//******************************************************************************

extern "C" {
  // AVR LibC Includes
  #include <inttypes.h>
  #include <stdlib.h>

  // Wiring Core Includes
  #include "WConstants.h"
}

#include "Firmata.h"
#include "EEPROM.h"
#include "HardwareSerial.h"

//******************************************************************************
//* Definitions
//******************************************************************************

//******************************************************************************
//* Constructors
//******************************************************************************

FirmataClass::FirmataClass()
{
	// TODO: init serial here
	// TODO: printVersion
}

//******************************************************************************
//* Private Methods
//******************************************************************************
// resets the system state upon a SYSTEM_RESET message from the host software
void FirmataClass::systemReset(void)
{
	// TODO automatically call this in response to SYSTEM_RESET
	// TODO reset EEPROM to 0 here
}

//******************************************************************************
//* Public Methods
//******************************************************************************

// output type of message that is next on the queue
int FirmataClass::available(void)
{
	// TODO output next available message type, or -1 if nothing
}

// output the protocol version message to the serial port
void FirmataClass::printVersion() {
  Serial.print(REPORT_VERSION, BYTE);
  Serial.print(FIRMATA_MINOR_VERSION, BYTE);
  Serial.print(FIRMATA_MAJOR_VERSION, BYTE);
}

// send an analog message
void FirmataClass::sendAnalog(int pin, int value)
{
	// pin can only be 0-15, so chop higher bits
	Serial.print(ANALOG_MESSAGE | (pin & 0xF), BYTE);
	Serial.print(value % 128, BYTE);
	Serial.print(value >> 7, BYTE);
}

// send a single digital pin in a digital message
void FirmataClass::sendDigital(int pin, int value)
{
	// TODO add single pin digital messages to the  protocol
}

// send 14-bits in a single digital message
void FirmataClass::sendDigitalPortPair(int port, int value)
{
	// TODO: the digital message should not be sent on the serial port every
	// time sendDigital() is called.  Instead, it should add it to an int
	// which will be sent on a schedule.  If a pin changes more than once
	// before the digital message is sent on the serial port, it should send a
	// digital message for each change.

	// TODO: some math needs to happen for pin > 14 since MIDI channels are used
	Serial.print(DIGITAL_MESSAGE | (port & 0xF),BYTE);
	Serial.print(value % 128, BYTE); // Tx pins 0-6
	Serial.print(value >> 7, BYTE);  // Tx pins 7-13
}

// Internal Actions/////////////////////////////////////////////////////////////

void FirmataClass::loadState(void)
{
	// TODO load state from EEPROM
}

void FirmataClass::saveState(void)
{
	// TODO save state to EEPROM
}

void FirmataClass::resetState(void)
{
	// TODO reset state bytes in EEPROM
}

// make one instance for the user to use
FirmataClass Firmata;
<commit_msg>Fixing some warnings.<commit_after>/*
  Firmata.cpp - Firmata library
  Copyright (c) 2007 Free Software Foundation.  All right reserved.
  Written by Hans-Christoph Steiner <hans@at.or.at>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

//******************************************************************************
//* Includes
//******************************************************************************

extern "C" {
  // AVR LibC Includes
  #include <inttypes.h>
  #include <stdlib.h>

  // use the abs in WConstants.h, not the one in stdlib.h
  #undef abs

  // Wiring Core Includes
  #include "WConstants.h"
}

#include "Firmata.h"
#include "EEPROM.h"
#include "HardwareSerial.h"

//******************************************************************************
//* Definitions
//******************************************************************************

//******************************************************************************
//* Constructors
//******************************************************************************

FirmataClass::FirmataClass()
{
	// TODO: init serial here
	// TODO: printVersion
}

//******************************************************************************
//* Private Methods
//******************************************************************************
// resets the system state upon a SYSTEM_RESET message from the host software
void FirmataClass::systemReset(void)
{
	// TODO automatically call this in response to SYSTEM_RESET
	// TODO reset EEPROM to 0 here
}

//******************************************************************************
//* Public Methods
//******************************************************************************

// output type of message that is next on the queue
int FirmataClass::available(void)
{
	return -1;
	// TODO output next available message type, or -1 if nothing
}

// output the protocol version message to the serial port
void FirmataClass::printVersion() {
  Serial.print(REPORT_VERSION, BYTE);
  Serial.print(FIRMATA_MINOR_VERSION, BYTE);
  Serial.print(FIRMATA_MAJOR_VERSION, BYTE);
}

// send an analog message
void FirmataClass::sendAnalog(int pin, int value)
{
	// pin can only be 0-15, so chop higher bits
	Serial.print(ANALOG_MESSAGE | (pin & 0xF), BYTE);
	Serial.print(value % 128, BYTE);
	Serial.print(value >> 7, BYTE);
}

// send a single digital pin in a digital message
void FirmataClass::sendDigital(int pin, int value)
{
	// TODO add single pin digital messages to the  protocol
}

// send 14-bits in a single digital message
void FirmataClass::sendDigitalPortPair(int port, int value)
{
	// TODO: the digital message should not be sent on the serial port every
	// time sendDigital() is called.  Instead, it should add it to an int
	// which will be sent on a schedule.  If a pin changes more than once
	// before the digital message is sent on the serial port, it should send a
	// digital message for each change.

	// TODO: some math needs to happen for pin > 14 since MIDI channels are used
	Serial.print(DIGITAL_MESSAGE | (port & 0xF),BYTE);
	Serial.print(value % 128, BYTE); // Tx pins 0-6
	Serial.print(value >> 7, BYTE);  // Tx pins 7-13
}

// Internal Actions/////////////////////////////////////////////////////////////

void FirmataClass::loadState(void)
{
	// TODO load state from EEPROM
}

void FirmataClass::saveState(void)
{
	// TODO save state to EEPROM
}

void FirmataClass::resetState(void)
{
	// TODO reset state bytes in EEPROM
}

// make one instance for the user to use
FirmataClass Firmata;
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "skia/ext/bitmap_platform_device_win.h"

#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkUtils.h"

namespace skia {

namespace {

// Constrains position and size to fit within available_size. If |size| is -1,
// all the available_size is used. Returns false if the position is out of
// available_size.
bool Constrain(int available_size, int* position, int *size) {
  if (*size < -2)
    return false;

  if (*position < 0) {
    if (*size != -1)
      *size += *position;
    *position = 0;
  }
  if (*size == 0 || *position >= available_size)
    return false;

  if (*size > 0) {
    int overflow = (*position + *size) - available_size;
    if (overflow > 0) {
      *size -= overflow;
    }
  } else {
    // Fill up available size.
    *size = available_size - *position;
  }
  return true;
}

}  // namespace

class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData : public SkRefCnt {
 public:
  explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap);

  // Create/destroy hdc_, which is the memory DC for our bitmap data.
  HDC GetBitmapDC();
  void ReleaseBitmapDC();
  bool IsBitmapDCCreated() const;

  // Sets the transform and clip operations. This will not update the DC,
  // but will mark the config as dirty. The next call of LoadConfig will
  // pick up these changes.
  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);

  const SkMatrix& transform() const {
    return transform_;
  }

 protected:
  // Loads the current transform and clip into the DC. Can be called even when
  // the DC is NULL (will be a NOP).
  void LoadConfig();

  // Windows bitmap corresponding to our surface.
  HBITMAP hbitmap_;

  // Lazily-created DC used to draw into the bitmap, see getBitmapDC.
  HDC hdc_;

  // True when there is a transform or clip that has not been set to the DC.
  // The DC is retrieved for every text operation, and the transform and clip
  // do not change as much. We can save time by not loading the clip and
  // transform for every one.
  bool config_dirty_;

  // Translation assigned to the DC: we need to keep track of this separately
  // so it can be updated even if the DC isn't created yet.
  SkMatrix transform_;

  // The current clipping
  SkRegion clip_region_;

 private:
  virtual ~BitmapPlatformDeviceWinData();

  // Copy & assign are not supported.
  BitmapPlatformDeviceWinData(const BitmapPlatformDeviceWinData&);
  BitmapPlatformDeviceWinData& operator=(const BitmapPlatformDeviceWinData&);
};

BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::BitmapPlatformDeviceWinData(
    HBITMAP hbitmap)
    : hbitmap_(hbitmap),
      hdc_(NULL),
      config_dirty_(true) {  // Want to load the config next time.
  // Initialize the clip region to the entire bitmap.
  BITMAP bitmap_data;
  if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) {
    SkIRect rect;
    rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
    clip_region_ = SkRegion(rect);
  }

  transform_.reset();
}

BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::~BitmapPlatformDeviceWinData() {
  if (hdc_)
    ReleaseBitmapDC();

  // this will free the bitmap data as well as the bitmap handle
  DeleteObject(hbitmap_);
}

HDC BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::GetBitmapDC() {
  if (!hdc_) {
    hdc_ = CreateCompatibleDC(NULL);
    InitializeDC(hdc_);
    HGDIOBJ old_bitmap = SelectObject(hdc_, hbitmap_);
    // When the memory DC is created, its display surface is exactly one
    // monochrome pixel wide and one monochrome pixel high. Since we select our
    // own bitmap, we must delete the previous one.
    DeleteObject(old_bitmap);
  }

  LoadConfig();
  return hdc_;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::ReleaseBitmapDC() {
  SkASSERT(hdc_);
  DeleteDC(hdc_);
  hdc_ = NULL;
}

bool BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::IsBitmapDCCreated()
    const {
  return hdc_ != NULL;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::SetMatrixClip(
    const SkMatrix& transform,
    const SkRegion& region) {
  transform_ = transform;
  clip_region_ = region;
  config_dirty_ = true;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::LoadConfig() {
  if (!config_dirty_ || !hdc_)
    return;  // Nothing to do.
  config_dirty_ = false;

  // Transform.
  SkMatrix t(transform_);
  LoadTransformToDC(hdc_, t);
  LoadClippingRegionToDC(hdc_, clip_region_, t);
}

// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDeviceWin* BitmapPlatformDeviceWin::create(
    HDC screen_dc,
    int width,
    int height,
    bool is_opaque,
    HANDLE shared_section) {
  SkBitmap bitmap;

  // CreateDIBSection appears to get unhappy if we create an empty bitmap, so
  // just create a minimal bitmap
  if ((width == 0) || (height == 0)) {
    width = 1;
    height = 1;
  }

  BITMAPINFOHEADER hdr = {0};
  hdr.biSize = sizeof(BITMAPINFOHEADER);
  hdr.biWidth = width;
  hdr.biHeight = -height;  // minus means top-down bitmap
  hdr.biPlanes = 1;
  hdr.biBitCount = 32;
  hdr.biCompression = BI_RGB;  // no compression
  hdr.biSizeImage = 0;
  hdr.biXPelsPerMeter = 1;
  hdr.biYPelsPerMeter = 1;
  hdr.biClrUsed = 0;
  hdr.biClrImportant = 0;

  void* data = NULL;
  HBITMAP hbitmap = CreateDIBSection(screen_dc,
                                     reinterpret_cast<BITMAPINFO*>(&hdr), 0,
                                     &data,
                                     shared_section, 0);

  // If we run out of GDI objects or some other error occurs, we won't get a
  // bitmap here. This will cause us to crash later because the data pointer is
  // NULL. To make sure that we can assign blame for those crashes to this code,
  // we deliberately crash here, even in release mode.
  if (!hbitmap) {
    DWORD error = GetLastError();
    return NULL;
  }

  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  bitmap.setPixels(data);
  bitmap.setIsOpaque(is_opaque);

  if (is_opaque) {
#ifndef NDEBUG
    // To aid in finding bugs, we set the background color to something
    // obviously wrong so it will be noticable when it is not cleared
    bitmap.eraseARGB(255, 0, 255, 128);  // bright bluish green
#endif
  } else {
    bitmap.eraseARGB(0, 0, 0, 0);
  }

  // The device object will take ownership of the HBITMAP. The initial refcount
  // of the data object will be 1, which is what the constructor expects.
  return new BitmapPlatformDeviceWin(new BitmapPlatformDeviceWinData(hbitmap),
                                     bitmap);
}

// The device will own the HBITMAP, which corresponds to also owning the pixel
// data. Therefore, we do not transfer ownership to the SkDevice's bitmap.
BitmapPlatformDeviceWin::BitmapPlatformDeviceWin(
    BitmapPlatformDeviceWinData* data,
    const SkBitmap& bitmap)
    : PlatformDeviceWin(bitmap),
      data_(data) {
  // The data object is already ref'ed for us by create().
}

// The copy constructor just adds another reference to the underlying data.
// We use a const cast since the default Skia definitions don't define the
// proper constedness that we expect (accessBitmap should really be const).
BitmapPlatformDeviceWin::BitmapPlatformDeviceWin(
    const BitmapPlatformDeviceWin& other)
    : PlatformDeviceWin(
          const_cast<BitmapPlatformDeviceWin&>(other).accessBitmap(true)),
      data_(other.data_) {
  data_->ref();
}

BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin() {
  data_->unref();
}

BitmapPlatformDeviceWin& BitmapPlatformDeviceWin::operator=(
    const BitmapPlatformDeviceWin& other) {
  data_ = other.data_;
  data_->ref();
  return *this;
}

HDC BitmapPlatformDeviceWin::getBitmapDC() {
  return data_->GetBitmapDC();
}

void BitmapPlatformDeviceWin::setMatrixClip(const SkMatrix& transform,
                                            const SkRegion& region) {
  data_->SetMatrixClip(transform, region);
}

void BitmapPlatformDeviceWin::drawToHDC(HDC dc, int x, int y,
                                        const RECT* src_rect) {
  bool created_dc = !data_->IsBitmapDCCreated();
  HDC source_dc = getBitmapDC();

  RECT temp_rect;
  if (!src_rect) {
    temp_rect.left = 0;
    temp_rect.right = width();
    temp_rect.top = 0;
    temp_rect.bottom = height();
    src_rect = &temp_rect;
  }

  int copy_width = src_rect->right - src_rect->left;
  int copy_height = src_rect->bottom - src_rect->top;

  // We need to reset the translation for our bitmap or (0,0) won't be in the
  // upper left anymore
  SkMatrix identity;
  identity.reset();

  LoadTransformToDC(source_dc, identity);
  if (isOpaque()) {
    BitBlt(dc,
           x,
           y,
           copy_width,
           copy_height,
           source_dc,
           src_rect->left,
           src_rect->top,
           SRCCOPY);
  } else {
    SkASSERT(copy_width != 0 && copy_height != 0);
    BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
    GdiAlphaBlend(dc,
                  x,
                  y,
                  copy_width,
                  copy_height,
                  source_dc,
                  src_rect->left,
                  src_rect->top,
                  copy_width,
                  copy_height,
                  blend_function);
  }
  LoadTransformToDC(source_dc, data_->transform());

  if (created_dc)
    data_->ReleaseBitmapDC();
}

void BitmapPlatformDeviceWin::makeOpaque(int x, int y, int width, int height) {
  const SkBitmap& bitmap = accessBitmap(true);
  SkASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);

  // FIXME(brettw): This is kind of lame, we shouldn't be dealing with
  // transforms at this level. Probably there should be a PlatformCanvas
  // function that does the transform (using the actual transform not just the
  // translation) and calls us with the transformed rect.
  const SkMatrix& matrix = data_->transform();
  int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x;
  int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y;

  if (Constrain(bitmap.width(), &bitmap_start_x, &width) &&
      Constrain(bitmap.height(), &bitmap_start_y, &height)) {
    SkAutoLockPixels lock(bitmap);
    SkASSERT(bitmap.rowBytes() % sizeof(uint32_t) == 0u);
    size_t row_words = bitmap.rowBytes() / sizeof(uint32_t);
    // Set data to the first pixel to be modified.
    uint32_t* data = bitmap.getAddr32(0, 0) + (bitmap_start_y * row_words) +
                     bitmap_start_x;
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++)
        data[j] |= (0xFF << SK_A32_SHIFT);
      data += row_words;
    }
  }
}

// Returns the color value at the specified location.
SkColor BitmapPlatformDeviceWin::getColorAt(int x, int y) {
  const SkBitmap& bitmap = accessBitmap(false);
  SkAutoLockPixels lock(bitmap);
  uint32_t* data = bitmap.getAddr32(0, 0);
  return static_cast<SkColor>(data[x + y * width()]);
}

void BitmapPlatformDeviceWin::onAccessBitmap(SkBitmap* bitmap) {
  // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
  // operation has occurred on our DC.
  if (data_->IsBitmapDCCreated())
    GdiFlush();
}

}  // namespace skia

<commit_msg>Remove misleading comment - we no longer crash when CreateDIBSection() fails, just return null<commit_after>// Copyright (c) 2006-2008 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 "skia/ext/bitmap_platform_device_win.h"

#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkUtils.h"

namespace skia {

namespace {

// Constrains position and size to fit within available_size. If |size| is -1,
// all the available_size is used. Returns false if the position is out of
// available_size.
bool Constrain(int available_size, int* position, int *size) {
  if (*size < -2)
    return false;

  if (*position < 0) {
    if (*size != -1)
      *size += *position;
    *position = 0;
  }
  if (*size == 0 || *position >= available_size)
    return false;

  if (*size > 0) {
    int overflow = (*position + *size) - available_size;
    if (overflow > 0) {
      *size -= overflow;
    }
  } else {
    // Fill up available size.
    *size = available_size - *position;
  }
  return true;
}

}  // namespace

class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData : public SkRefCnt {
 public:
  explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap);

  // Create/destroy hdc_, which is the memory DC for our bitmap data.
  HDC GetBitmapDC();
  void ReleaseBitmapDC();
  bool IsBitmapDCCreated() const;

  // Sets the transform and clip operations. This will not update the DC,
  // but will mark the config as dirty. The next call of LoadConfig will
  // pick up these changes.
  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);

  const SkMatrix& transform() const {
    return transform_;
  }

 protected:
  // Loads the current transform and clip into the DC. Can be called even when
  // the DC is NULL (will be a NOP).
  void LoadConfig();

  // Windows bitmap corresponding to our surface.
  HBITMAP hbitmap_;

  // Lazily-created DC used to draw into the bitmap, see getBitmapDC.
  HDC hdc_;

  // True when there is a transform or clip that has not been set to the DC.
  // The DC is retrieved for every text operation, and the transform and clip
  // do not change as much. We can save time by not loading the clip and
  // transform for every one.
  bool config_dirty_;

  // Translation assigned to the DC: we need to keep track of this separately
  // so it can be updated even if the DC isn't created yet.
  SkMatrix transform_;

  // The current clipping
  SkRegion clip_region_;

 private:
  virtual ~BitmapPlatformDeviceWinData();

  // Copy & assign are not supported.
  BitmapPlatformDeviceWinData(const BitmapPlatformDeviceWinData&);
  BitmapPlatformDeviceWinData& operator=(const BitmapPlatformDeviceWinData&);
};

BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::BitmapPlatformDeviceWinData(
    HBITMAP hbitmap)
    : hbitmap_(hbitmap),
      hdc_(NULL),
      config_dirty_(true) {  // Want to load the config next time.
  // Initialize the clip region to the entire bitmap.
  BITMAP bitmap_data;
  if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) {
    SkIRect rect;
    rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
    clip_region_ = SkRegion(rect);
  }

  transform_.reset();
}

BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::~BitmapPlatformDeviceWinData() {
  if (hdc_)
    ReleaseBitmapDC();

  // this will free the bitmap data as well as the bitmap handle
  DeleteObject(hbitmap_);
}

HDC BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::GetBitmapDC() {
  if (!hdc_) {
    hdc_ = CreateCompatibleDC(NULL);
    InitializeDC(hdc_);
    HGDIOBJ old_bitmap = SelectObject(hdc_, hbitmap_);
    // When the memory DC is created, its display surface is exactly one
    // monochrome pixel wide and one monochrome pixel high. Since we select our
    // own bitmap, we must delete the previous one.
    DeleteObject(old_bitmap);
  }

  LoadConfig();
  return hdc_;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::ReleaseBitmapDC() {
  SkASSERT(hdc_);
  DeleteDC(hdc_);
  hdc_ = NULL;
}

bool BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::IsBitmapDCCreated()
    const {
  return hdc_ != NULL;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::SetMatrixClip(
    const SkMatrix& transform,
    const SkRegion& region) {
  transform_ = transform;
  clip_region_ = region;
  config_dirty_ = true;
}

void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::LoadConfig() {
  if (!config_dirty_ || !hdc_)
    return;  // Nothing to do.
  config_dirty_ = false;

  // Transform.
  SkMatrix t(transform_);
  LoadTransformToDC(hdc_, t);
  LoadClippingRegionToDC(hdc_, clip_region_, t);
}

// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDeviceWin* BitmapPlatformDeviceWin::create(
    HDC screen_dc,
    int width,
    int height,
    bool is_opaque,
    HANDLE shared_section) {
  SkBitmap bitmap;

  // CreateDIBSection appears to get unhappy if we create an empty bitmap, so
  // just create a minimal bitmap
  if ((width == 0) || (height == 0)) {
    width = 1;
    height = 1;
  }

  BITMAPINFOHEADER hdr = {0};
  hdr.biSize = sizeof(BITMAPINFOHEADER);
  hdr.biWidth = width;
  hdr.biHeight = -height;  // minus means top-down bitmap
  hdr.biPlanes = 1;
  hdr.biBitCount = 32;
  hdr.biCompression = BI_RGB;  // no compression
  hdr.biSizeImage = 0;
  hdr.biXPelsPerMeter = 1;
  hdr.biYPelsPerMeter = 1;
  hdr.biClrUsed = 0;
  hdr.biClrImportant = 0;

  void* data = NULL;
  HBITMAP hbitmap = CreateDIBSection(screen_dc,
                                     reinterpret_cast<BITMAPINFO*>(&hdr), 0,
                                     &data,
                                     shared_section, 0);
  if (!hbitmap) {
    return NULL;
  }

  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  bitmap.setPixels(data);
  bitmap.setIsOpaque(is_opaque);

  if (is_opaque) {
#ifndef NDEBUG
    // To aid in finding bugs, we set the background color to something
    // obviously wrong so it will be noticable when it is not cleared
    bitmap.eraseARGB(255, 0, 255, 128);  // bright bluish green
#endif
  } else {
    bitmap.eraseARGB(0, 0, 0, 0);
  }

  // The device object will take ownership of the HBITMAP. The initial refcount
  // of the data object will be 1, which is what the constructor expects.
  return new BitmapPlatformDeviceWin(new BitmapPlatformDeviceWinData(hbitmap),
                                     bitmap);
}

// The device will own the HBITMAP, which corresponds to also owning the pixel
// data. Therefore, we do not transfer ownership to the SkDevice's bitmap.
BitmapPlatformDeviceWin::BitmapPlatformDeviceWin(
    BitmapPlatformDeviceWinData* data,
    const SkBitmap& bitmap)
    : PlatformDeviceWin(bitmap),
      data_(data) {
  // The data object is already ref'ed for us by create().
}

// The copy constructor just adds another reference to the underlying data.
// We use a const cast since the default Skia definitions don't define the
// proper constedness that we expect (accessBitmap should really be const).
BitmapPlatformDeviceWin::BitmapPlatformDeviceWin(
    const BitmapPlatformDeviceWin& other)
    : PlatformDeviceWin(
          const_cast<BitmapPlatformDeviceWin&>(other).accessBitmap(true)),
      data_(other.data_) {
  data_->ref();
}

BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin() {
  data_->unref();
}

BitmapPlatformDeviceWin& BitmapPlatformDeviceWin::operator=(
    const BitmapPlatformDeviceWin& other) {
  data_ = other.data_;
  data_->ref();
  return *this;
}

HDC BitmapPlatformDeviceWin::getBitmapDC() {
  return data_->GetBitmapDC();
}

void BitmapPlatformDeviceWin::setMatrixClip(const SkMatrix& transform,
                                            const SkRegion& region) {
  data_->SetMatrixClip(transform, region);
}

void BitmapPlatformDeviceWin::drawToHDC(HDC dc, int x, int y,
                                        const RECT* src_rect) {
  bool created_dc = !data_->IsBitmapDCCreated();
  HDC source_dc = getBitmapDC();

  RECT temp_rect;
  if (!src_rect) {
    temp_rect.left = 0;
    temp_rect.right = width();
    temp_rect.top = 0;
    temp_rect.bottom = height();
    src_rect = &temp_rect;
  }

  int copy_width = src_rect->right - src_rect->left;
  int copy_height = src_rect->bottom - src_rect->top;

  // We need to reset the translation for our bitmap or (0,0) won't be in the
  // upper left anymore
  SkMatrix identity;
  identity.reset();

  LoadTransformToDC(source_dc, identity);
  if (isOpaque()) {
    BitBlt(dc,
           x,
           y,
           copy_width,
           copy_height,
           source_dc,
           src_rect->left,
           src_rect->top,
           SRCCOPY);
  } else {
    SkASSERT(copy_width != 0 && copy_height != 0);
    BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
    GdiAlphaBlend(dc,
                  x,
                  y,
                  copy_width,
                  copy_height,
                  source_dc,
                  src_rect->left,
                  src_rect->top,
                  copy_width,
                  copy_height,
                  blend_function);
  }
  LoadTransformToDC(source_dc, data_->transform());

  if (created_dc)
    data_->ReleaseBitmapDC();
}

void BitmapPlatformDeviceWin::makeOpaque(int x, int y, int width, int height) {
  const SkBitmap& bitmap = accessBitmap(true);
  SkASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);

  // FIXME(brettw): This is kind of lame, we shouldn't be dealing with
  // transforms at this level. Probably there should be a PlatformCanvas
  // function that does the transform (using the actual transform not just the
  // translation) and calls us with the transformed rect.
  const SkMatrix& matrix = data_->transform();
  int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x;
  int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y;

  if (Constrain(bitmap.width(), &bitmap_start_x, &width) &&
      Constrain(bitmap.height(), &bitmap_start_y, &height)) {
    SkAutoLockPixels lock(bitmap);
    SkASSERT(bitmap.rowBytes() % sizeof(uint32_t) == 0u);
    size_t row_words = bitmap.rowBytes() / sizeof(uint32_t);
    // Set data to the first pixel to be modified.
    uint32_t* data = bitmap.getAddr32(0, 0) + (bitmap_start_y * row_words) +
                     bitmap_start_x;
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++)
        data[j] |= (0xFF << SK_A32_SHIFT);
      data += row_words;
    }
  }
}

// Returns the color value at the specified location.
SkColor BitmapPlatformDeviceWin::getColorAt(int x, int y) {
  const SkBitmap& bitmap = accessBitmap(false);
  SkAutoLockPixels lock(bitmap);
  uint32_t* data = bitmap.getAddr32(0, 0);
  return static_cast<SkColor>(data[x + y * width()]);
}

void BitmapPlatformDeviceWin::onAccessBitmap(SkBitmap* bitmap) {
  // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
  // operation has occurred on our DC.
  if (data_->IsBitmapDCCreated())
    GdiFlush();
}

}  // namespace skia

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef AST_ARRAY_VALUE_H
#define AST_ARRAY_VALUE_H

#include <memory>
#include <string>

#include "ast/Deferred.hpp"
#include "ast/Position.hpp"

namespace eddic {

class Context;
class Variable;

namespace ast {

/*!
 * \class ASTArrayValue
 * \brief The AST node for a value of an array.
 * Should only be used from the Deferred version (eddic::ast::ArrayValue).
 */
struct ASTArrayValue {
    Position position;
    Value ref;
    Value indexValue;

    mutable long references = 0;
};

/*!
 * \typedef ArrayValue
 * \brief The AST node for a value of an array.
 */
typedef Deferred<ASTArrayValue> ArrayValue;

} //end of ast

} //end of eddic

//Adapt the struct for the AST
BOOST_FUSION_ADAPT_STRUCT(
    eddic::ast::ArrayValue,
    (eddic::ast::Position, Content->position)
    (eddic::ast::Value, Content->ref)
    (eddic::ast::Value, Content->indexValue)
)

#endif
<commit_msg>Remove the old ArrayValue<commit_after><|endoftext|>


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

#ifndef __CPU_O3_DYN_INST_HH__
#define __CPU_O3_DYN_INST_HH__

#include "arch/isa_traits.hh"
#include "config/the_isa.hh"
#include "cpu/o3/cpu.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"

class Packet;

/**
 * Mostly implementation & ISA specific AlphaDynInst. As with most
 * other classes in the new CPU model, it is templated on the Impl to
 * allow for passing in of all types, such as the CPU type and the ISA
 * type. The AlphaDynInst serves as the primary interface to the CPU
 * for instructions that are executing.
 */
template <class Impl>
class BaseO3DynInst : public BaseDynInst<Impl>
{
  public:
    /** Typedef for the CPU. */
    typedef typename Impl::O3CPU O3CPU;

    /** Binary machine instruction type. */
    typedef TheISA::MachInst MachInst;
    /** Extended machine instruction type. */
    typedef TheISA::ExtMachInst ExtMachInst;
    /** Logical register index type. */
    typedef TheISA::RegIndex RegIndex;
    /** Integer register index type. */
    typedef TheISA::IntReg   IntReg;
    typedef TheISA::FloatReg FloatReg;
    typedef TheISA::FloatRegBits FloatRegBits;
    /** Misc register index type. */
    typedef TheISA::MiscReg  MiscReg;

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

  public:
    /** BaseDynInst constructor given a binary instruction. */
    BaseO3DynInst(StaticInstPtr staticInst, StaticInstPtr macroop,
                  TheISA::PCState pc, TheISA::PCState predPC,
                  InstSeqNum seq_num, O3CPU *cpu);

    /** BaseDynInst constructor given a static inst pointer. */
    BaseO3DynInst(StaticInstPtr _staticInst, StaticInstPtr _macroop);

    ~BaseO3DynInst();

    /** Executes the instruction.*/
    Fault execute();

    /** Initiates the access.  Only valid for memory operations. */
    Fault initiateAcc();

    /** Completes the access.  Only valid for memory operations. */
    Fault completeAcc(PacketPtr pkt);

  private:
    /** Initializes variables. */
    void initVars();

  protected:
    /** Values to be written to the destination misc. registers. */
    MiscReg _destMiscRegVal[TheISA::MaxMiscDestRegs];

    /** Indexes of the destination misc. registers. They are needed to defer
     * the write accesses to the misc. registers until the commit stage, when
     * the instruction is out of its speculative state.
     */
    short _destMiscRegIdx[TheISA::MaxMiscDestRegs];

    /** Number of destination misc. registers. */
    uint8_t _numDestMiscRegs;

  public:
#if TRACING_ON
    /** Tick records used for the pipeline activity viewer. */
    Tick fetchTick;	     // instruction fetch is completed.
    int32_t decodeTick;  // instruction enters decode phase
    int32_t renameTick;  // instruction enters rename phase
    int32_t dispatchTick;
    int32_t issueTick;
    int32_t completeTick;
    int32_t commitTick;
    int32_t storeTick;
#endif

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

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscReg(int misc_reg, const MiscReg &val)
    {
        /** Writes to misc. registers are recorded and deferred until the
         * commit stage, when updateMiscRegs() is called.
         */
        assert(_numDestMiscRegs < TheISA::MaxMiscDestRegs);
        _destMiscRegIdx[_numDestMiscRegs] = misc_reg;
        _destMiscRegVal[_numDestMiscRegs] = val;
        _numDestMiscRegs++;
    }

    /** Reads a misc. register, including any side-effects the read
     * might have as defined by the architecture.
     */
    TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readMiscReg(
                si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
                this->threadNumber);
    }

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscRegOperand(const StaticInst *si, int idx,
                                     const MiscReg &val)
    {
        int misc_reg = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
        setMiscReg(misc_reg, val);
    }

    /** Called at the commit stage to update the misc. registers. */
    void updateMiscRegs()
    {
        // @todo: Pretty convoluted way to avoid squashing from happening when
        // using the TC during an instruction's execution (specifically for
        // instructions that have side-effects that use the TC).  Fix this.
        // See cpu/o3/dyn_inst_impl.hh.
        bool no_squash_from_TC = this->thread->noSquashFromTC;
        this->thread->noSquashFromTC = true;

        for (int i = 0; i < _numDestMiscRegs; i++)
            this->cpu->setMiscReg(
                _destMiscRegIdx[i], _destMiscRegVal[i], this->threadNumber);

        this->thread->noSquashFromTC = no_squash_from_TC;
    }

    void forwardOldRegs()
    {

        for (int idx = 0; idx < this->numDestRegs(); idx++) {
            PhysRegIndex prev_phys_reg = this->prevDestRegIdx(idx);
            TheISA::RegIndex original_dest_reg = this->staticInst->destRegIdx(idx);
            if (original_dest_reg <  TheISA::FP_Base_DepTag)
                this->setIntRegOperand(this->staticInst.get(), idx, this->cpu->readIntReg(prev_phys_reg));
            else if (original_dest_reg < TheISA::Ctrl_Base_DepTag)
                this->setFloatRegOperandBits(this->staticInst.get(), idx, this->cpu->readFloatRegBits(prev_phys_reg));
        }
    }
    /** Calls hardware return from error interrupt. */
    Fault hwrei();
    /** Traps to handle specified fault. */
    void trap(Fault fault);
    bool simPalCheck(int palFunc);

    /** Emulates a syscall. */
    void syscall(int64_t callnum);

  public:

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readIntReg(this->_srcRegIdx[idx]);
    }

    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
    }

    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
    }

    /** @todo: Make results into arrays so they can handle multiple dest
     *  registers.
     */
    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
    {
        this->cpu->setIntReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
    }

    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
    {
        this->cpu->setFloatReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
    }

    void setFloatRegOperandBits(const StaticInst *si, int idx,
                                FloatRegBits val)
    {
        this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
    }

#if THE_ISA == MIPS_ISA
    uint64_t readRegOtherThread(int misc_reg)
    {
        panic("MIPS MT not defined for O3 CPU.\n");
        return 0;
    }

    void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val)
    {
        panic("MIPS MT not defined for O3 CPU.\n");
    }
#endif

  public:
    /** Calculates EA part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault calcEA()
    {
        return this->staticInst->eaCompInst()->execute(this, this->traceData);
    }

    /** Does the memory access part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault memAccess()
    {
        return this->staticInst->memAccInst()->execute(this, this->traceData);
    }
};

#endif // __CPU_O3_ALPHA_DYN_INST_HH__

<commit_msg>cpu: Avoid duplicate entries in tracking structures for writes to misc regs<commit_after>/*
 * Copyright (c) 2010 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) 2004-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Kevin Lim
 */

#ifndef __CPU_O3_DYN_INST_HH__
#define __CPU_O3_DYN_INST_HH__

#include "arch/isa_traits.hh"
#include "config/the_isa.hh"
#include "cpu/o3/cpu.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"

class Packet;

/**
 * Mostly implementation & ISA specific AlphaDynInst. As with most
 * other classes in the new CPU model, it is templated on the Impl to
 * allow for passing in of all types, such as the CPU type and the ISA
 * type. The AlphaDynInst serves as the primary interface to the CPU
 * for instructions that are executing.
 */
template <class Impl>
class BaseO3DynInst : public BaseDynInst<Impl>
{
  public:
    /** Typedef for the CPU. */
    typedef typename Impl::O3CPU O3CPU;

    /** Binary machine instruction type. */
    typedef TheISA::MachInst MachInst;
    /** Extended machine instruction type. */
    typedef TheISA::ExtMachInst ExtMachInst;
    /** Logical register index type. */
    typedef TheISA::RegIndex RegIndex;
    /** Integer register index type. */
    typedef TheISA::IntReg   IntReg;
    typedef TheISA::FloatReg FloatReg;
    typedef TheISA::FloatRegBits FloatRegBits;
    /** Misc register index type. */
    typedef TheISA::MiscReg  MiscReg;

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

  public:
    /** BaseDynInst constructor given a binary instruction. */
    BaseO3DynInst(StaticInstPtr staticInst, StaticInstPtr macroop,
                  TheISA::PCState pc, TheISA::PCState predPC,
                  InstSeqNum seq_num, O3CPU *cpu);

    /** BaseDynInst constructor given a static inst pointer. */
    BaseO3DynInst(StaticInstPtr _staticInst, StaticInstPtr _macroop);

    ~BaseO3DynInst();

    /** Executes the instruction.*/
    Fault execute();

    /** Initiates the access.  Only valid for memory operations. */
    Fault initiateAcc();

    /** Completes the access.  Only valid for memory operations. */
    Fault completeAcc(PacketPtr pkt);

  private:
    /** Initializes variables. */
    void initVars();

  protected:
    /** Values to be written to the destination misc. registers. */
    MiscReg _destMiscRegVal[TheISA::MaxMiscDestRegs];

    /** Indexes of the destination misc. registers. They are needed to defer
     * the write accesses to the misc. registers until the commit stage, when
     * the instruction is out of its speculative state.
     */
    short _destMiscRegIdx[TheISA::MaxMiscDestRegs];

    /** Number of destination misc. registers. */
    uint8_t _numDestMiscRegs;

  public:
#if TRACING_ON
    /** Tick records used for the pipeline activity viewer. */
    Tick fetchTick;	     // instruction fetch is completed.
    int32_t decodeTick;  // instruction enters decode phase
    int32_t renameTick;  // instruction enters rename phase
    int32_t dispatchTick;
    int32_t issueTick;
    int32_t completeTick;
    int32_t commitTick;
    int32_t storeTick;
#endif

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

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscReg(int misc_reg, const MiscReg &val)
    {
        /** Writes to misc. registers are recorded and deferred until the
         * commit stage, when updateMiscRegs() is called. First, check if
         * the misc reg has been written before and update its value to be
         * committed instead of making a new entry. If not, make a new
         * entry and record the write.
         */
        for (int idx = 0; idx < _numDestMiscRegs; idx++) {
            if (_destMiscRegIdx[idx] == misc_reg) {
               _destMiscRegVal[idx] = val;
               return;
            }
        }

        assert(_numDestMiscRegs < TheISA::MaxMiscDestRegs);
        _destMiscRegIdx[_numDestMiscRegs] = misc_reg;
        _destMiscRegVal[_numDestMiscRegs] = val;
        _numDestMiscRegs++;
    }

    /** Reads a misc. register, including any side-effects the read
     * might have as defined by the architecture.
     */
    TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readMiscReg(
                si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
                this->threadNumber);
    }

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscRegOperand(const StaticInst *si, int idx,
                                     const MiscReg &val)
    {
        int misc_reg = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
        setMiscReg(misc_reg, val);
    }

    /** Called at the commit stage to update the misc. registers. */
    void updateMiscRegs()
    {
        // @todo: Pretty convoluted way to avoid squashing from happening when
        // using the TC during an instruction's execution (specifically for
        // instructions that have side-effects that use the TC).  Fix this.
        // See cpu/o3/dyn_inst_impl.hh.
        bool no_squash_from_TC = this->thread->noSquashFromTC;
        this->thread->noSquashFromTC = true;

        for (int i = 0; i < _numDestMiscRegs; i++)
            this->cpu->setMiscReg(
                _destMiscRegIdx[i], _destMiscRegVal[i], this->threadNumber);

        this->thread->noSquashFromTC = no_squash_from_TC;
    }

    void forwardOldRegs()
    {

        for (int idx = 0; idx < this->numDestRegs(); idx++) {
            PhysRegIndex prev_phys_reg = this->prevDestRegIdx(idx);
            TheISA::RegIndex original_dest_reg = this->staticInst->destRegIdx(idx);
            if (original_dest_reg <  TheISA::FP_Base_DepTag)
                this->setIntRegOperand(this->staticInst.get(), idx, this->cpu->readIntReg(prev_phys_reg));
            else if (original_dest_reg < TheISA::Ctrl_Base_DepTag)
                this->setFloatRegOperandBits(this->staticInst.get(), idx, this->cpu->readFloatRegBits(prev_phys_reg));
        }
    }
    /** Calls hardware return from error interrupt. */
    Fault hwrei();
    /** Traps to handle specified fault. */
    void trap(Fault fault);
    bool simPalCheck(int palFunc);

    /** Emulates a syscall. */
    void syscall(int64_t callnum);

  public:

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readIntReg(this->_srcRegIdx[idx]);
    }

    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
    }

    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
    }

    /** @todo: Make results into arrays so they can handle multiple dest
     *  registers.
     */
    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
    {
        this->cpu->setIntReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
    }

    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
    {
        this->cpu->setFloatReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
    }

    void setFloatRegOperandBits(const StaticInst *si, int idx,
                                FloatRegBits val)
    {
        this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
    }

#if THE_ISA == MIPS_ISA
    uint64_t readRegOtherThread(int misc_reg)
    {
        panic("MIPS MT not defined for O3 CPU.\n");
        return 0;
    }

    void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val)
    {
        panic("MIPS MT not defined for O3 CPU.\n");
    }
#endif

  public:
    /** Calculates EA part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault calcEA()
    {
        return this->staticInst->eaCompInst()->execute(this, this->traceData);
    }

    /** Does the memory access part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault memAccess()
    {
        return this->staticInst->memAccInst()->execute(this, this->traceData);
    }
};

#endif // __CPU_O3_ALPHA_DYN_INST_HH__

<|endoftext|>