Example #1
0
    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.
            }
Example #2
0
File: Node.cpp Project: koenk/mgsim
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;
}
Example #3
0
    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;
    }
Example #4
0
 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;
 }
Example #5
0
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;
}
Example #6
0
    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;
    }
Example #7
0
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)