Result IODirectCacheAccess::DoBusOutgoing() { const Response& res = m_responses.Front(); if (!p_service.Invoke()) { DeadlockWrite("Unable to acquire port for DCA read response (%#016llx, %u)", (unsigned long long)res.address, (unsigned)res.size); return FAILED; } if (res.address == 0 && res.size == 0) { // write response assert(m_pending_writes > 0); if (m_pending_writes == 1 && m_flushing == true) { COMMIT { --m_pending_writes; m_flushing = false; } // the flush response will be sent below. }
Result ZLCOMA::Node::DoForward() { // Forward requests to the next node assert(!m_outgoing.Empty()); assert(m_next != NULL); if (!m_next->m_incoming.Push( m_outgoing.Front() )) { DeadlockWrite("Unable to send request to next node"); return FAILED; } m_outgoing.Pop(); return SUCCESS; }
Result IOBusInterface::DoOutgoingRequests() { assert(!m_outgoing_reqs.Empty()); const IORequest& req = m_outgoing_reqs.Front(); switch(req.type) { case REQ_WRITE: if (!m_iobus.SendWriteRequest(m_hostid, req.device, req.address, req.data)) { DeadlockWrite("Unable to send I/O write request to %u:%016llx (%u)", (unsigned)req.device, (unsigned long long)req.address, (unsigned)req.data.size); return FAILED; } break; case REQ_READ: if (!m_iobus.SendReadRequest(m_hostid, req.device, req.address, req.data.size)) { DeadlockWrite("Unable to send I/O read request to %u:%016llx (%u)", (unsigned)req.device, (unsigned long long)req.address, (unsigned)req.data.size); return FAILED; } break; case REQ_READRESPONSE: if (!m_iobus.SendReadResponse(m_hostid, req.device, req.address, req.data)) { DeadlockWrite("Unable to send DCA read response to %u:%016llx (%u)", (unsigned)req.device, (unsigned long long)req.address, (unsigned)req.data.size); return FAILED; } break; }; m_outgoing_reqs.Pop(); return SUCCESS; }
bool IODirectCacheAccess::OnMemoryWriteCompleted(TID tid) { if (tid == INVALID_TID) // otherwise for D-Cache { Response res; res.address = 0; res.size = 0; if (!m_responses.Push(res)) { DeadlockWrite("Unable to push memory write response"); return false; } } return true; }
Result CDMA::Node::DoForward() { // Forward requests to the next node assert(!m_outgoing.Empty()); assert(m_next != NULL); TraceWrite(m_outgoing.Front()->address, "Sending %s to %s", m_outgoing.Front()->str().c_str(), m_next->GetFQN().c_str()); if (!m_next->m_incoming.Push( m_outgoing.Front() )) { DeadlockWrite("Unable to send request to next node (%s)", m_next->GetFQN().c_str()); return FAILED; } m_outgoing.Pop(); return SUCCESS; }
bool IODirectCacheAccess::OnMemoryReadCompleted(MemAddr addr, const char * data) { assert(addr % m_lineSize == 0); Response res; res.address = addr; res.size = m_lineSize; std::copy(data, data + m_lineSize, res.data); if (!m_responses.Push(res)) { DeadlockWrite("Unable to push memory read response (%#016llx)", (unsigned long long)addr); return false; } return true; }
Processor::Pipeline::PipeAction Processor::Pipeline::WritebackStage::OnCycle() { int writebackOffset = m_writebackOffset; int size = -1; bool allow_reschedule = true; bool suspend = (m_input.suspend != SUSPEND_NONE); if (m_stall) { // We need to stall this cycle without doing *anything*. // Since we stall, we never commit. if (!IsAcquiring()) { m_stall = false; } return PIPE_STALL; } if (m_input.Rrc.type != RemoteMessage::MSG_NONE) { // Network activity if (!m_network.SendMessage(m_input.Rrc)) { DeadlockWrite("Unable to send network message"); return PIPE_STALL; } DebugPipeWrite("F%u/T%u(%llu) %s sent network message %s", (unsigned)m_input.fid, (unsigned)m_input.tid, (unsigned long long)m_input.logical_index, m_input.pc_sym, m_input.Rrc.str().c_str()); } if (m_input.Rcv.m_state != RST_INVALID) { // We have something to write back assert(m_input.Rcv.m_size % sizeof(Integer) == 0); size = m_input.Rcv.m_size / sizeof(Integer); if (writebackOffset == -1) { // New data write writebackOffset = 0; } if (writebackOffset < size) { // Take data from input RegValue value = MAKE_EMPTY_REG(); value.m_state = m_input.Rcv.m_state; switch (value.m_state) { case RST_PENDING: case RST_WAITING: case RST_EMPTY: if (writebackOffset == 0) { // Store the thread and memory information in the first register only value.m_waiting = m_input.Rcv.m_waiting; value.m_memory = m_input.Rcv.m_memory; } break; case RST_FULL: { // Compose register value unsigned int index = writebackOffset; #ifdef ARCH_BIG_ENDIAN index = size - 1 - index; #endif const unsigned int shift = index * 8 * sizeof(Integer); switch (m_input.Rc.type) { case RT_INTEGER: value.m_integer = (Integer)(m_input.Rcv.m_integer.get(m_input.Rcv.m_size) >> shift); break; case RT_FLOAT: value.m_float.integer = (Integer)(m_input.Rcv.m_float.toint(m_input.Rcv.m_size) >> shift); break; } break; } default: // These states are never written from the pipeline UNREACHABLE; } if (m_input.Rc.valid()) { // Get the address of the register we're writing. const RegAddr addr = MAKE_REGADDR(m_input.Rc.type, m_input.Rc.index + writebackOffset); // We have something to write back if (!m_regFile.p_pipelineW.Write(addr)) { DeadlockWrite("F%u/T%u(%llu) %s unable to acquire write port on RF", (unsigned)m_input.fid, (unsigned)m_input.tid, (unsigned long long)m_input.logical_index, m_input.pc_sym); return PIPE_STALL; } // Read the old value RegValue old_value; if (!m_regFile.ReadRegister(addr, old_value)) { DeadlockWrite("F%u/T%u(%llu) %s unable to read prev %s", (unsigned)m_input.fid, (unsigned)m_input.tid, (unsigned long long)m_input.logical_index, m_input.pc_sym, addr.str().c_str()); return PIPE_STALL; } if (value.m_state == RST_WAITING) { assert(suspend == true); if (old_value.m_state == RST_FULL) { // The data we wanted to wait for has returned before we could write the register. // Just reschedule the thread. suspend = false; value.m_state = RST_INVALID; DebugPipeWrite("F%u/T%u(%llu) %s data arrived in %s since read, rescheduling", (unsigned)m_input.fid, (unsigned)m_input.tid, (unsigned long long)m_input.logical_index, m_input.pc_sym, addr.str().c_str()); } else { assert(value.m_waiting.head == m_input.tid); // The Read Stage will have setup the register to // link this thread into the register's thread waiting list if (old_value.m_state == RST_WAITING && old_value.m_waiting.head != INVALID_TID) { // Not the first thread waiting on the register // Update the tail assert(value.m_waiting.tail == old_value.m_waiting.tail); } else { assert(value.m_waiting.tail == m_input.tid); } COMMIT { // We're suspending because we're waiting on a non-full register. // Since we support multiple threads waiting on a register, update the // next field in the thread table to the next waiting thread. m_threadTable[m_input.tid].next = old_value.m_waiting.head; } } } else if (value.m_state == RST_PENDING && old_value.m_state == RST_WAITING)