<commit_before>/*
 * CLKernel.cpp
 *
 *  Created on: Aug 1, 2010
 *      Author: rasmussn
 */

#include "CLKernel.hpp"
#include "CLDevice.hpp"
#include <stdio.h>
#include <sys/stat.h>

namespace PV {

static char * load_program_source(const char *filename);

CLKernel::CLKernel(cl_context context, cl_command_queue commands, cl_device_id device,
                   const char * filename, const char * name)
{
   this->device = device;
   this->commands = commands;
   this->profiling = true;
   this->elapsed = 0;

#ifdef PV_USE_OPENCL

   int status = CL_SUCCESS;

   // Create the compute program from the source buffer
   //
   char * source = load_program_source(filename);
   program = clCreateProgramWithSource(context, 1, (const char **) &source, NULL, &status);
   if (!program || status != CL_SUCCESS)
   {
       printf("Error: Failed to create compute program!\n");
       CLDevice::print_error_code(status);
       exit(status);
   }

   // Build the program executable
   //
   status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
   if (status != CL_SUCCESS)
   {
       size_t len;
       char buffer[2048];

       printf("Error: Failed to build program executable!\n");
       clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
       printf("%s\n", buffer);
       CLDevice::print_error_code(status);
       exit(status);
   }

   // Create the compute kernel in the program we wish to run
   //
   kernel = clCreateKernel(program, name, &status);
   if (!kernel || status != CL_SUCCESS)
   {
       fprintf(stderr, "Error: Failed to create compute kernel!\n");
       CLDevice::print_error_code(status);
       exit(status);
   }

#endif // PV_USE_OPENCL

}

int CLKernel::run(size_t global_work_size)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   size_t local_work_size;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
                                     sizeof(size_t), &local_work_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==%ld global_work_size==%ld\n", local_work_size, global_work_size);
   }
   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 1, NULL,
                                   &global_work_size, &local_work_size, 0, NULL, &event);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel!\n");
      CLDevice::print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::run(size_t gWorkSizeX, size_t gWorkSizeY, size_t lWorkSizeX, size_t lWorkSizeY)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   size_t local_work_size[2];
   size_t global_work_size[2];
   size_t max_local_size;

   global_work_size[0] = gWorkSizeX;
   global_work_size[1] = gWorkSizeY;

   local_work_size[0] = lWorkSizeX;
   local_work_size[1] = lWorkSizeY;

#ifdef PV_USE_TAU
   int tau_id = 10;
   TAU_START("CLKernel::run::CPU");
#endif

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
                                     sizeof(size_t), &max_local_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! (status==%d)\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   } else {
      //printf("run: local_work_size==(%ld,%ld) global_work_size==(%ld,%ld)\n",
      //       local_work_size[0], local_work_size[1], global_work_size[0], global_work_size[1]);
   }

   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 2, NULL,
                                   global_work_size, local_work_size, 0, NULL, &event);
   if (status) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel! (status==%d)\n", status);
      fprintf(stderr, "CLDevice::run(): max_local_work_size==%ld\n", max_local_size);
      CLDevice::print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   // get profiling information
   //
   if (profiling) {
      size_t param_size;
      cl_ulong start, end;
#ifdef PV_USE_TAU
      tau_id += 1000;
      TAU_STOP("CLKernel::run::CPU");
#endif
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START,
                                       sizeof(start), &start, &param_size);
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END,
                                       sizeof(end), &end, &param_size);
      if (status == 0) {
         elapsed = (end - start) / 1000;  // microseconds
      }
#ifdef PV_USE_TAU
      Tau_opencl_register_gpu_event("CLKernel::run::GPU", tau_id, start, end);
#endif
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, int arg)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, sizeof(int), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, float arg)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, sizeof(float), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, CLBuffer * buf)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL
   cl_mem mobj = buf->clMemObject();

   status = clSetKernelArg(kernel, argid, sizeof(cl_mem), &mobj);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }
#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setLocalArg(int argid, size_t size)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, size, 0);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addLocalArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

static char *
load_program_source(const char *filename)
{
    struct stat statbuf;
    FILE        *fh;
    char        *source;

    fh = fopen(filename, "r");
    if (fh == 0)
        return 0;

    stat(filename, &statbuf);
    source = (char *) malloc(statbuf.st_size + 1);
    fread(source, statbuf.st_size, 1, fh);
    source[statbuf.st_size] = '\0';

    return source;
}

}
<commit_msg>Set local_work_size to 1 if max_local_work_size is less than the local work size chosen.  This is needed if device is 1 (using CPU).<commit_after>/*
 * CLKernel.cpp
 *
 *  Created on: Aug 1, 2010
 *      Author: rasmussn
 */

#include "CLKernel.hpp"
#include "CLDevice.hpp"
#include <stdio.h>
#include <sys/stat.h>

namespace PV {

static char * load_program_source(const char *filename);

CLKernel::CLKernel(cl_context context, cl_command_queue commands, cl_device_id device,
                   const char * filename, const char * name)
{
   this->device = device;
   this->commands = commands;
   this->profiling = true;
   this->elapsed = 0;

#ifdef PV_USE_OPENCL

   int status = CL_SUCCESS;

   // Create the compute program from the source buffer
   //
   char * source = load_program_source(filename);
   program = clCreateProgramWithSource(context, 1, (const char **) &source, NULL, &status);
   if (!program || status != CL_SUCCESS)
   {
       printf("Error: Failed to create compute program!\n");
       CLDevice::print_error_code(status);
       exit(status);
   }

   // Build the program executable
   //
   status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
   if (status != CL_SUCCESS)
   {
       size_t len;
       char buffer[2048];

       printf("Error: Failed to build program executable!\n");
       clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
       printf("%s\n", buffer);
       CLDevice::print_error_code(status);
       exit(status);
   }

   // Create the compute kernel in the program we wish to run
   //
   kernel = clCreateKernel(program, name, &status);
   if (!kernel || status != CL_SUCCESS)
   {
       fprintf(stderr, "Error: Failed to create compute kernel!\n");
       CLDevice::print_error_code(status);
       exit(status);
   }

#endif // PV_USE_OPENCL

}

int CLKernel::run(size_t global_work_size)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   size_t local_work_size;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
                                     sizeof(size_t), &local_work_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==%ld global_work_size==%ld\n", local_work_size, global_work_size);
   }
   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 1, NULL,
                                   &global_work_size, &local_work_size, 0, NULL, &event);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel!\n");
      CLDevice::print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::run(size_t gWorkSizeX, size_t gWorkSizeY, size_t lWorkSizeX, size_t lWorkSizeY)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   size_t local_work_size[2];
   size_t global_work_size[2];
   size_t max_local_size;

   global_work_size[0] = gWorkSizeX;
   global_work_size[1] = gWorkSizeY;

   local_work_size[0] = lWorkSizeX;
   local_work_size[1] = lWorkSizeY;

#ifdef PV_USE_TAU
   int tau_id = 10;
   TAU_START("CLKernel::run::CPU");
#endif

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
                                     sizeof(size_t), &max_local_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! (status==%d)\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   } else {
      //printf("run: local_work_size==(%ld,%ld) global_work_size==(%ld,%ld)\n",
      //       local_work_size[0], local_work_size[1], global_work_size[0], global_work_size[1]);
   }

   if (lWorkSizeX * lWorkSizeY > max_local_size) {
      local_work_size[0] = 1;
      local_work_size[1] = 1;
   }

   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 2, NULL,
                                   global_work_size, local_work_size, 0, NULL, &event);
   if (status) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel! (status==%d)\n", status);
      fprintf(stderr, "CLDevice::run(): max_local_work_size==%ld\n", max_local_size);
      CLDevice::print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   // get profiling information
   //
   if (profiling) {
      size_t param_size;
      cl_ulong start, end;
#ifdef PV_USE_TAU
      tau_id += 1000;
      TAU_STOP("CLKernel::run::CPU");
#endif
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START,
                                       sizeof(start), &start, &param_size);
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END,
                                       sizeof(end), &end, &param_size);
      if (status == 0) {
         elapsed = (end - start) / 1000;  // microseconds
      }
#ifdef PV_USE_TAU
      Tau_opencl_register_gpu_event("CLKernel::run::GPU", tau_id, start, end);
#endif
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, int arg)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, sizeof(int), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, float arg)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, sizeof(float), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setKernelArg(int argid, CLBuffer * buf)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL
   cl_mem mobj = buf->clMemObject();

   status = clSetKernelArg(kernel, argid, sizeof(cl_mem), &mobj);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }
#endif // PV_USE_OPENCL

   return status;
}

int CLKernel::setLocalArg(int argid, size_t size)
{
   int status = CL_SUCCESS;

#ifdef PV_USE_OPENCL

   status = clSetKernelArg(kernel, argid, size, 0);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addLocalArg: Failed to set kernel argument! %d\n", status);
      CLDevice::print_error_code(status);
      exit(status);
   }

#endif // PV_USE_OPENCL

   return status;
}

