Esempio n. 1
0
/**
 * This is a microbenchmark to get cpu frequency the process is running on. The
 * returned value is used to convert TSC counter values to microseconds.
 *
 * @return int64.
 * @author cjiang
 */
static int64_t get_cpu_frequency() {
  struct timeval start;
  struct timeval end;

  if (gettimeofday(&start, 0)) {
    perror("gettimeofday");
    return 0.0;
  }
  uint64_t tsc_start = cpuCycles();
  uint64_t tsc_end;
  volatile int i;
  // Busy loop for 5 miliseconds. Don't use usleep() here since it causes the
  // CPU to halt which will generate meaningless results.
  do {
    for (i = 0; i < 1000000; i++);
    if (gettimeofday(&end, 0)) {
      perror("gettimeofday");
      return 0.0;
    }
    tsc_end = cpuCycles();
  } while (get_us_interval(&start, &end) < 5000);

  return nearbyint((tsc_end - tsc_start) * 1.0
                                   / (get_us_interval(&start, &end)));
}
Esempio n. 2
0
  virtual void endFrameEx(const TypedValue *retval,
                          const char *given_symbol) override {
    char symbol[512];
    HierarchicalProfilerFrame *frame =
      dynamic_cast<HierarchicalProfilerFrame *>(m_stack);
    frame->getStack(2, symbol, sizeof(symbol));
    CountMap &counts = m_stats[symbol];
    counts.count++;
    counts.wall_time += cpuCycles() - frame->m_tsc_start;

    if (m_flags & TrackCPU) {
      counts.cpu += cpuTime(m_MHz) - frame->m_vtsc_start;
    }

    if (m_flags & TrackMemory) {
      auto const& stats = MM().getStats();
      int64_t mu_end = stats.usage;
      int64_t pmu_end = stats.peakUsage;
      counts.memory += mu_end - frame->m_mu_start;
      counts.peak_memory += pmu_end - frame->m_pmu_start;
    } else if (m_flags & TrackMalloc) {
      counts.memory += get_allocs() - frame->m_mu_start;
      counts.peak_memory += get_frees() - frame->m_pmu_start;
    }
  }
Esempio n. 3
0
 virtual void endFrameEx(const TypedValue *retval,
                         const char *symbol) override {
   CountMap &counts = m_stats[m_stack->m_name];
   counts.count++;
   counts.tsc += cpuCycles() - m_stack->m_tsc_start;
   counts.vtsc += vtsc(m_MHz) - m_stack->m_vtsc_start;
 }
Esempio n. 4
0
/**
 * This is a microbenchmark to get cpu frequency the process is running on. The
 * returned value is used to convert TSC counter values to microseconds.
 *
 * @return int64.
 * @author cjiang
 */
static int64_t get_cpu_frequency() {
    struct timeval start;
    struct timeval end;

    if (gettimeofday(&start, 0)) {
        perror("gettimeofday");
        return 0.0;
    }
    uint64_t tsc_start = cpuCycles();
    // Sleep for 5 miliseconds. Comparaing with gettimeofday's  few microseconds
    // execution time, this should be enough.
    usleep(5000);
    if (gettimeofday(&end, 0)) {
        perror("gettimeofday");
        return 0.0;
    }
    uint64_t tsc_end = cpuCycles();
    return nearbyint((tsc_end - tsc_start) * 1.0
                     / (get_us_interval(&start, &end)));
}
Esempio n. 5
0
static uint32_t processInterrupt(uint32_t intMask, uint16_t npc, uint32_t startTime, int32_t cycleLimit) {
	// known limitation: if the code uses ROM routines calculation is flawed (see mock-up ROM routines).
	uint16_t originalDigiCount= digiGetCount();
	uint16_t originalDigiOverflowCount= digiGetOverflowCount();
	
	sidResetVolumeChangeCount();
	
	if (isPsidDummyIrqVector()) {
		// no point in trying to keep the stack consistent for a PSID
		cpuRegReset();
	}

	cpuResetToIrq(npc);
	cpuSetProgramMode(intMask);
	
	initCycleCount(intMask, startTime);
	
	if (intMask == IRQ_OFFSET_MASK)	{
		vicSyncRasterIRQ();
		
		// FIXME the cpu interrupt flag should also be set before starting the interrupt handler!
		// but since no one seems to have missed it yet..
	}
	
    while (cpuPcIsValid() && ((cycleLimit <0) || (cpuCycles() <cycleLimit))) {
		vicSimRasterline();
        cpuParse();
	}
	cpuSetProgramMode(MAIN_OFFSET_MASK);
	
	digiTagOrigin(intMask, startTime, originalDigiCount, originalDigiOverflowCount);		
	
	if (intMask == IRQ_OFFSET_MASK) _volUpdates+= sidGetNumberOfVolumeChanges();	// number of updates to the volume	
	
	return cpuCycles();
}
Esempio n. 6
0
  virtual void beginFrameEx(const char *symbol) override {
    m_stack->m_tsc_start = cpuCycles();

    if (m_flags & TrackCPU) {
      m_stack->m_vtsc_start = cpuTime(m_MHz);
    }

    if (m_flags & TrackMemory) {
      auto const& stats = MM().getStats();
      m_stack->m_mu_start  = stats.usage;
      m_stack->m_pmu_start = stats.peakUsage;
    } else if (m_flags & TrackMalloc) {
      m_stack->m_mu_start = get_allocs();
      m_stack->m_pmu_start = get_frees();
    }
  }
