<commit_before>#include "Directory.h"
#include "sim/config.h"
#include <cassert>
#include <cstring>
#include <cstdio>
#include <iomanip>
using namespace std;

namespace Simulator
{

// When we shortcut a message over the ring, we want at least one slots
// available in the buffer to avoid deadlocking the ring network. This
// is not necessary for forwarding messages onto the lower ring.
static const size_t MINSPACE_SHORTCUT = 2;
static const size_t MINSPACE_FORWARD  = 1;

COMA::DirectoryTop::DirectoryTop(const std::string& name, COMA& parent, Clock& clock, Config& config)
    : Simulator::Object(name, parent),
    Node(name, parent, clock, config)
{
}

COMA::DirectoryBottom::DirectoryBottom(const std::string& name, COMA& parent, Clock& clock, Config& config)
    : Simulator::Object(name, parent),
    Node(name, parent, clock, config)
{
}

bool COMA::Directory::IsBelow(CacheID id) const
{
    return (id >= m_firstCache) && (id <= m_lastCache);
}

// Performs a lookup in this directory's table to see whether
// the wanted address exists in the ring below this directory.
COMA::Directory::Line* COMA::Directory::FindLine(MemAddr address)
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        Line* line = &m_lines[set + i];
        if (line->valid && line->tag == tag)
        {
            return line;
        }
    }
    return NULL;
}

// Performs a lookup in this directory's table to see whether
// the wanted address exists in the ring below this directory.
const COMA::Directory::Line* COMA::Directory::FindLine(MemAddr address) const
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        const Line* line = &m_lines[set + i];
        if (line->valid && line->tag == tag)
        {
            return line;
        }
    }
    return NULL;
}

// Marks the specified address as present in the directory
COMA::Directory::Line* COMA::Directory::AllocateLine(MemAddr address)
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        Line* line = &m_lines[set + i];
        if (!line->valid)
        {
            COMMIT
            {                
                line->valid  = true;
                line->tag    = tag;
                line->tokens = 0;
            }
            return line;
        }
    }
    assert(false);
    return NULL;
}

bool COMA::Directory::OnMessageReceivedBottom(Message* msg)
{
#if 1 /* set to 0 to attempt to flatten the COMA ring, ie remove the shortcut across (DEBUG FEATURE ONLY) */

    // We need to grab p_line because it arbitrates access to the outgoing
    // buffer on the top ring as well.
    if (!p_lines.Invoke())
    {
        DeadlockWrite("Unable to get access to lines");
        return false;
    }

    if (!msg->ignore)
    {    
        switch (msg->type)
        {
        case Message::EVICTION:
            // Evictions always come from below since they do not go down into a ring.
            // (Except for deadlock avoidance, but then the ignore flag is set).
            assert(IsBelow(msg->sender));
            
        case Message::REQUEST_DATA_TOKEN:
        {
            // Reduce the token count in the dir line
            Line* line = FindLine(msg->address);
            assert(line != NULL);
            assert(line->tokens >= msg->tokens);
            
            COMMIT
            {
                line->tokens -= msg->tokens;
                if (line->tokens == 0)
                {
                    // No more tokens left; clear the line too
                    line->valid = false;
                }
            }
            break;
        }
            
        case Message::REQUEST:
        case Message::REQUEST_DATA:
        case Message::UPDATE:
            break;
            
        default:
            assert(false);
            break;
        }
    }
    
    // We can stop ignoring it now
    COMMIT{ msg->ignore = false; }
#endif
    
    // Put the message on the higher-level ring
    if (!m_top.SendMessage(msg, MINSPACE_FORWARD))
    {
        DeadlockWrite("Unable to buffer request for next node on top ring");
        return false;
    }

    return true;
}