static char *
load_program_source(const char *filename)
{
    struct stat statbuf;
    FILE        *fh;
    char        *source;

    fh = fopen(filename, "r");
    if (fh == 0)
        return 0;

    stat(filename, &statbuf);
    source = (char *) malloc(statbuf.st_size + 1);
    fread(source, statbuf.st_size, 1, fh);
    source[statbuf.st_size] = '\0';

    return source;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 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: Nathan Binkert
 */

/*
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratories.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
 *
 *	@(#)kgdb_stub.c	8.4 (Berkeley) 1/12/94
 */

/*-
 * Copyright (c) 2001 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the NetBSD
 *	Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

/*
 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
 *
 * Taken from NetBSD
 *
 * "Stub" to allow remote cpu to debug over a serial line using gdb.
 */

#include <sys/signal.h>

#include <string>
#include <unistd.h>

#include "arch/vtophys.hh"
#include "arch/sparc/remote_gdb.hh"
#include "base/intmath.hh"
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh"
#include "cpu/static_inst.hh"
#include "mem/physical.hh"
#include "mem/port.hh"
#include "sim/system.hh"

using namespace std;
using namespace TheISA;

RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
    : BaseRemoteGDB(_system, c, NumGDBRegs), nextBkpt(0)
{}

///////////////////////////////////////////////////////////
// RemoteGDB::acc
//
//	Determine if the mapping at va..(va+len) is valid.
//
bool
RemoteGDB::acc(Addr va, size_t len)
{
    //@Todo In NetBSD, this function checks if all addresses
    //from va to va + len have valid page mape entries. Not
    //sure how this will work for other OSes or in general.
    if (va)
        return true;
    return false;
}

///////////////////////////////////////////////////////////
// RemoteGDB::getregs
//
//	Translate the kernel debugger register format into
//	the GDB register format.
void
RemoteGDB::getregs()
{
    memset(gdbregs.regs, 0, gdbregs.size);

    if (context->readMiscReg(MISCREG_PSTATE) &
           PSTATE::am) {
        uint32_t *regs;
        regs = (uint32_t*)gdbregs.regs;
        regs[Reg32Pc] = htobe((uint32_t)context->readPC());
        regs[Reg32Npc] = htobe((uint32_t)context->readNextPC());
        for(int x = RegG0; x <= RegI0 + 7; x++)
            regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));

        regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1));
        regs[Reg32Psr] = htobe((uint32_t)context->readMiscReg(MISCREG_PSTATE));
        regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR));
        regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
    } else {
        gdbregs.regs[RegPc] = htobe(context->readPC());
        gdbregs.regs[RegNpc] = htobe(context->readNextPC());
        for(int x = RegG0; x <= RegI0 + 7; x++)
            gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));

        gdbregs.regs[RegFsr] = htobe(context->readMiscReg(MISCREG_FSR));
        gdbregs.regs[RegFprs] = htobe(context->readMiscReg(MISCREG_FPRS));
        gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
        gdbregs.regs[RegState] = htobe(
            context->readMiscReg(MISCREG_CWP) |
            context->readMiscReg(MISCREG_PSTATE) << 8 |
            context->readMiscReg(MISCREG_ASI) << 24 |
            context->readIntReg(NumIntArchRegs + 2) << 32);
    }

    DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]);

    //Floating point registers are left at 0 in netbsd
    //All registers other than the pc, npc and int regs
    //are ignored as well.
}

///////////////////////////////////////////////////////////
// RemoteGDB::setregs
//
//	Translate the GDB register format into the kernel
//	debugger register format.
//
void
RemoteGDB::setregs()
{
    context->setPC(gdbregs.regs[RegPc]);
    context->setNextPC(gdbregs.regs[RegNpc]);
    for(int x = RegG0; x <= RegI0 + 7; x++)
        context->setIntReg(x - RegG0, gdbregs.regs[x]);
    //Only the integer registers, pc and npc are set in netbsd
}

void
RemoteGDB::clearSingleStep()
{
   if (nextBkpt)
       clearTempBreakpoint(nextBkpt);
}

void
RemoteGDB::setSingleStep()
{
    nextBkpt = context->readNextPC();
    setTempBreakpoint(nextBkpt);
}
<commit_msg>SPARC,Remote GDB: Flesh out the acc function for SE mode.<commit_after>/*
 * Copyright (c) 2002-2005 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: Nathan Binkert
 */

/*
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratories.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
 *
 *	@(#)kgdb_stub.c	8.4 (Berkeley) 1/12/94
 */

/*-
 * Copyright (c) 2001 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the NetBSD
 *	Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

/*
 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
 *
 * Taken from NetBSD
 *
 * "Stub" to allow remote cpu to debug over a serial line using gdb.
 */

#include <sys/signal.h>

#include <string>
#include <unistd.h>

#include "arch/vtophys.hh"
#include "arch/sparc/remote_gdb.hh"
#include "base/intmath.hh"
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh"
#include "cpu/static_inst.hh"
#include "mem/page_table.hh"
#include "mem/physical.hh"
#include "mem/port.hh"
#include "sim/process.hh"
#include "sim/system.hh"

using namespace std;
using namespace TheISA;

RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
    : BaseRemoteGDB(_system, c, NumGDBRegs), nextBkpt(0)
{}

///////////////////////////////////////////////////////////
// RemoteGDB::acc
//
//	Determine if the mapping at va..(va+len) is valid.
//
bool
RemoteGDB::acc(Addr va, size_t len)
{
    //@Todo In NetBSD, this function checks if all addresses
    //from va to va + len have valid page map entries. Not
    //sure how this will work for other OSes or in general.
#if FULL_SYSTEM
    if (va)
        return true;
    return false;
#else
    TlbEntry entry;
    //Check to make sure the first byte is mapped into the processes address
    //space.
    if (context->getProcessPtr()->pTable->lookup(va, entry))
        return true;
    return false;
#endif
}

///////////////////////////////////////////////////////////
// RemoteGDB::getregs
//
//	Translate the kernel debugger register format into
//	the GDB register format.
void
RemoteGDB::getregs()
{
    memset(gdbregs.regs, 0, gdbregs.size);

    if (context->readMiscReg(MISCREG_PSTATE) &
           PSTATE::am) {
        uint32_t *regs;
        regs = (uint32_t*)gdbregs.regs;
        regs[Reg32Pc] = htobe((uint32_t)context->readPC());
        regs[Reg32Npc] = htobe((uint32_t)context->readNextPC());
        for(int x = RegG0; x <= RegI0 + 7; x++)
            regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));

        regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1));
        regs[Reg32Psr] = htobe((uint32_t)context->readMiscReg(MISCREG_PSTATE));
        regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR));
        regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
    } else {
        gdbregs.regs[RegPc] = htobe(context->readPC());
        gdbregs.regs[RegNpc] = htobe(context->readNextPC());
        for(int x = RegG0; x <= RegI0 + 7; x++)
            gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));

        gdbregs.regs[RegFsr] = htobe(context->readMiscReg(MISCREG_FSR));
        gdbregs.regs[RegFprs] = htobe(context->readMiscReg(MISCREG_FPRS));
        gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
        gdbregs.regs[RegState] = htobe(
            context->readMiscReg(MISCREG_CWP) |
            context->readMiscReg(MISCREG_PSTATE) << 8 |
            context->readMiscReg(MISCREG_ASI) << 24 |
            context->readIntReg(NumIntArchRegs + 2) << 32);
    }

    DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]);

    //Floating point registers are left at 0 in netbsd
    //All registers other than the pc, npc and int regs
    //are ignored as well.
}

///////////////////////////////////////////////////////////
// RemoteGDB::setregs
//
//	Translate the GDB register format into the kernel
//	debugger register format.
//
void
RemoteGDB::setregs()
{
    context->setPC(gdbregs.regs[RegPc]);
    context->setNextPC(gdbregs.regs[RegNpc]);
    for(int x = RegG0; x <= RegI0 + 7; x++)
        context->setIntReg(x - RegG0, gdbregs.regs[x]);
    //Only the integer registers, pc and npc are set in netbsd
}

void
RemoteGDB::clearSingleStep()
{
   if (nextBkpt)
       clearTempBreakpoint(nextBkpt);
}

