예제 #1
0
파일: app.cpp 프로젝트: FlibbleMr/neogfx
	bool app::process_events(i_event_processing_context&)
	{
		bool didSome = false;
		try
		{
			didSome = pump_messages();
			didSome = (do_io(neolib::yield_type::Sleep) || didSome);
			didSome = (do_process_events() || didSome);
			rendering_engine().render_now();
		}
		catch (std::exception& e)
		{
			if (!halted())
			{
				halt();
				std::cerr << "neogfx::app::process_events: terminating with exception: " << e.what() << std::endl;
				iSurfaceManager->display_error_message(iName.empty() ? "Abnormal Program Termination" : "Abnormal Program Termination - " + iName, std::string("neogfx::app::process_events: terminating with exception: ") + e.what());
				std::exit(EXIT_FAILURE);
			}
		}
		catch (...)
		{
			if (!halted())
			{
				halt();
				std::cerr << "neogfx::app::process_events: terminating with unknown exception" << std::endl;
				iSurfaceManager->display_error_message(iName.empty() ? "Abnormal Program Termination" : "Abnormal Program Termination - " + iName, "neogfx::app::process_events: terminating with unknown exception");
				std::exit(EXIT_FAILURE);
			}
		}
		return didSome;
	}
예제 #2
0
/// PerCycle
int
ClusterFunctional::PerCycle() {

  if (halted()) {
    return halted();
  }

  ccache->PerCycle(); 

  // HACK: clock the cores in rotating priority to avoid starvation (should not be any)
  // OK for FUNCTIONAL simulation, we are not limiting bandwidth or modelling contention
  int idx = rigel::CURR_CYCLE % numcores; 
  int halted_cores = 0;
  for (int offset = 0; offset < numcores; offset++) {
    halted_cores += cores[idx]->PerCycle();
    idx = (idx + 1) % numcores;
  }
  halted_ = halted_cores;

  if (halted()) {
    printf("all %d cores halted in cluster %d\n", numcores, id());
  }

  return halted();
};
예제 #3
0
/// called each cycle
/// update all owned components
int
TileNew::PerCycle() {

  if( halted() ) {
    return halted();
  }

  interconnect->PerCycle();

  int idx = rigel::CURR_CYCLE % rigel::CLUSTERS_PER_TILE; 

  int halted_clusters = 0;
  for (int offset = 0; offset < rigel::CLUSTERS_PER_TILE; offset++) {
    halted_clusters += clusters[idx]->PerCycle();
    idx = (idx + 1) % rigel::CLUSTERS_PER_TILE;
  }

  _halted = halted_clusters;

  return halted();

}
예제 #4
0
	bool io_thread::pump_messages()
	{
		bool didWork = false;
		while (have_messages())
		{
			if (halted())
				return didWork;
			if (have_message_queue())
			{
				message_queue().get_message();
				message_queue().idle();
			}
			didWork = true;
		}
		return didWork;
	}