bool COMA::Directory::OnMessageReceivedTop(Message* msg)
{
#if 0
    if (!p_lines.Invoke())
    {
        DeadlockWrite("Unable to get access to lines");
        return false;
    }
    
    // See if a cache below this directory has the line
    Line* line = NULL;
    switch (msg->type)
    {
    case Message::REQUEST:
    case Message::REQUEST_DATA:
    case Message::UPDATE:
        line = FindLine(msg->address);
        break;
<commit_msg>Complement to previous commit 'Cancel a recent change to the COMA protocol intended for debug only.'<commit_after>#include "Directory.h"
#include "sim/config.h"
#include <cassert>
#include <cstring>
#include <cstdio>
#include <iomanip>
using namespace std;

namespace Simulator
{

// When we shortcut a message over the ring, we want at least one slots
// available in the buffer to avoid deadlocking the ring network. This
// is not necessary for forwarding messages onto the lower ring.
static const size_t MINSPACE_SHORTCUT = 2;
static const size_t MINSPACE_FORWARD  = 1;

COMA::DirectoryTop::DirectoryTop(const std::string& name, COMA& parent, Clock& clock, Config& config)
    : Simulator::Object(name, parent),
    Node(name, parent, clock, config)
{
}

COMA::DirectoryBottom::DirectoryBottom(const std::string& name, COMA& parent, Clock& clock, Config& config)
    : Simulator::Object(name, parent),
    Node(name, parent, clock, config)
{
}

bool COMA::Directory::IsBelow(CacheID id) const
{
    return (id >= m_firstCache) && (id <= m_lastCache);
}

// Performs a lookup in this directory's table to see whether
// the wanted address exists in the ring below this directory.
COMA::Directory::Line* COMA::Directory::FindLine(MemAddr address)
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        Line* line = &m_lines[set + i];
        if (line->valid && line->tag == tag)
        {
            return line;
        }
    }
    return NULL;
}

// Performs a lookup in this directory's table to see whether
// the wanted address exists in the ring below this directory.
const COMA::Directory::Line* COMA::Directory::FindLine(MemAddr address) const
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        const Line* line = &m_lines[set + i];
        if (line->valid && line->tag == tag)
        {
            return line;
        }
    }
    return NULL;
}

// Marks the specified address as present in the directory
COMA::Directory::Line* COMA::Directory::AllocateLine(MemAddr address)
{
    MemAddr tag;
    size_t setindex;
    m_selector.Map(address / m_lineSize, tag, setindex);
    const size_t  set  = setindex * m_assoc;

    // Find the line
    for (size_t i = 0; i < m_assoc; ++i)
    {
        Line* line = &m_lines[set + i];
        if (!line->valid)
        {
            COMMIT
            {                
                line->valid  = true;
                line->tag    = tag;
                line->tokens = 0;
            }
            return line;
        }
    }
    assert(false);
    return NULL;
}

bool COMA::Directory::OnMessageReceivedBottom(Message* msg)
{
#if 1 /* set to 0 to attempt to flatten the COMA ring, ie remove the shortcut across (DEBUG FEATURE ONLY) -- also check below */

    // We need to grab p_line because it arbitrates access to the outgoing
    // buffer on the top ring as well.
    if (!p_lines.Invoke())
    {
        DeadlockWrite("Unable to get access to lines");
        return false;
    }

    if (!msg->ignore)
    {    
        switch (msg->type)
        {
        case Message::EVICTION:
            // Evictions always come from below since they do not go down into a ring.
            // (Except for deadlock avoidance, but then the ignore flag is set).
            assert(IsBelow(msg->sender));
            
        case Message::REQUEST_DATA_TOKEN:
        {
            // Reduce the token count in the dir line
            Line* line = FindLine(msg->address);
            assert(line != NULL);
            assert(line->tokens >= msg->tokens);
            
            COMMIT
            {
                line->tokens -= msg->tokens;
                if (line->tokens == 0)
                {
                    // No more tokens left; clear the line too
                    line->valid = false;
                }
            }
            break;
        }
            
        case Message::REQUEST:
        case Message::REQUEST_DATA:
        case Message::UPDATE:
            break;
            
        default:
            assert(false);
            break;
        }
    }
    
    // We can stop ignoring it now
    COMMIT{ msg->ignore = false; }
#endif
    
    // Put the message on the higher-level ring
    if (!m_top.SendMessage(msg, MINSPACE_FORWARD))
    {
        DeadlockWrite("Unable to buffer request for next node on top ring");
        return false;
    }

    return true;
}

bool COMA::Directory::OnMessageReceivedTop(Message* msg)
{
#if 1 /* set to 0 to attempt to flatten the COMA ring, ie remove the shortcut across (DEBUG FEATURE ONLY) -- also check above */
    if (!p_lines.Invoke())
    {
        DeadlockWrite("Unable to get access to lines");
        return false;
    }
    
    // See if a cache below this directory has the line
    Line* line = NULL;
    switch (msg->type)
    {
    case Message::REQUEST:
    case Message::REQUEST_DATA:
    case Message::UPDATE:
        line = FindLine(msg->address);
        break;

{'fraction_non_alphanumeric': 0.10430044755789064, 'fraction_numerical': 0.0020431990659661413, 'mean_word_length': 2.0528660528660527, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5972584', 'n_tokens_mistral': 3073, 'n_tokens_neox': 2991, 'n_words': 987}