void
RemoteGDB::setSingleStep()
{
    nextBkpt = context->readNextPC();
    setTempBreakpoint(nextBkpt);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFont.h"
#include "SkPath.h"

// This GM shows off a flaw in delta-based rasterizers (DAA, CCPR, etc.).
// See also the bottom of dashing4 and skia:6886.

static const int K = 50;

DEF_SIMPLE_GM(daa, canvas, K+350, K) {
    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(SK_ColorBLACK);
    canvas->drawString("Should be a green square with no red showing through.",
                       K*1.5f, K/2, SkFont(), paint);

    paint.setColor(SK_ColorRED);
    canvas->drawRect({0,0,K,K}, paint);

    SkPath path;
    SkPoint tri1[] = {{0,0},{K,K},{0,K},{0,0}};
    SkPoint tri2[] = {{0,0},{K,K},{K,0},{0,0}};
    path.addPoly(tri1, SK_ARRAY_COUNT(tri1), false);
    path.addPoly(tri2, SK_ARRAY_COUNT(tri2), false);

    paint.setColor(SK_ColorGREEN);
    canvas->drawPath(path, paint);
}
<commit_msg>Roll external/skia d6841487e..1edcea99a (1 commits)<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFont.h"
#include "SkPath.h"

// This GM shows off a flaw in delta-based rasterizers (DAA, CCPR, etc.).
// See also the bottom of dashing4 and skia:6886.

static const int K = 49;

DEF_SIMPLE_GM(daa, canvas, K+350, 5*K) {
    SkPaint paint;
    paint.setAntiAlias(true);

    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Should be a green square with no red showing through.",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        SkPath path;
        SkPoint tri1[] = {{0,0},{K,K},{0,K},{0,0}};
        SkPoint tri2[] = {{0,0},{K,K},{K,0},{0,0}};
        path.addPoly(tri1, SK_ARRAY_COUNT(tri1), false);
        path.addPoly(tri2, SK_ARRAY_COUNT(tri2), false);

        paint.setColor(SK_ColorGREEN);
        canvas->drawPath(path, paint);
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, two draws.  Blue then green, no red?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);

            paint.setColor(SK_ColorBLUE);
            canvas->drawPath(path, paint);
        }

        {
            SkPath path;
            SkPoint rect2[] = {{K*0.5f,0},{K*0.5f,K},{K,K},{K,0}};
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, wound together.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            SkPoint rect2[] = {{K*0.5f,0},{K*0.5f,K},{K,K},{K,0}};

            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, wound opposite.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            SkPoint rect2[] = {{K*0.5f,0},{K,0},{K,K},{K*0.5f,K}};

            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("One poly, wound opposite.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint poly[] = {{K*0.5f,0},{0,0},{0,K},{K*0.5f,K},{K*0.5f,0},{K,0},{K,K},{K*0.5f,K}};

            path.addPoly(poly, SK_ARRAY_COUNT(poly), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }
}
<|endoftext|>


<commit_before>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <iostream>
#include <map>
using namespace std;

#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimArgumentParser.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimStdOutProgress.h>
#include <ossim/base/ossimTimer.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimString.h>
#include <ossim/util/ossimUtilityRegistry.h>
#include <ossim/base/ossimException.h>

int main(int argc, char *argv[])
{
   ossimArgumentParser ap(&argc, argv);
   ap.getApplicationUsage()->setApplicationName(argv[0]);

   try
   {
      // Initialize ossim stuff, factories, plugin, etc.
      ossimInit::instance()->initialize(ap);

      ossimUtilityFactoryBase* factory = ossimUtilityRegistry::instance();
      map<string, string> capabilities;
      factory->getCapabilities(capabilities);
      ossimRefPtr<ossimUtility> utility = 0;
      ossimString toolName;
      ossimKeywordlist kwl;
      char input[4096];
      bool usingCmdLineMode = false;

      if ((argc > 1) && (ossimString(argv[1]).contains("help")))
      {
         cout << "\nUsages: "<<endl;
         cout << "    "<<argv[0]<<" <command> [command options and parameters]"<<endl;
         cout << "    "<<argv[0]<<" --version"<<endl;
         cout << "    "<<argv[0]<<"  (with no args, displays command descriptions)\n"<<endl;
         exit (0);
      }

      if  (argc > 1)
      {
         if (ossimString(argv[1]).contains("--"))
         {
            // Support ossim-info style system queries by interpreting any options as options to
            // info tool:
            toolName = "info";
            usingCmdLineMode = true;
         }
         else if (kwl.addFile(argv[1]))
         {
            // KWL filename provided, get tool name from it:
            toolName = kwl.find("tool");
            ap.remove(0);
         }
         else
         {
            // The tool name was explicitely provided on command line:
            toolName = argv[1];
            if (argc > 2)
               usingCmdLineMode = true;
            ap.remove(0);
         }
      }

      // Using one-time do-loop for breaking out when finished processing:
      do
      {
         if (toolName.empty())
         {
            map<string, string>::iterator iter = capabilities.begin();
            cout<<"\n\nAvailable commands:"<<endl;
            for (;iter != capabilities.end(); ++iter)
               cout<<"  "<<iter->first<<" -- "<<iter->second<<endl;

            // Query for operation:
            cout << "\nossim> ";
            cin.getline(input, 256);
            if (input[0] == 'q')
               break;
            toolName = input;
         }

         // Fetch the utility object:
         ossimRefPtr<ossimUtility> utility = factory->createUtility(toolName);
         if (!utility.valid())
         {
            cout << "\nDid not understand <"<<toolName<<">"<<endl;
            continue;
         }

         if (usingCmdLineMode)
         {
            // Check if user provided options along with tool name:
            // Init utility with command line
            if (!utility->initialize(ap))
            {
               cout << "\nCould not execute command with options provided."<<endl;
            }
            if (!utility->execute())
            {
               cout << "\nAn error was encountered executing the command. Check options."<<endl;
            }
            continue;
         }

         if (utility.valid() && !toolName.empty())
         {
            // Have toolname but no command line options:
            cout << "\nEnter command arguments/options or return for usage. "<<endl;
            cout << "\nossim> ";
            cin.getline(input, 4096);
            if (input[0] == 'q')
               break;

            // Create the command line with either "help" or inputs:
            ossimString cmdLine (toolName);
            cmdLine += " ";
            if (input[0] == '\0')
               cmdLine += "--help";
            else
               cmdLine += input;

            // Run command:
            ossimArgumentParser tap (cmdLine);
            utility->initialize(tap);
            if (cmdLine.contains("--help"))
               continue;
            utility->execute();
            break;
         }
         if (kwl.getSize() == 0)
         {
            //
            // Query for config filename:
            ossimKeywordlist kwl;
            cout << "\nEnter config file name or <return> for template: " << ends;
            cin.getline(input, 4096);
            if (input[0] && !kwl.addFile(input))
            {
               cout<<"\nCould not load config file at <"<<input<<">"<<endl;
               break;
            }
         }

         // Init utility with KWL if available:
         if (kwl.getSize())
         {
            utility->initialize(kwl);
            utility->execute();
            break;
         }

         // Display API:
         ossimKeywordlist kwl_template;
         utility->getKwlTemplate(kwl_template);
         cout << "\nUtility template specification: "<<endl;
         cout << kwl_template << endl;

         // Accept inputs:
         do
         {
            cout << "Enter \"<keyword>: <value>\" with colon separator (or 'x' to finish): ";
            cin.getline(input, 4096);
            if (input[0] == 'x' || (!kwl.parseString(string(input))))
               break;
         } while (1);

         if (kwl.getSize() == 0)
            break;

         // Display final KWL:
         cout << "\nUtility final specification: "<<endl;
         cout << kwl << endl;

         // Query go-ahead. Perform operation:
         while (1)
         {
            cout << "Perform operation? [y|n]: ";
            cin.getline(input, 4096);
            if (input[0] == 'n')
               break;
            else if (input[0] == 'y')
            {
               utility->initialize(kwl);
               utility->execute();
               break;
            }
         }

      } while (true);
   }
   catch  (const ossimException& e)
   {
      ossimNotify(ossimNotifyLevel_FATAL)<<e.what()<<endl;
      exit(1);
   }
   catch( ... )
   {
      cerr << "Caught unknown exception!" << endl;
   }

   exit(0);
}
<commit_msg>Fixed typo in ossim-cli<commit_after>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <iostream>
#include <map>
using namespace std;

#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimArgumentParser.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimStdOutProgress.h>
#include <ossim/base/ossimTimer.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimString.h>
#include <ossim/util/ossimUtilityRegistry.h>
#include <ossim/base/ossimException.h>

int main(int argc, char *argv[])
{
   ossimArgumentParser ap(&argc, argv);
   ap.getApplicationUsage()->setApplicationName(argv[0]);

   try
   {
      // Initialize ossim stuff, factories, plugin, etc.
      ossimInit::instance()->initialize(ap);

      ossimUtilityFactoryBase* factory = ossimUtilityRegistry::instance();
      map<string, string> capabilities;
      factory->getCapabilities(capabilities);
      ossimRefPtr<ossimUtility> utility = 0;
      ossimString toolName;
      ossimKeywordlist kwl;
      char input[4096];
      bool usingCmdLineMode = false;

      if ((argc > 1) && (ossimString(argv[1]).contains("help")))
      {
         cout << "\nUsages: "<<endl;
         cout << "    "<<argv[0]<<" <command> [command options and parameters]"<<endl;
         cout << "    "<<argv[0]<<" --version"<<endl;
         cout << "    "<<argv[0]<<"  (with no args, displays command descriptions)\n"<<endl;
         exit (0);
      }

      if  (argc > 1)
      {
         if (ossimString(argv[1]).contains("--"))
         {
            // Support ossim-info style system queries by interpreting any options as options to
            // info tool:
            toolName = "info";
            usingCmdLineMode = true;
         }
         else if (kwl.addFile(argv[1]))
         {
            // KWL filename provided, get tool name from it:
            toolName = kwl.find("tool");
            ap.remove(0);
         }
         else
         {
            // The tool name was explicitely provided on command line:
            toolName = argv[1];
            if (argc > 2)
               usingCmdLineMode = true;
            ap.remove(0);
         }
      }

      // Using one-time do-loop for breaking out when finished processing:
      do
      {
         if (toolName.empty())
         {
            map<string, string>::iterator iter = capabilities.begin();
            cout<<"\n\nAvailable commands:"<<endl;
            for (;iter != capabilities.end(); ++iter)
               cout<<"  "<<iter->first<<" -- "<<iter->second<<endl;

            // Query for operation:
            cout << "\nossim> ";
            cin.getline(input, 256);
            if (input[0] == 'q')
               break;
            toolName = input;
         }

         // Fetch the utility object:
         ossimRefPtr<ossimUtility> utility = factory->createUtility(toolName);
         if (!utility.valid())
         {
            cout << "\nDid not understand <"<<toolName<<">"<<endl;
            continue;
         }

         if (usingCmdLineMode)
         {
            // Check if user provided options along with tool name:
            // Init utility with command line
            if (!utility->initialize(ap))
            {
               cout << "\nCould not execute command with options provided."<<endl;
            }
            if (!utility->execute())
            {
               cout << "\nAn error was encountered executing the command. Check options."<<endl;
            }
            break;
         }

         if (utility.valid() && !toolName.empty())
         {
            // Have toolname but no command line options:
            cout << "\nEnter command arguments/options or return for usage. "<<endl;
            cout << "\nossim> ";
            cin.getline(input, 4096);
            if (input[0] == 'q')
               break;

            // Create the command line with either "help" or inputs:
            ossimString cmdLine (toolName);
            cmdLine += " ";
            if (input[0] == '\0')
               cmdLine += "--help";
            else
               cmdLine += input;

            // Run command:
            ossimArgumentParser tap (cmdLine);
            utility->initialize(tap);
            if (cmdLine.contains("--help"))
            {
               toolName = "";
               continue;
            }
            utility->execute();
            break;
         }
         if (kwl.getSize() == 0)
         {
            //
            // Query for config filename:
            ossimKeywordlist kwl;
            cout << "\nEnter config file name or <return> for template: " << ends;
            cin.getline(input, 4096);
            if (input[0] && !kwl.addFile(input))
            {
               cout<<"\nCould not load config file at <"<<input<<">"<<endl;
               break;
            }
         }

         // Init utility with KWL if available:
         if (kwl.getSize())
         {
            utility->initialize(kwl);
            utility->execute();
            break;
         }

         // Display API:
         ossimKeywordlist kwl_template;
         utility->getKwlTemplate(kwl_template);
         cout << "\nUtility template specification: "<<endl;
         cout << kwl_template << endl;

         // Accept inputs:
         do
         {
            cout << "Enter \"<keyword>: <value>\" with colon separator (or 'x' to finish): ";
            cin.getline(input, 4096);
            if (input[0] == 'x' || (!kwl.parseString(string(input))))
               break;
         } while (1);

         if (kwl.getSize() == 0)
            break;

         // Display final KWL:
         cout << "\nUtility final specification: "<<endl;
         cout << kwl << endl;

         // Query go-ahead. Perform operation:
         while (1)
         {
            cout << "Perform operation? [y|n]: ";
            cin.getline(input, 4096);
            if (input[0] == 'n')
               break;
            else if (input[0] == 'y')
            {
               utility->initialize(kwl);
               utility->execute();
               break;
            }
         }

      } while (true);
   }
   catch  (const ossimException& e)
   {
      ossimNotify(ossimNotifyLevel_FATAL)<<e.what()<<endl;
      exit(1);
   }
   catch( ... )
   {
      cerr << "Caught unknown exception!" << endl;
   }

   exit(0);
}
<|endoftext|>


<commit_before>#define BENCHMARK_FIB
//#define SINGLESTEP

#ifdef BENCHMARK_FIB
# define START 0
# define ENTRY 0
#else
# define START 0
# define ENTRY 0
#endif

#include "timings.h"

#define START_NO 1000000000
#define TIMES 100

#include <libcpu.h>
#include "arch/m88k/libcpu_m88k.h"
#include "arch/m88k/m88k_isa.h"

//////////////////////////////////////////////////////////////////////
// command line parsing helpers
//////////////////////////////////////////////////////////////////////

void tag_extra(cpu_t *cpu, char *entries)
{
	addr_t entry;
	char* old_entries;

	while (entries && *entries) {
	/* just one for now */
		if (entries[0] == ',')
			entries++;
		if (!entries[0])
			break;
		old_entries = entries;
		entry = (addr_t)strtol(entries, &entries, 0);
		if (entries == old_entries) {
			printf("Error parsing entries!\n");
			exit(3);
		}
		cpu_tag(cpu, entry);
	}
}

void tag_extra_filename(cpu_t *cpu, char *filename)
{
	FILE *fp;
	char *buf;
	size_t nbytes;

	fp = fopen(filename, "r");
	if (!fp) {
		perror("error opening tag file");
		exit(3);
	}
	fseek(fp, 0, SEEK_END);
	nbytes = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	buf = (char*)malloc(nbytes + 1);
	nbytes = fread(buf, 1, nbytes, fp);
	buf[nbytes] = '\0';
	fclose(fp);

	while (nbytes && buf[nbytes - 1] == '\n')
		buf[--nbytes] = '\0';

	tag_extra(cpu, buf);
	free(buf);
}

void __attribute__((noinline))
breakpoint() {
asm("nop");
}

static double
ieee754_fp80_to_double(fp80_reg_t reg)
{
#if defined(__i386__) || defined(__x86_64__)
#if 0
	uint32_t sign      = (reg.i.hi & 0x8000) != 0;
	uint32_t exp       = reg.i.hi & 0x7fff;
	uint64_t mantissa  = reg.i.lo;
#endif
	return (double)reg.f;
#else
	uint32_t sign      = (reg.i.hi & 0x8000) != 0;
	uint32_t exp       = reg.i.hi & 0x7fff;
	uint64_t mantissa  = reg.i.lo << 1;

	uint64_t v64 = ((uint64_t)sign << 63) |
		((uint64_t)(exp & 0x7000) << 48) |
		((uint64_t)(exp & 0x3ff) << 52) |
		(mantissa >> 12);

	return *(double *)&v64;
#endif
}

#if 0
static void
ieee754_fp80_set_d(fp80_reg_t *reg, double v)
{
#if defined(__i386__) || defined(__x86_64__)
	reg->f = v;
#else
	uint64_t v64       = *(uint64_t *)&v;
	uint32_t sign      = (v64 >> 63);
	uint32_t exp       = (v64 >> 52) & 0x7ff;
	uint64_t mantissa  = v64 & ((1ULL << 52) - 1);

	mantissa <<= 11;
	mantissa |= (1ULL << 63);

	exp = ((exp & 0x700) << 4) | ((-((exp >> 9) & 1)) & 0xf00) | (exp & 0x3ff);

	reg->i.hi = (sign << 15) | exp;
	reg->i.lo = mantissa;
#endif
}
#endif

static void
dump_state(uint8_t *RAM, m88k_grf_t *reg, m88k_xrf_t *xrf)
{
	printf("%08llx:", (unsigned long long)reg->sxip);
	for (int i=0; i<32; i++) {
		if (!(i%4))
			printf("\n");
		printf("R%02d=%08x ", i, (unsigned int)reg->r[i]);
	}
	for (int i=0; xrf != NULL && i<32; i++) {
		if (!(i%2))
			printf("\n");
		printf("X%02d=%04x%016llx (%.8f) ", i,
			xrf->x[i].i.hi, xrf->x[i].i.lo,
			ieee754_fp80_to_double(xrf->x[i]));
	}
	uint32_t base = reg->r[31];
	for (int i=0; i<256 && i+base<65536; i+=4) {
		if (!(i%16))
			printf("\nSTACK: ");
		printf("%08x ", *(unsigned int*)&RAM[(base+i)]);
	}
	printf("\n");
}

static void
debug_function(cpu_t *cpu) {
	fprintf(stderr, "%s:%u\n", __FILE__, __LINE__);
}

#if 0
int fib(int n)
{
	if (n==0 || n==1)
		return n;
	else
		return fib(n-1) + fib(n-2);
}
#else
int fib(int n)
{
    int f2=0;
    int f1=1;
    int fib=0;
    int i;

    if (n==0 || n==1)
        return n;
    for(i=2;i<=n;i++){
        fib=f1+f2; /*sum*/
        f2=f1;
        f1=fib;
    }
    return fib;
}
#endif

//////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
	char *executable;
	char *entries;
	cpu_t *cpu;
	uint8_t *RAM;
	FILE *f;
	int ramsize;
	char *stack;
	int i;
#ifdef BENCHMARK_FIB
	int r1, r2;
	uint64_t t1, t2, t3, t4;
	unsigned start_no = START_NO;
#endif
#ifdef SINGLESTEP
	int step = 0;
#endif
	ramsize = 5*1024*1024;
	RAM = (uint8_t*)malloc(ramsize);

	cpu = cpu_new(CPU_ARCH_M88K, CPU_FLAG_ENDIAN_BIG, 0);

#ifdef SINGLESTEP
	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
	cpu_set_flags_debug(cpu, CPU_DEBUG_SINGLESTEP | CPU_DEBUG_PRINT_IR | CPU_DEBUG_PRINT_IR_OPTIMIZED);
#else
	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
//	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_NONE);
//	cpu_set_flags_optimize(cpu, 0x3eff);
//	cpu_set_flags_optimize(cpu, 0x3eff);
	cpu_set_flags_debug(cpu, CPU_DEBUG_PRINT_IR | CPU_DEBUG_PRINT_IR_OPTIMIZED);
#endif

	cpu_set_ram(cpu, RAM);

	/* parameter parsing */
	if (argc < 2) {
#ifdef BENCHMARK_FIB
		printf("Usage: %s executable [itercount] [entries]\n", argv[0]);
#else
		printf("Usage: %s executable [entries]\n", argv[0]);
#endif
		return 0;
	}

	executable = argv[1];
#ifdef BENCHMARK_FIB
	if (argc >= 3)
		start_no = atoi(argv[2]);

	if (argc >= 4)
		entries = argv[3];
	else
		entries = 0;
#else
	if (argc >= 3)
		entries = argv[2];
	else
		entries = 0;
#endif

	/* load code */
	if (!(f = fopen(executable, "rb"))) {
		printf("Could not open %s!\n", executable);
		return 2;
	}
	cpu->code_start = START;
	cpu->code_end = cpu->code_start + fread(&RAM[cpu->code_start], 1, ramsize-cpu->code_start, f);
	fclose(f);
	cpu->code_entry = cpu->code_start + ENTRY;

	cpu_tag(cpu, cpu->code_entry);

	if (entries && *entries == '@')
		tag_extra_filename(cpu, entries + 1);
	else
		tag_extra(cpu, entries); /* tag extra entry points from the command line */

#ifdef RET_OPTIMIZATION
	find_rets(RAM, cpu->code_start, cpu->code_end);
#endif

	printf("*** Executing...\n");

#define STACK_SIZE 65536

	stack = (char *)(ramsize - STACK_SIZE); // THIS IS *GUEST* ADDRESS!

#define STACK ((long long)(stack+STACK_SIZE-4))

#define PC (((m88k_grf_t*)cpu->rf.grf)->sxip)
#define PSR (((m88k_grf_t*)cpu->rf.grf)->psr)
#define R (((m88k_grf_t*)cpu->rf.grf)->r)
#define X (((m88k_xrf_t*)cpu->rf.fpr)->x)

	PC = cpu->code_entry;
#if 0
	for (i = 1; i < 32; i++)
		R[i] = 0xF0000000 + i;	// DEBUG
#endif
	R[31] = STACK; // STACK
	R[1] = -1; // return address

#ifdef BENCHMARK_FIB//fib
	R[2] = start_no; // parameter
#else
	R[2] = 0x3f800000; // 1.0
	ieee754_fp80_set_d(&X[2], 1.0);
#endif
	dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, NULL);