예제 #5
0
unsigned long Memory::event(unsigned long cycleCounter) {
	if (lastOamDmaUpdate != DISABLED_TIME)
		updateOamDma(cycleCounter);

	switch (intreq.minEventId()) {
	case UNHALT:
		nontrivial_ff_write(0xFF04, 0, cycleCounter);
		PC = (PC + 1) & 0xFFFF;
		cycleCounter += 4;
		intreq.unhalt();
		intreq.setEventTime<UNHALT>(DISABLED_TIME);
		break;
	case END:
		intreq.setEventTime<END>(DISABLED_TIME - 1);

		while (cycleCounter >= intreq.minEventTime() && intreq.eventTime(END) != DISABLED_TIME)
			cycleCounter = event(cycleCounter);
		
		intreq.setEventTime<END>(DISABLED_TIME);

		break;
	case BLIT:
		{
			const bool lcden = ioamhram[0x140] >> 7 & 1;
			unsigned long blitTime = intreq.eventTime(BLIT);
			
			if (lcden | blanklcd) {
				display.updateScreen(blanklcd, cycleCounter);
				intreq.setEventTime<BLIT>(DISABLED_TIME);
				intreq.setEventTime<END>(DISABLED_TIME);
				
				while (cycleCounter >= intreq.minEventTime())
					cycleCounter = event(cycleCounter);
			} else
				blitTime += 70224 << isDoubleSpeed();
			
			blanklcd = lcden ^ 1;
			intreq.setEventTime<BLIT>(blitTime);
		}
		break;
	case SERIAL:
		updateSerial(cycleCounter);
		break;
	case OAM:
		intreq.setEventTime<OAM>(lastOamDmaUpdate == DISABLED_TIME ?
				static_cast<unsigned long>(DISABLED_TIME) : intreq.eventTime(OAM) + 0xA0 * 4);
		break;
	case DMA:
		{
			const bool doubleSpeed = isDoubleSpeed();
			unsigned dmaSrc = dmaSource;
			unsigned dmaDest = dmaDestination;
			unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10;
			unsigned length = hdmaReqFlagged(intreq) ? 0x10 : dmaLength;
			
			ackDmaReq(&intreq);

			if ((static_cast<unsigned long>(dmaDest) + length) & 0x10000) {
				length = 0x10000 - dmaDest;
				ioamhram[0x155] |= 0x80;
			}

			dmaLength -= length;

			if (!(ioamhram[0x140] & 0x80))
				dmaLength = 0;

			{
				unsigned long lOamDmaUpdate = lastOamDmaUpdate;
				lastOamDmaUpdate = DISABLED_TIME;

				while (length--) {
					const unsigned src = dmaSrc++ & 0xFFFF;
					const unsigned data = ((src & 0xE000) == 0x8000 || src > 0xFDFF) ? 0xFF : read(src, cycleCounter);

					cycleCounter += 2 << doubleSpeed;

					if (cycleCounter - 3 > lOamDmaUpdate) {
						oamDmaPos = (oamDmaPos + 1) & 0xFF;
						lOamDmaUpdate += 4;

						if (oamDmaPos < 0xA0) {
							if (oamDmaPos == 0)
								startOamDma(lOamDmaUpdate - 1);

							ioamhram[src & 0xFF] = data;
						} else if (oamDmaPos == 0xA0) {
							endOamDma(lOamDmaUpdate - 1);
							lOamDmaUpdate = DISABLED_TIME;
						}
					}

					nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cycleCounter);
				}

				lastOamDmaUpdate = lOamDmaUpdate;
			}

			cycleCounter += 4;

			dmaSource = dmaSrc;
			dmaDestination = dmaDest;
			ioamhram[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram[0x155] & 0x80);

			if ((ioamhram[0x155] & 0x80) && display.hdmaIsEnabled()) {
				if (lastOamDmaUpdate != DISABLED_TIME)
					updateOamDma(cycleCounter);
				
				display.disableHdma(cycleCounter);
			}
		}

		break;
	case TIMA:
		tima.doIrqEvent(TimaInterruptRequester(intreq));
		break;
	case VIDEO:
		display.update(cycleCounter);
		break;
	case INTERRUPTS:
		if (stopped) {
			intreq.setEventTime<INTERRUPTS>(DISABLED_TIME);
			break;
		}
		if (halted()) {
			if (gbIsCgb_ || (!gbIsCgb_ && cycleCounter <= halttime + 4))
				cycleCounter += 4;
			
			intreq.unhalt();
			intreq.setEventTime<UNHALT>(DISABLED_TIME);
		}
		
		if (ime()) {
			unsigned address;

			cycleCounter += 12;
			display.update(cycleCounter);
			SP = (SP - 2) & 0xFFFF;
			write(SP + 1, PC >> 8, cycleCounter);
			unsigned ie = intreq.iereg();

			cycleCounter += 4;
			display.update(cycleCounter);
			write(SP, PC & 0xFF, cycleCounter);
			const unsigned pendingIrqs = ie & intreq.ifreg();

			cycleCounter += 4;
			display.update(cycleCounter);
			const unsigned n = pendingIrqs & -pendingIrqs;
			
			if (n == 0) {
				address = 0;
			}
			else if (n < 8) {
				static const unsigned char lut[] = { 0x40, 0x48, 0x48, 0x50 };
				address = lut[n-1];
			} else
				address = 0x50 + n;
			
			intreq.ackIrq(n);
			PC = address;
		}
		
		break;
	}

	return cycleCounter;
}
예제 #6
0
void InterruptRequester::saveState(SaveState &state) const {
	state.mem.minIntTime = minIntTime;
	state.mem.IME = ime();
	state.mem.halted = halted();
}
예제 #7
0
파일: clock.cpp 프로젝트: Etrnls/etrnlabs
void Clock::trigger()
{
	if (!halt)	emit tick();
	if ((halt = newHalt))	emit halted();
}
예제 #8
0
unsigned long Memory::event(unsigned long cc) {
	if (lastOamDmaUpdate_ != disabled_time)
		updateOamDma(cc);

	switch (intreq_.minEventId()) {
	case intevent_unhalt:
		intreq_.unhalt();
		intreq_.setEventTime<intevent_unhalt>(disabled_time);
		break;
	case intevent_end:
		intreq_.setEventTime<intevent_end>(disabled_time - 1);

		while (cc >= intreq_.minEventTime()
				&& intreq_.eventTime(intevent_end) != disabled_time) {
			cc = event(cc);
		}

		intreq_.setEventTime<intevent_end>(disabled_time);

		break;
	case intevent_blit:
		{
			bool const lcden = ioamhram_[0x140] & lcdc_en;
			unsigned long blitTime = intreq_.eventTime(intevent_blit);

			if (lcden | blanklcd_) {
				lcd_.updateScreen(blanklcd_, cc);
				intreq_.setEventTime<intevent_blit>(disabled_time);
				intreq_.setEventTime<intevent_end>(disabled_time);

				while (cc >= intreq_.minEventTime())
					cc = event(cc);
			} else
				blitTime += 70224 << isDoubleSpeed();

			blanklcd_ = lcden ^ 1;
			intreq_.setEventTime<intevent_blit>(blitTime);
		}
		break;
	case intevent_serial:
		updateSerial(cc);
		break;
	case intevent_oam:
		intreq_.setEventTime<intevent_oam>(lastOamDmaUpdate_ == disabled_time
			? static_cast<unsigned long>(disabled_time)
			: intreq_.eventTime(intevent_oam) + 0xA0 * 4);
		break;
	case intevent_dma:
		{
			bool const doubleSpeed = isDoubleSpeed();
			unsigned dmaSrc = dmaSource_;
			unsigned dmaDest = dmaDestination_;
			unsigned dmaLength = ((ioamhram_[0x155] & 0x7F) + 0x1) * 0x10;
			unsigned length = hdmaReqFlagged(intreq_) ? 0x10 : dmaLength;

			ackDmaReq(intreq_);

			if ((static_cast<unsigned long>(dmaDest) + length) & 0x10000) {
				length = 0x10000 - dmaDest;
				ioamhram_[0x155] |= 0x80;
			}

			dmaLength -= length;

			if (!(ioamhram_[0x140] & lcdc_en))
				dmaLength = 0;

			{
				unsigned long lOamDmaUpdate = lastOamDmaUpdate_;
				lastOamDmaUpdate_ = disabled_time;

				while (length--) {
					unsigned const src = dmaSrc++ & 0xFFFF;
					unsigned const data = (src & 0xE000) == 0x8000 || src > 0xFDFF
					                    ? 0xFF
					                    : read(src, cc);

					cc += 2 << doubleSpeed;

					if (cc - 3 > lOamDmaUpdate) {
						oamDmaPos_ = (oamDmaPos_ + 1) & 0xFF;
						lOamDmaUpdate += 4;

						if (oamDmaPos_ < 0xA0) {
							if (oamDmaPos_ == 0)
								startOamDma(lOamDmaUpdate - 1);

							ioamhram_[src & 0xFF] = data;
						} else if (oamDmaPos_ == 0xA0) {
							endOamDma(lOamDmaUpdate - 1);
							lOamDmaUpdate = disabled_time;
						}
					}

					nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cc);
				}

				lastOamDmaUpdate_ = lOamDmaUpdate;
			}

			cc += 4;

			dmaSource_ = dmaSrc;
			dmaDestination_ = dmaDest;
			ioamhram_[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram_[0x155] & 0x80);

			if ((ioamhram_[0x155] & 0x80) && lcd_.hdmaIsEnabled()) {
				if (lastOamDmaUpdate_ != disabled_time)
					updateOamDma(cc);

				lcd_.disableHdma(cc);
			}
		}

		break;
	case intevent_tima:
		tima_.doIrqEvent(TimaInterruptRequester(intreq_));
		break;
	case intevent_video:
		lcd_.update(cc);
		break;
	case intevent_interrupts:
		if (halted()) {
			if (isCgb())
				cc += 4;

			intreq_.unhalt();
			intreq_.setEventTime<intevent_unhalt>(disabled_time);
		}

		if (ime()) {
			unsigned const pendingIrqs = intreq_.pendingIrqs();
			unsigned const n = pendingIrqs & -pendingIrqs;
			unsigned address;
			if (n <= 4) {
				static unsigned char const lut[] = { 0x40, 0x48, 0x48, 0x50 };
				address = lut[n-1];
			} else
				address = 0x50 + n;

			intreq_.ackIrq(n);
			cc = interrupter_.interrupt(address, cc, *this);
		}

		break;
	}

	return cc;
}