Exemplo n.º 1
0
bool FPU::OnCompletion(unsigned int unit, const Result& res) const
{
    const CycleNo now = GetKernel()->GetActiveClock()->GetCycleNo();

    Source *source = m_sources[res.source];

    if (source->m_last_write == now && source->m_last_unit != unit)
    {
        DeadlockWrite("Unable to write back result because another FPU pipe already wrote back this cycle");
        return false;
    }
    source->m_last_write = now;
    source->m_last_unit  = unit;

    // Calculate the address of this register
    RegAddr addr = res.address;
    addr.index += res.index;

    if (!source->client->CheckFPUOutputAvailability(addr))
    {
        DeadlockWrite("Client not ready to accept result");
        return false;
    }

    // Write new value
    unsigned int index = res.index;
#ifdef ARCH_BIG_ENDIAN
    const unsigned int size = res.size / sizeof(Integer);
    index = size - 1 - index;
#endif

    RegValue value;
    value.m_state         = RST_FULL;
    value.m_float.integer = (Integer)(res.value.toint(res.size) >> (sizeof(Integer) * 8 * index));

    if (!source->client->WriteFPUResult(addr, value))
    {
        DeadlockWrite("Unable to write result to %s", addr.str().c_str());
        return false;
    }

    DebugFPUWrite("unit %u completed %s %s <- %s",
                  (unsigned)unit,
                  source->client->GetName().c_str(),
                  addr.str().c_str(),
                  value.str(addr.type).c_str());
    return true;
}
Exemplo n.º 2
0
bool Processor::Network::WriteRegister(LFID fid, RemoteRegType kind, const RegAddr& raddr, const RegValue& value)
{
    RegAddr addr = m_allocator.GetRemoteRegisterAddress(fid, kind, raddr);
    if (addr != INVALID_REG)
    {
        // Write it
        if (!m_regFile.p_asyncW.Write(addr))
        {
            DeadlockWrite("Unable to acquire port to write register response to %s", addr.str().c_str());
            return false;
        }
                    
        if (!m_regFile.WriteRegister(addr, value, false))
        {
            DeadlockWrite("Unable to write register response to %s", addr.str().c_str());
            return false;
        }       

        DebugSimWrite("F%u write %s register %s (physical %s) <- %s",
                      (unsigned)fid,
                      GetRemoteRegisterTypeString(kind),
                      raddr.str().c_str(),
                      addr.str().c_str(), value.str(addr.type).c_str()
        );
    }
    return true;
}
Exemplo n.º 3
0
bool Processor::Network::ReadRegister(LFID fid, RemoteRegType kind, const RegAddr& raddr, RegValue& value)
{
    const RegAddr addr = m_allocator.GetRemoteRegisterAddress(fid, kind, raddr);
    assert(addr != INVALID_REG);

    // The thread of the register has been allocated, read it
    if (!m_regFile.p_asyncR.Read())
    {
        return false;
    }

    if (!m_regFile.ReadRegister(addr, value))
    {
        return false;
    }

    if (value.m_state != RST_FULL)
    {
        /*
         It's possible that the last shared in a family hasn't been written.
         Print a warning, and return a dummy value.
        */
        DebugProgWrite("F%u request for unwritten %s register %s (physical %s)",
            (unsigned)fid,
            GetRemoteRegisterTypeString(kind),
            raddr.str().c_str(),
            addr.str().c_str()
        );
            
        value.m_state = RST_FULL;
        switch (addr.type)
        {
        case RT_FLOAT:   value.m_float.fromfloat(0.0f); break;
        case RT_INTEGER: value.m_integer = 0; break;
        default: assert(0); // should not be here
        }
    }
    else
    {
        DebugSimWrite("F%u read %s register %s (physical %s) -> %s",
                      (unsigned)fid,
                      GetRemoteRegisterTypeString(kind),
                      raddr.str().c_str(),
                      addr.str().c_str(), value.str(addr.type).c_str()
        );
    }
    return true;
}
Exemplo n.º 4
0
void RegisterFile::Cmd_Read(std::ostream& out, const std::vector<std::string>& arguments) const
{
    // Need to change this if the RF is not directly child of parent
    auto& cpu = GetDRISC();

    // Find the RAUnit in the same processor
    auto& rau = cpu.GetRAUnit();

    RegType type = RT_INTEGER;
    size_t  ix    = 0;
    if (!arguments.empty())
    {
        if (arguments[ix] == "float") {
            type = RT_FLOAT;
            ix++;
        } else if (arguments[ix] == "integer") {
            // already initialized above
            ix++;
        }
    }
    auto& aliases = m_local_aliases[type];

    auto regs = rau.GetBlockInfo(type);

    set<RegIndex> indices;
    if (ix < arguments.size())
    {
        indices = parse_range<RegIndex>(arguments[ix], 0, regs.size());
    }
    else
    {
        // Default: add all registers that are part of a family
        for (size_t i = 0; i < regs.size(); i++)
        {
            if (regs[i] != INVALID_LFID)
            {
                indices.insert(i);
            }
        }
    }

    auto& alloc = GetDRISC().GetAllocator();

    out << "Phy   | Fam | Thread | Name/Alias | State / Value" << endl
        << "------+-----+--------+------------+--------------------------------" << endl;
    for (set<RegIndex>::const_reverse_iterator p = indices.rbegin(); p != indices.rend(); ++p)
    {
        RegAddr  addr = MAKE_REGADDR(type, *p);
        LFID     fid  = regs[*p];
        RegValue value;
        ReadRegister(addr, value, true);

        out << addr << " | ";

        if (fid != INVALID_LFID) out << "F" << setw(2) << setfill('0') << dec << fid; else out << "   ";

        out << " |  ";

        RegClass group = RC_LOCAL;
        size_t   rel   = 0;
        TID      tid   = (fid != INVALID_LFID) ? alloc.GetRegisterType(fid, addr, &group, &rel) : INVALID_TID;
        if (tid != INVALID_TID) {
            out << "T" << setw(4) << setfill('0') << tid;
        } else {
            out << "  -  ";
        }

        out << " | " << setfill(' ');

        char groupc = '\0';
        switch (group)
        {
        case RC_GLOBAL:    groupc = 'g'; break;
        case RC_DEPENDENT: groupc = 'd'; break;
        case RC_SHARED:    groupc = 's'; break;
        case RC_LOCAL:     groupc = 'l'; break;
        case RC_RAZ:       break;
        }

        if (tid != INVALID_TID)
        {
            if (type == RT_FLOAT)
                out << groupc << 'f' << setw(2) << left << rel << right;
            else
                out << ' ' << groupc << setw(2) << left << rel << right;
            out << ' ';
            if (group == RC_LOCAL && rel < aliases.size())
                out << setw(5) << aliases[rel];
            else
                out << "   - ";
        }
        else
            out << "  -     - ";

        out << " | "
            << value.str(type)
            << endl;
    }
}
Exemplo n.º 5
0
bool RegisterFile::WriteRegister(const RegAddr& addr, const RegValue& data, bool from_memory)
{
    auto& regs = m_files[addr.type];
    auto sz = m_sizes[addr.type];
    if (addr.index >= sz)
    {
        throw SimulationException("A component attempted to write to a non-existing register", *this);
    }

    assert(data.m_state == RST_EMPTY || data.m_state == RST_PENDING || data.m_state == RST_WAITING || data.m_state == RST_FULL);

    if (data.m_state == RST_EMPTY || data.m_state == RST_PENDING)
    {
        assert(data.m_waiting.head == INVALID_TID);
    }

    auto& value = regs[addr.index];
    if (value.m_state != RST_FULL)
    {
        if (value.m_state == RST_WAITING && data.m_state == RST_EMPTY)
        {
            throw exceptf<SimulationException>(*this, "Invalid reset of %s: %s becomes %s", addr.str().c_str(), value.str(addr.type).c_str(), data.str(addr.type).c_str());
        }

        if (value.m_memory.size != 0)
        {
            // Check that the memory information isn't changed
            if (data.m_state              == RST_FULL ||
                data.m_memory.fid         != value.m_memory.fid ||
                data.m_memory.offset      != value.m_memory.offset ||
                data.m_memory.size        != value.m_memory.size ||
                data.m_memory.sign_extend != value.m_memory.sign_extend ||
                data.m_memory.next        != value.m_memory.next)
            {
                if (!from_memory)
                {
                    // Only the memory can change memory-pending registers
                    throw exceptf<SimulationException>(*this, "Invalid reset of pending load %s: %s becomes %s", addr.str().c_str(), value.str(addr.type).c_str(), data.str(addr.type).c_str());
                }
            }
        }

        if (data.m_state == RST_FULL)
        {
            if (value.m_state == RST_WAITING && value.m_waiting.head != INVALID_TID)
            {
                // This write caused a reschedule
                auto& alloc = GetDRISC().GetAllocator();
                if (!alloc.ActivateThreads(value.m_waiting))
                {
                    DeadlockWrite("Unable to wake up threads after write of %s: %s becomes %s", addr.str().c_str(), value.str(addr.type).c_str(), data.str(addr.type).c_str());
                    return false;
                }
            }
        }
    }

    COMMIT
    {
#ifndef NDEBUG
        // Paranoid sanity check:
        // We cannot have multiple writes to same register in a cycle
        for (unsigned int i = 0; i < m_nUpdates; ++i)
        {
            assert(m_updates[i].first != addr);
        }
#endif

        // Queue the update
        assert(m_nUpdates < MAX_UPDATES);
        m_updates[m_nUpdates] = make_pair(addr, data);
        if (m_nUpdates == 0) {
            RegisterUpdate();
        }
        m_nUpdates++;
    }
    return true;
}
Exemplo n.º 6
0
Arquivo: FPU.cpp Projeto: koenk/mgsim
bool FPU::OnCompletion(unsigned int unit, const Result& res) const
{
    const CycleNo now = GetCycleNo();

    Source *source = m_sources[res.source];

    if (source->last_write == now && source->last_unit != unit)
    {
        DeadlockWrite("Unable to write back result because another FPU pipe already wrote back this cycle");
        return false;
    }
    source->last_write = now;
    source->last_unit  = unit;

    // Calculate the address of this register
    RegAddr addr = res.address;
    addr.index += res.index;

    if (!source->regfile->p_asyncW.Write(addr))
    {
        DeadlockWrite("Unable to acquire port to write back to %s", addr.str().c_str());
        return false;
    }

    // Read the old value
    RegValue value;
    if (!source->regfile->ReadRegister(addr, value))
    {
        DeadlockWrite("Unable to read register %s", addr.str().c_str());
        return false;
    }

    if (value.m_state != RST_PENDING && value.m_state != RST_WAITING)
    {
        // We're too fast, wait!
        DeadlockWrite("FP operation completed before register %s was cleared", addr.str().c_str());
        return false;
    }

    // Write new value
    unsigned int index = res.index;
#ifdef ARCH_BIG_ENDIAN
    const unsigned int size = res.size / sizeof(Integer);
    index = size - 1 - index;
#endif

    value.m_state         = RST_FULL;
    value.m_float.integer = (Integer)(res.value.toint(res.size) >> (sizeof(Integer) * 8 * index));

    if (!source->regfile->WriteRegister(addr, value, false))
    {
        DeadlockWrite("Unable to write register %s", addr.str().c_str());
        return false;
    }

    DebugFPUWrite("unit %u completed %s %s <- %s",
                  (unsigned)unit,
                  source->regfile->GetParent()->GetFQN().c_str(),
                  addr.str().c_str(),
                  value.str(addr.type).c_str());
    return true;
}