#ifdef SINGLESTEP
	for(step = 0;;) {
		printf("::STEP:: %d\n", step++);

		cpu_run(cpu, debug_function);

		dump_state(RAM, (m88k_grf_t*)cpu->reg);
		printf ("NPC=%08x\n", PC);

		if (PC == -1)
			break;

		cpu_flush(cpu);
		printf("*** PRESS <ENTER> TO CONTINUE ***\n");
		getchar();
	}
#else
	for(;;) {
		int ret;
		breakpoint();
		ret = cpu_run(cpu, debug_function);
		printf("ret = %d\n", ret);
		switch (ret) {
			case JIT_RETURN_NOERR: /* JIT code wants us to end execution */
				break;
			case JIT_RETURN_FUNCNOTFOUND:
				dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, (m88k_xrf_t*)cpu->rf.frf);

				if (PC == (uint32_t)(-1))
					goto double_break;

				// bad :(
				printf("%s: error: $%llX not found!\n", __func__, (unsigned long long)PC);
				printf("PC: ");
				for (i = 0; i < 16; i++)
					printf("%02X ", RAM[PC+i]);
				printf("\n");
				exit(1);
			default:
				printf("unknown return code: %d\n", ret);
		}
	}
double_break:
#ifdef BENCHMARK_FIB
	printf("start_no=%u\n", start_no);

	printf("RUN1..."); fflush(stdout);
	PC = cpu->code_entry;

	for (i = 1; i < 32; i++)
		R[i] = 0xF0000000 + i;	// DEBUG

	R[31] = STACK; // STACK
	R[1] = -1; // return address

	R[2] = start_no; // parameter
	breakpoint();

	t1 = abs_time();