Esempio n. 7
0
/*
 * handle a potentially endless running main program (e.g. started from "init_addr").
 * @param npc 			0 means that interrupted main program is continued (whereever it was)
 * @param cycleLimit	limit the number of available CPU cycles before the processing stops
 * @return 				0= run to completion; 1= interrupted by cyclelimit or due to number of produced digi samples
 */
static uint8_t callMain(uint16_t npc, uint8_t na, uint32_t startTime, int32_t cycleLimit) {

	/*
		the way how the sequence of main and INT calls is scheduled is obviously incorrect, and
		the logic below tries to at least workaround (which does not always work) some the flaws.
		the problems arise when:
				
		scenario 1: main program is interrupted by some INT and when it later resumes it expects to
                    continue with the register content it had at the time of the interrupt (why
					is special handling needed here: any well behaved INT would perform that cleanup
					anyway.. but various songs do seem to benefit from a respective hack.. see 
					comment in cpuRegSave)	

		scenario 2: supposing a chain of INTs does not expect any interference from MAIN and registers
					are just passed on from one INT call to the next (see Jevers_Bannys_and_the_Master_Mixers.sid):
					a main call should then under no circumstances mess with the registers... (caution: doing
					too much here will harm songs like: Storebror.sid, Wonderland XII part1.sid, Comalight 13 tune4.sid)
	*/
	
	initCycleCount(0, startTime); // use new timestamps for potential digi-samples & cycleLimit check

	if (npc == 0) cpuRegSave(1, 1);

	if (npc == 0) {
		cpuRegRestore(0,0);
	} else {
		cpuReset(npc, na);	// sid init call: with 'start addr' and 'seleced track' in acc
	}
    while (cpuPcIsValid()) {
		// if a main progs is already producing samples then it is done with the "init" phase and
		// we interrupt it when we have enough samples for one screen (see Suicide_Express.sid)

		if (((cycleLimit >0) && (cpuCycles() >=cycleLimit)) || (digiGetOverflowCount() >0)) {	
			cpuRegSave(0,0);
			
			if (npc == 0) cpuRegRestore(1, 1);
			return 1;
		}		
		vicSimRasterline();
		cpuParse();
	}
	
	if (npc == 0) cpuRegRestore(1, 1);
	return 0;
}
Esempio n. 8
0
  virtual void beginFrameEx(const char *symbol) override {
    HierarchicalProfilerFrame *frame =
      dynamic_cast<HierarchicalProfilerFrame *>(m_stack);
    frame->m_tsc_start = cpuCycles();

    if (m_flags & TrackCPU) {
      frame->m_vtsc_start = cpuTime(m_MHz);
    }

    if (m_flags & TrackMemory) {
      auto const& stats = MM().getStats();
      frame->m_mu_start  = stats.usage;
      frame->m_pmu_start = stats.peakUsage;
    } else if (m_flags & TrackMalloc) {
      frame->m_mu_start = get_allocs();
      frame->m_pmu_start = get_frees();
    }
  }
Esempio n. 9
0
 virtual void beginFrameEx(const char *symbol) override {
   m_stack->m_tsc_start = cpuCycles();
   m_stack->m_vtsc_start = vtsc(m_MHz);
 }