//	for (int i=0; i<TIMES; i++)
		cpu_run(cpu, debug_function);
	r1 = R[2];
	t2 = abs_time();

	printf("done!\n");

	dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, NULL);

	printf("RUN2..."); fflush(stdout);
	t3 = abs_time();
//	for (int i=0; i<TIMES; i++)
		r2 = fib(start_no);
	t4 = abs_time();
	printf("done!\n");

	printf("%d -- %d\n", r1, r2);
	printf("%lld -- %lld\n", t2-t1, t4-t3);
	printf("%f%%\n",  (float)(t2-t1)/(float)(t4-t3));
#endif
#endif

	printf("done.\n");

	int base = 0x2000;
	for (int i=0; i<256; i+=4) {
		if (!(i%16))
			printf("\nDATA: ");
		printf("%08x ", *(unsigned int*)&RAM[(base+i)]);
	}
	printf("\n");

	return 0;
}
<commit_msg>Pass fp80_reg_t by reference (MSVC doesn't like passing structs with alignment by value)<commit_after>#define BENCHMARK_FIB
//#define SINGLESTEP

#ifdef BENCHMARK_FIB
# define START 0
# define ENTRY 0
#else
# define START 0
# define ENTRY 0
#endif

#include "timings.h"

#define START_NO 1000000000
#define TIMES 100

#include <libcpu.h>
#include "arch/m88k/libcpu_m88k.h"
#include "arch/m88k/m88k_isa.h"

//////////////////////////////////////////////////////////////////////
// command line parsing helpers
//////////////////////////////////////////////////////////////////////

void tag_extra(cpu_t *cpu, char *entries)
{
	addr_t entry;
	char* old_entries;

	while (entries && *entries) {
	/* just one for now */
		if (entries[0] == ',')
			entries++;
		if (!entries[0])
			break;
		old_entries = entries;
		entry = (addr_t)strtol(entries, &entries, 0);
		if (entries == old_entries) {
			printf("Error parsing entries!\n");
			exit(3);
		}
		cpu_tag(cpu, entry);
	}
}

void tag_extra_filename(cpu_t *cpu, char *filename)
{
	FILE *fp;
	char *buf;
	size_t nbytes;

	fp = fopen(filename, "r");
	if (!fp) {
		perror("error opening tag file");
		exit(3);
	}
	fseek(fp, 0, SEEK_END);
	nbytes = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	buf = (char*)malloc(nbytes + 1);
	nbytes = fread(buf, 1, nbytes, fp);
	buf[nbytes] = '\0';
	fclose(fp);

	while (nbytes && buf[nbytes - 1] == '\n')
		buf[--nbytes] = '\0';

	tag_extra(cpu, buf);
	free(buf);
}

void __attribute__((noinline))
breakpoint() {
asm("nop");
}

static double
ieee754_fp80_to_double(const fp80_reg_t &reg)
{
#if defined(__i386__) || defined(__x86_64__)
#if 0
	uint32_t sign      = (reg.i.hi & 0x8000) != 0;
	uint32_t exp       = reg.i.hi & 0x7fff;
	uint64_t mantissa  = reg.i.lo;
#endif
	return (double)reg.f;
#else
	uint32_t sign      = (reg.i.hi & 0x8000) != 0;
	uint32_t exp       = reg.i.hi & 0x7fff;
	uint64_t mantissa  = reg.i.lo << 1;

	uint64_t v64 = ((uint64_t)sign << 63) |
		((uint64_t)(exp & 0x7000) << 48) |
		((uint64_t)(exp & 0x3ff) << 52) |
		(mantissa >> 12);

	return *(double *)&v64;
#endif
}

#if 0
static void
ieee754_fp80_set_d(fp80_reg_t *reg, double v)
{
#if defined(__i386__) || defined(__x86_64__)
	reg->f = v;
#else
	uint64_t v64       = *(uint64_t *)&v;
	uint32_t sign      = (v64 >> 63);
	uint32_t exp       = (v64 >> 52) & 0x7ff;
	uint64_t mantissa  = v64 & ((1ULL << 52) - 1);

	mantissa <<= 11;
	mantissa |= (1ULL << 63);

	exp = ((exp & 0x700) << 4) | ((-((exp >> 9) & 1)) & 0xf00) | (exp & 0x3ff);

	reg->i.hi = (sign << 15) | exp;
	reg->i.lo = mantissa;
#endif
}
#endif

static void
dump_state(uint8_t *RAM, m88k_grf_t *reg, m88k_xrf_t *xrf)
{
	printf("%08llx:", (unsigned long long)reg->sxip);
	for (int i=0; i<32; i++) {
		if (!(i%4))
			printf("\n");
		printf("R%02d=%08x ", i, (unsigned int)reg->r[i]);
	}
	for (int i=0; xrf != NULL && i<32; i++) {
		if (!(i%2))
			printf("\n");
		printf("X%02d=%04x%016llx (%.8f) ", i,
			xrf->x[i].i.hi, xrf->x[i].i.lo,
			ieee754_fp80_to_double(xrf->x[i]));
	}
	uint32_t base = reg->r[31];
	for (int i=0; i<256 && i+base<65536; i+=4) {
		if (!(i%16))
			printf("\nSTACK: ");
		printf("%08x ", *(unsigned int*)&RAM[(base+i)]);
	}
	printf("\n");
}

static void
debug_function(cpu_t *cpu) {
	fprintf(stderr, "%s:%u\n", __FILE__, __LINE__);
}

#if 0
int fib(int n)
{
	if (n==0 || n==1)
		return n;
	else
		return fib(n-1) + fib(n-2);
}
#else
int fib(int n)
{
    int f2=0;
    int f1=1;
    int fib=0;
    int i;

    if (n==0 || n==1)
        return n;
    for(i=2;i<=n;i++){
        fib=f1+f2; /*sum*/
        f2=f1;
        f1=fib;
    }
    return fib;
}
#endif

//////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
	char *executable;
	char *entries;
	cpu_t *cpu;
	uint8_t *RAM;
	FILE *f;
	int ramsize;
	char *stack;
	int i;
#ifdef BENCHMARK_FIB
	int r1, r2;
	uint64_t t1, t2, t3, t4;
	unsigned start_no = START_NO;
#endif
#ifdef SINGLESTEP
	int step = 0;
#endif
	ramsize = 5*1024*1024;
	RAM = (uint8_t*)malloc(ramsize);

	cpu = cpu_new(CPU_ARCH_M88K, CPU_FLAG_ENDIAN_BIG, 0);

#ifdef SINGLESTEP
	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
	cpu_set_flags_debug(cpu, CPU_DEBUG_SINGLESTEP | CPU_DEBUG_PRINT_IR | CPU_DEBUG_PRINT_IR_OPTIMIZED);
#else
	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
//	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_NONE);
//	cpu_set_flags_optimize(cpu, 0x3eff);
//	cpu_set_flags_optimize(cpu, 0x3eff);
	cpu_set_flags_debug(cpu, CPU_DEBUG_PRINT_IR | CPU_DEBUG_PRINT_IR_OPTIMIZED);
#endif

	cpu_set_ram(cpu, RAM);

	/* parameter parsing */
	if (argc < 2) {
#ifdef BENCHMARK_FIB
		printf("Usage: %s executable [itercount] [entries]\n", argv[0]);
#else
		printf("Usage: %s executable [entries]\n", argv[0]);
#endif
		return 0;
	}

	executable = argv[1];
#ifdef BENCHMARK_FIB
	if (argc >= 3)
		start_no = atoi(argv[2]);

	if (argc >= 4)
		entries = argv[3];
	else
		entries = 0;
#else
	if (argc >= 3)
		entries = argv[2];
	else
		entries = 0;
#endif

	/* load code */
	if (!(f = fopen(executable, "rb"))) {
		printf("Could not open %s!\n", executable);
		return 2;
	}
	cpu->code_start = START;
	cpu->code_end = cpu->code_start + fread(&RAM[cpu->code_start], 1, ramsize-cpu->code_start, f);
	fclose(f);
	cpu->code_entry = cpu->code_start + ENTRY;

	cpu_tag(cpu, cpu->code_entry);

	if (entries && *entries == '@')
		tag_extra_filename(cpu, entries + 1);
	else
		tag_extra(cpu, entries); /* tag extra entry points from the command line */

#ifdef RET_OPTIMIZATION
	find_rets(RAM, cpu->code_start, cpu->code_end);
#endif

	printf("*** Executing...\n");

#define STACK_SIZE 65536

	stack = (char *)(ramsize - STACK_SIZE); // THIS IS *GUEST* ADDRESS!

#define STACK ((long long)(stack+STACK_SIZE-4))

#define PC (((m88k_grf_t*)cpu->rf.grf)->sxip)
#define PSR (((m88k_grf_t*)cpu->rf.grf)->psr)
#define R (((m88k_grf_t*)cpu->rf.grf)->r)
#define X (((m88k_xrf_t*)cpu->rf.fpr)->x)

	PC = cpu->code_entry;
#if 0
	for (i = 1; i < 32; i++)
		R[i] = 0xF0000000 + i;	// DEBUG
#endif
	R[31] = STACK; // STACK
	R[1] = -1; // return address

#ifdef BENCHMARK_FIB//fib
	R[2] = start_no; // parameter
#else
	R[2] = 0x3f800000; // 1.0
	ieee754_fp80_set_d(&X[2], 1.0);
#endif
	dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, NULL);

#ifdef SINGLESTEP
	for(step = 0;;) {
		printf("::STEP:: %d\n", step++);

		cpu_run(cpu, debug_function);

		dump_state(RAM, (m88k_grf_t*)cpu->reg);
		printf ("NPC=%08x\n", PC);

		if (PC == -1)
			break;

		cpu_flush(cpu);
		printf("*** PRESS <ENTER> TO CONTINUE ***\n");
		getchar();
	}
#else
	for(;;) {
		int ret;
		breakpoint();
		ret = cpu_run(cpu, debug_function);
		printf("ret = %d\n", ret);
		switch (ret) {
			case JIT_RETURN_NOERR: /* JIT code wants us to end execution */
				break;
			case JIT_RETURN_FUNCNOTFOUND:
				dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, (m88k_xrf_t*)cpu->rf.frf);

				if (PC == (uint32_t)(-1))
					goto double_break;

				// bad :(
				printf("%s: error: $%llX not found!\n", __func__, (unsigned long long)PC);
				printf("PC: ");
				for (i = 0; i < 16; i++)
					printf("%02X ", RAM[PC+i]);
				printf("\n");
				exit(1);
			default:
				printf("unknown return code: %d\n", ret);
		}
	}
double_break:
#ifdef BENCHMARK_FIB
	printf("start_no=%u\n", start_no);

	printf("RUN1..."); fflush(stdout);
	PC = cpu->code_entry;

	for (i = 1; i < 32; i++)
		R[i] = 0xF0000000 + i;	// DEBUG

	R[31] = STACK; // STACK
	R[1] = -1; // return address

	R[2] = start_no; // parameter
	breakpoint();

	t1 = abs_time();
//	for (int i=0; i<TIMES; i++)
		cpu_run(cpu, debug_function);
	r1 = R[2];
	t2 = abs_time();

	printf("done!\n");

	dump_state(RAM, (m88k_grf_t*)cpu->rf.grf, NULL);

	printf("RUN2..."); fflush(stdout);
	t3 = abs_time();
//	for (int i=0; i<TIMES; i++)
		r2 = fib(start_no);
	t4 = abs_time();
	printf("done!\n");

	printf("%d -- %d\n", r1, r2);
	printf("%lld -- %lld\n", t2-t1, t4-t3);
	printf("%f%%\n",  (float)(t2-t1)/(float)(t4-t3));
#endif
#endif

	printf("done.\n");

	int base = 0x2000;
	for (int i=0; i<256; i+=4) {
		if (!(i%16))
			printf("\nDATA: ");
		printf("%08x ", *(unsigned int*)&RAM[(base+i)]);
	}
	printf("\n");

	return 0;
}
<|endoftext|>


<commit_before>//
//  yas_ui_collider.cpp
//

#include "yas_observing.h"
#include "yas_property.h"
#include "yas_to_bool.h"
#include "yas_ui_collider.h"

using namespace yas;

#pragma mark - shape

bool ui::anywhere_shape::hit_test(ui::point const &) const {
    return true;
}

bool ui::circle_shape::hit_test(ui::point const &pos) const {
    return std::powf(pos.x - center.x, 2.0f) + std::powf(pos.y - center.y, 2.0f) < std::powf(radius, 2.0f);
}

bool ui::rect_shape::hit_test(ui::point const &pos) const {
    return contains(rect, pos);
}

struct ui::shape::impl_base : base::impl {
    virtual std::type_info const &type() const = 0;
    virtual bool hit_test(ui::point const &) = 0;
};

template <typename T>
struct ui::shape::impl : impl_base {
    typename T::type _value;

    impl(typename T::type &&value) : _value(std::move(value)) {
    }

    std::type_info const &type() const override {
        return typeid(T);
    }

    bool hit_test(ui::point const &pos) override {
        return _value.hit_test(pos);
    }
};

ui::shape::shape(anywhere::type shape) : base(std::make_shared<impl<anywhere>>(std::move(shape))) {
}

ui::shape::shape(circle::type shape) : base(std::make_shared<impl<circle>>(std::move(shape))) {
}

ui::shape::shape(rect::type shape) : base(std::make_shared<impl<rect>>(std::move(shape))) {
}

ui::shape::shape(std::nullptr_t) : base(nullptr) {
}

ui::shape::~shape() = default;

std::type_info const &ui::shape::type_info() const {
    return impl_ptr<impl_base>()->type();
}

bool ui::shape::hit_test(ui::point const &pos) const {
    return impl_ptr<impl_base>()->hit_test(pos);
}

template <typename T>
typename T::type const &ui::shape::get() const {
    if (auto ip = std::dynamic_pointer_cast<impl<T>>(impl_ptr())) {
        return ip->_value;
    }

    static const typename T::type _default{};
    return _default;
}

template ui::anywhere_shape const &ui::shape::get<ui::shape::anywhere>() const;
template ui::circle_shape const &ui::shape::get<ui::shape::circle>() const;
template ui::rect_shape const &ui::shape::get<ui::shape::rect>() const;

#pragma mark - collider

struct ui::collider::impl : base::impl, renderable_collider::impl {
    property<ui::shape> _shape_property{{.value = nullptr}};
    property<bool> _enabled_property{{.value = true}};
    subject_t _subject;
    std::vector<base> _property_observers;

    impl(ui::shape &&shape) : _shape_property({.value = std::move(shape)}) {
        _property_observers.reserve(2);
    }

    void dispatch_method(ui::collider::method const method) {
        auto weak_collider = to_weak(cast<ui::collider>());

        base observer = nullptr;

        switch (method) {
            case ui::collider::method::shape_changed:
                observer = _shape_property.subject().make_observer(
                    property_method::did_change, [weak_collider](auto const &context) {
                        if (auto collider = weak_collider.lock()) {
                            collider.subject().notify(ui::collider::method::shape_changed, collider);
                        }
                    });
                break;
            case ui::collider::method::enabled_changed:
                observer = _enabled_property.subject().make_observer(
                    property_method::did_change, [weak_collider](auto const &context) {
                        if (auto collider = weak_collider.lock()) {
                            collider.subject().notify(ui::collider::method::enabled_changed, collider);
                        }
                    });
                break;
        }

        _property_observers.emplace_back(std::move(observer));
    }

    bool hit_test(ui::point const &loc) {
        auto const &shape = _shape_property.value();
        if (shape && _enabled_property.value()) {
            auto pos = simd::float4x4(matrix_invert(_matrix)) * to_float4(loc.v);
            return shape.hit_test({pos.x, pos.y});
        }
        return false;
    }

    simd::float4x4 const &matrix() const override {
        return _matrix;
    }

    void set_matrix(simd::float4x4 &&matrix) override {
        _matrix = std::move(matrix);
    }

   private:
    simd::float4x4 _matrix = matrix_identity_float4x4;
};

ui::collider::collider() : base(std::make_shared<impl>(nullptr)) {
}

ui::collider::collider(ui::shape shape) : base(std::make_shared<impl>(std::move(shape))) {
}

ui::collider::collider(std::nullptr_t) : base(nullptr) {
}

ui::collider::~collider() = default;

void ui::collider::set_shape(ui::shape shape) {
    impl_ptr<impl>()->_shape_property.set_value(std::move(shape));
}

ui::shape const &ui::collider::shape() const {
    return impl_ptr<impl>()->_shape_property.value();
}

void ui::collider::set_enabled(bool const enabled) {
    impl_ptr<impl>()->_enabled_property.set_value(enabled);
}

bool ui::collider::is_enabled() const {
    return impl_ptr<impl>()->_enabled_property.value();
}

bool ui::collider::hit_test(ui::point const &pos) const {
    return impl_ptr<impl>()->hit_test(pos);
}

ui::collider::subject_t &ui::collider::subject() {
    return impl_ptr<impl>()->_subject;
}

void ui::collider::dispatch_method(ui::collider::method const method) {
    impl_ptr<impl>()->dispatch_method(method);
}

ui::renderable_collider &ui::collider::renderable() {
    if (!_renderable) {
        _renderable = ui::renderable_collider{impl_ptr<ui::renderable_collider::impl>()};
    }
    return _renderable;
}
<commit_msg>update collider<commit_after>//
//  yas_ui_collider.cpp
//

#include "yas_observing.h"
#include "yas_property.h"
#include "yas_to_bool.h"
#include "yas_ui_collider.h"

using namespace yas;

#pragma mark - shape

bool ui::anywhere_shape::hit_test(ui::point const &) const {
    return true;
}

bool ui::circle_shape::hit_test(ui::point const &pos) const {
    return std::powf(pos.x - center.x, 2.0f) + std::powf(pos.y - center.y, 2.0f) < std::powf(radius, 2.0f);
}

bool ui::rect_shape::hit_test(ui::point const &pos) const {
    return contains(rect, pos);
}

struct ui::shape::impl_base : base::impl {
    virtual std::type_info const &type() const = 0;
    virtual bool hit_test(ui::point const &) = 0;
};

template <typename T>
struct ui::shape::impl : impl_base {
    typename T::type _value;

    impl(typename T::type &&value) : _value(std::move(value)) {
    }

    std::type_info const &type() const override {
        return typeid(T);
    }

    bool hit_test(ui::point const &pos) override {
        return _value.hit_test(pos);
    }
};

ui::shape::shape(anywhere::type shape) : base(std::make_shared<impl<anywhere>>(std::move(shape))) {
}

ui::shape::shape(circle::type shape) : base(std::make_shared<impl<circle>>(std::move(shape))) {
}

ui::shape::shape(rect::type shape) : base(std::make_shared<impl<rect>>(std::move(shape))) {
}

ui::shape::shape(std::nullptr_t) : base(nullptr) {
}

ui::shape::~shape() = default;

std::type_info const &ui::shape::type_info() const {
    return impl_ptr<impl_base>()->type();
}

bool ui::shape::hit_test(ui::point const &pos) const {
    return impl_ptr<impl_base>()->hit_test(pos);
}

template <typename T>
typename T::type const &ui::shape::get() const {
    if (auto ip = std::dynamic_pointer_cast<impl<T>>(impl_ptr())) {
        return ip->_value;
    }

    static const typename T::type _default{};
    return _default;
}

template ui::anywhere_shape const &ui::shape::get<ui::shape::anywhere>() const;
template ui::circle_shape const &ui::shape::get<ui::shape::circle>() const;
template ui::rect_shape const &ui::shape::get<ui::shape::rect>() const;

#pragma mark - collider

struct ui::collider::impl : base::impl, renderable_collider::impl {
    property<ui::shape> _shape_property{{.value = nullptr}};
    property<bool> _enabled_property{{.value = true}};
    subject_t _subject;

    impl(ui::shape &&shape) : _shape_property({.value = std::move(shape)}) {
        _property_observers.reserve(2);
    }

    void dispatch_method(ui::collider::method const method) {
        if (_property_observers.count(method)) {
            return;
        }

        auto weak_collider = to_weak(cast<ui::collider>());

        base observer = nullptr;

        switch (method) {
            case ui::collider::method::shape_changed:
                observer = _shape_property.subject().make_observer(
                    property_method::did_change, [weak_collider](auto const &context) {
                        if (auto collider = weak_collider.lock()) {
                            collider.subject().notify(ui::collider::method::shape_changed, collider);
                        }
                    });
                break;
            case ui::collider::method::enabled_changed:
                observer = _enabled_property.subject().make_observer(
                    property_method::did_change, [weak_collider](auto const &context) {
                        if (auto collider = weak_collider.lock()) {
                            collider.subject().notify(ui::collider::method::enabled_changed, collider);
                        }
                    });
                break;
        }

        _property_observers.emplace(std::make_pair(method, std::move(observer)));
    }

    bool hit_test(ui::point const &loc) {
        auto const &shape = _shape_property.value();
        if (shape && _enabled_property.value()) {
            auto pos = simd::float4x4(matrix_invert(_matrix)) * to_float4(loc.v);
            return shape.hit_test({pos.x, pos.y});
        }
        return false;
    }

    simd::float4x4 const &matrix() const override {
        return _matrix;
    }

    void set_matrix(simd::float4x4 &&matrix) override {
        _matrix = std::move(matrix);
    }

   private:
    simd::float4x4 _matrix = matrix_identity_float4x4;
    std::unordered_map<ui::collider::method, base> _property_observers;
};

ui::collider::collider() : base(std::make_shared<impl>(nullptr)) {
}

ui::collider::collider(ui::shape shape) : base(std::make_shared<impl>(std::move(shape))) {
}

ui::collider::collider(std::nullptr_t) : base(nullptr) {
}

ui::collider::~collider() = default;

void ui::collider::set_shape(ui::shape shape) {
    impl_ptr<impl>()->_shape_property.set_value(std::move(shape));
}

ui::shape const &ui::collider::shape() const {
    return impl_ptr<impl>()->_shape_property.value();
}

void ui::collider::set_enabled(bool const enabled) {
    impl_ptr<impl>()->_enabled_property.set_value(enabled);
}

bool ui::collider::is_enabled() const {
    return impl_ptr<impl>()->_enabled_property.value();
}

bool ui::collider::hit_test(ui::point const &pos) const {
    return impl_ptr<impl>()->hit_test(pos);
}

ui::collider::subject_t &ui::collider::subject() {
    return impl_ptr<impl>()->_subject;
}

void ui::collider::dispatch_method(ui::collider::method const method) {
    impl_ptr<impl>()->dispatch_method(method);
}

ui::renderable_collider &ui::collider::renderable() {
    if (!_renderable) {
        _renderable = ui::renderable_collider{impl_ptr<ui::renderable_collider::impl>()};
    }
    return _renderable;
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief staticThreadBlinker example application
 *
 * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/distortosConfiguration.h"

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

#include "distortos/board/leds.hpp"

#include "distortos/chip/ChipOutputPin.hpp"

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

namespace
{

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

/**
 * \brief LED blinking function
 *
 * Constantly toggles state of \a led and waits for half of \a periodMs.
 *
 * \param [in] led is a reference to distortos::devices::OutputPin object which will be toggled by this function
 * \param [in] periodMs is a full (on -> off -> on) period of toggling, milliseconds
 */

void ledBlinkerFunction(distortos::devices::OutputPin& led, const std::chrono::milliseconds periodMs)
{
	while (1)
	{
		led.set(!led.get());	// invert state of LED
		distortos::ThisThread::sleepFor(periodMs / 2);
	}
}

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

/**
 * \brief Boolean variable "blinking" function
 *
 * Constantly toggles value of \a variable and waits for half of \a periodMs. This function is meant as a demonstration
 * for configuration which either has no LEDs or doesn't enable them.
 *
 * \param [in] variable is a reference to bool variable which will be toggled by this function
 * \param [in] periodMs is a full (true -> false -> true) period of toggling, milliseconds
 */

void variableBlinkerFunction(bool& variable, const std::chrono::milliseconds periodMs)
{
	while (1)
	{
		variable = !variable;	// invert state of variable
		distortos::ThisThread::sleepFor(periodMs / 2);
	}
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Main code block of staticThreadBlinker application
 *
 * This example application tries to demonstrate the most basic aspects of static threads:
 * - creating and starting them,
 * - passing arguments to thread's function by reference and by value,
 * - joining them.
 *
 * If the configured board has no LEDs or if they are not enabled in the configuration, only one dummy thread is
 * created - it "blinks" a boolean variable instead of a real LED. Otherwise up to four additional threads are created
 * (but no more than the number of LEDs on the board - CONFIG_BOARD_TOTAL_LEDS) - each one blinks its own LED (which was
 * passed to the thread's function by reference) with provided period (passed by value). The periods of blinking are
 * slightly different for each thread, so if there are multiple LEDs they are not in sync with each other. The periods
 * are actually prime numbers, so they create very long "global" period (in which the whole pattern repeats).
 *
 * Even though all created threads never terminate (their functions have infinite loops and never return), main thread
 * calls Thread::join() for each of them anyway. This is a good and safe practice, which also happens to be the easiest
 * way to suspend main thread in this example application.
 *
 * \return doesn't return
 */

int main()
{
	bool variable {};
	// create and immediately start static thread with 1024 bytes of stack, low priority (1), variableBlinkerFunction()
	// will get variable by reference and period by value
	auto variableBlinkerThread = distortos::makeAndStartStaticThread<1024>(1, variableBlinkerFunction,
			std::ref(variable), std::chrono::milliseconds{401});

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

	// create and immediately start static thread with 1024 bytes of stack, low priority (1), ledBlinkerFunction() will
	// get its own LED by reference and period by value
	auto ledBlinkerThread0 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[0]), std::chrono::milliseconds{397});

#	if CONFIG_BOARD_TOTAL_LEDS >= 2

	auto ledBlinkerThread1 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[1]), std::chrono::milliseconds{389});

#		if CONFIG_BOARD_TOTAL_LEDS >= 3

	auto ledBlinkerThread2 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[2]), std::chrono::milliseconds{383});

#			if CONFIG_BOARD_TOTAL_LEDS >= 4

	auto ledBlinkerThread3 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[3]), std::chrono::milliseconds{379});

	ledBlinkerThread3.join();

#			endif	// CONFIG_BOARD_TOTAL_LEDS >= 4

	ledBlinkerThread2.join();

#		endif	// CONFIG_BOARD_TOTAL_LEDS >= 3

	ledBlinkerThread1.join();

#	endif	// CONFIG_BOARD_TOTAL_LEDS >= 2

	ledBlinkerThread0.join();

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

	variableBlinkerThread.join();

	return 0;
}
<commit_msg>Add "local functions" header in staticThreadBlinker.cpp<commit_after>/**
 * \file
 * \brief staticThreadBlinker example application
 *
 * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/distortosConfiguration.h"

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

#include "distortos/board/leds.hpp"

#include "distortos/chip/ChipOutputPin.hpp"

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

/**
 * \brief LED blinking function
 *
 * Constantly toggles state of \a led and waits for half of \a periodMs.
 *
 * \param [in] led is a reference to distortos::devices::OutputPin object which will be toggled by this function
 * \param [in] periodMs is a full (on -> off -> on) period of toggling, milliseconds
 */

void ledBlinkerFunction(distortos::devices::OutputPin& led, const std::chrono::milliseconds periodMs)
{
	while (1)
	{
		led.set(!led.get());	// invert state of LED
		distortos::ThisThread::sleepFor(periodMs / 2);
	}
}

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

/**
 * \brief Boolean variable "blinking" function
 *
 * Constantly toggles value of \a variable and waits for half of \a periodMs. This function is meant as a demonstration
 * for configuration which either has no LEDs or doesn't enable them.
 *
 * \param [in] variable is a reference to bool variable which will be toggled by this function
 * \param [in] periodMs is a full (true -> false -> true) period of toggling, milliseconds
 */

void variableBlinkerFunction(bool& variable, const std::chrono::milliseconds periodMs)
{
	while (1)
	{
		variable = !variable;	// invert state of variable
		distortos::ThisThread::sleepFor(periodMs / 2);
	}
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Main code block of staticThreadBlinker application
 *
 * This example application tries to demonstrate the most basic aspects of static threads:
 * - creating and starting them,
 * - passing arguments to thread's function by reference and by value,
 * - joining them.
 *
 * If the configured board has no LEDs or if they are not enabled in the configuration, only one dummy thread is
 * created - it "blinks" a boolean variable instead of a real LED. Otherwise up to four additional threads are created
 * (but no more than the number of LEDs on the board - CONFIG_BOARD_TOTAL_LEDS) - each one blinks its own LED (which was
 * passed to the thread's function by reference) with provided period (passed by value). The periods of blinking are
 * slightly different for each thread, so if there are multiple LEDs they are not in sync with each other. The periods
 * are actually prime numbers, so they create very long "global" period (in which the whole pattern repeats).
 *
 * Even though all created threads never terminate (their functions have infinite loops and never return), main thread
 * calls Thread::join() for each of them anyway. This is a good and safe practice, which also happens to be the easiest
 * way to suspend main thread in this example application.
 *
 * \return doesn't return
 */

int main()
{
	bool variable {};
	// create and immediately start static thread with 1024 bytes of stack, low priority (1), variableBlinkerFunction()
	// will get variable by reference and period by value
	auto variableBlinkerThread = distortos::makeAndStartStaticThread<1024>(1, variableBlinkerFunction,
			std::ref(variable), std::chrono::milliseconds{401});

#if defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

	// create and immediately start static thread with 1024 bytes of stack, low priority (1), ledBlinkerFunction() will
	// get its own LED by reference and period by value
	auto ledBlinkerThread0 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[0]), std::chrono::milliseconds{397});

#	if CONFIG_BOARD_TOTAL_LEDS >= 2

	auto ledBlinkerThread1 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[1]), std::chrono::milliseconds{389});

#		if CONFIG_BOARD_TOTAL_LEDS >= 3

	auto ledBlinkerThread2 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[2]), std::chrono::milliseconds{383});

#			if CONFIG_BOARD_TOTAL_LEDS >= 4

	auto ledBlinkerThread3 = distortos::makeAndStartStaticThread<1024>(1, ledBlinkerFunction,
			std::ref(distortos::board::leds[3]), std::chrono::milliseconds{379});

	ledBlinkerThread3.join();

#			endif	// CONFIG_BOARD_TOTAL_LEDS >= 4

	ledBlinkerThread2.join();

#		endif	// CONFIG_BOARD_TOTAL_LEDS >= 3

	ledBlinkerThread1.join();

#	endif	// CONFIG_BOARD_TOTAL_LEDS >= 2

	ledBlinkerThread0.join();

#endif	// defined(CONFIG_BOARD_LEDS_ENABLE) && CONFIG_BOARD_TOTAL_LEDS >= 1

	variableBlinkerThread.join();

	return 0;
}
<|endoftext|>


<commit_before>// This file is part of the "x0" project
//   (c) 2009-2014 Christian Parpart <trapni@gmail.com>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

/**
 * HTTP Server example for serving local static files.
 *
 * Highlights:
 *
 * This code has builtin support for:
 *

 *
 GET and HEAD requests

 *
 client cache aware response handling

 *
 Range requests

 *

 *
 */

#include <xzero/HttpRequest.h>
#include <xzero/HttpServer.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ev++.h>

int main() {
  xzero::HttpServer httpServer(ev::default_loop(0));
  httpServer.setupListener("0.0.0.0", 3000);

  char cwd[1024];
  if (!getcwd(cwd, sizeof(cwd))) {
    cwd[0] = '.';
    cwd[1] = '\0';
  }

  printf("Serving HTTP from 0.0.0.0:3000 ...\n");

  httpServer.requestHandler = [&](xzero::HttpRequest* r) {
    r->documentRoot = cwd;
    r->fileinfo = r->connection.worker().fileinfo(r->documentRoot + r->path);
    if (r->fileinfo) {
      r->sendfile(r->fileinfo);
    } else {
      r->status = xzero::HttpStatus::NotFound;
    }
    r->finish();
  };

  return httpServer.run();
}
<commit_msg>libxzero: improves staticfile example code quality<commit_after>// This file is part of the "x0" project
//   (c) 2009-2014 Christian Parpart <trapni@gmail.com>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

/**
 * HTTP Server example for serving local static files.
 *
 * Highlights:
 *
 * This code has builtin support for:
 *

 *
 GET and HEAD requests

 *
 client cache aware response handling

 *
 Range requests

 *

 *
 */

#include <xzero/HttpRequest.h>
#include <xzero/HttpServer.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ev++.h>

int main() {
  xzero::HttpServer httpServer(ev::default_loop(0));
  httpServer.setupListener("0.0.0.0", 3000);

  char cwd[1024];
  if (!getcwd(cwd, sizeof(cwd))) {
    cwd[0] = '.';
    cwd[1] = '\0';
  }

  printf("Serving HTTP from 0.0.0.0:3000 ...\n");

  httpServer.requestHandler = [&](xzero::HttpRequest* r) {
    r->documentRoot = cwd;
    r->fileinfo = r->connection.worker().fileinfo(r->documentRoot + r->path);
    r->sendfile(r->fileinfo);
    r->finish();
  };

  return httpServer.run();
}
<|endoftext|>