OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_c/] [synfull/] [pronoc-interface/] [src/] [dpi_interface.cpp] - Rev 54

Compare with Previous | Blame | View Log

#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include "socketstream.h"
#include "messages.h"
#include "svdpi.h"
#include "dpi_interface.hpp"
 
 
extern "C" void connection_init ( 
        svLogic startCom, svLogic *ready
        )
{
 
    if ( startCom == 1 )
    {
        _connection_manager = new connection_manager;
        rp = new RequestPacket();
        _connection_manager->Init();
        *ready = '1';
    }
 
}
 
extern "C" void c_dpi_interface ( 
        svLogic startCom, svLogic getData, svLogic ejectReq,  svLogic queueReq, svLogic *endCom, 
        svLogic *newReq, svBitVec32 source_all[NE], svBitVec32 destination_all[NE], 
        svBitVec32 address_all[NE], svBitVec32 opcode_all[NE], svBitVec32 id_all[NE], 
        svBitVec32 valid_all[NE], svBitVec32 rtrn_pkgid_all[NE], 
        svBitVec32 rtrn_valid_all[NE], svBitVec32 NEready_all[NE], 
        svBitVec32 size_all[NE] ,
        svBitVec32 enqueue_valid[NE]   ,
        svBitVec32 enqueue_src[NE]     ,
        svBitVec32 enqueue_dst[NE]     ,
        svBitVec32 enqueue_id[NE]      ,
        svBitVec32 enqueue_size[NE]                      
        )
{
 
    bool process_more = true;
    int msgDone = 0;
    *endCom = '0'; 
    *newReq = '0';
    int noreq=0;
    int node_dst;
    int node_src;
    int toDataPort=0;
    int toRspPort=0;
    int id_cnt=0;
 
    int rtrn_valid_all_[NE];    
    int _enqueue_valid[NE] ;
 
    for(int i=0; i<NE; i++) {
        valid_all[i] = 0;
        rtrn_valid_all_[i] = rtrn_valid_all[i];
        _enqueue_valid[i] = enqueue_valid[i];
    }
 
 
    if (startCom == 1 && getData == 1) 
    {
        //cout << "\n*** new clock *** " << endl
 
 
        while ( process_more )
        {
            // read message
            _connection_manager->readMsg();
 
 
            switch(_msg->type)
            { 
                case STEP_REQ: //2
                    {
                        StepResMsg res;
                        *_channel << res;
 
                        if (queueReq == 1)
                        {
                            // enqueue packets from pronoc
                            for(int k=0; k<NE; k++)
                            {
                                if (_enqueue_valid[k] == 1){
                                    _req->size    = enqueue_size[k];
                                    _req->dest    = enqueue_dst[k];
                                    _req->source  = enqueue_src[k];
                                    _req->id      = enqueue_id[k];
 
                                    if (_inject_buffer.empty()) 
                                    {
                                        _inject_buffer.push(_req);
                                        //cout << "<enqueue> id: " << _req->id << endl;
                                    }
                                    else
                                    {
                                        int quesize = _inject_buffer.size();
                                        for(int i=0;i<quesize;i++)
                                        {
                                            _req_tmp = _inject_buffer.front();
                                            _inject_buffer.pop();
                                            if ( _req->id == _req_tmp->id ) id_cnt++;
                                            _inject_buffer.push(_req_tmp);
                                        }
                                        if(id_cnt == 0)
                                        {
                                            _inject_buffer.push(_req);
                                            //cout << "<enqueue> id: " << _req->id << endl;
                                        }
                                        id_cnt=0;
                                    }
                                    _enqueue_valid[k] = 0;
                                }
                            }
                        }
 
                        //dequeue packets to send to pronoc
                        if (!_inject_buffer.empty()) {
                            int quesize = _inject_buffer.size();
 
                            for(int i=0;i<quesize;i++){
                                _req = _inject_buffer.front();
                                _inject_buffer.pop();
 
                                if(NEready_all[_req->source] == 1 & valid_all[_req->source] == 0)
                                {
                                    address_all[_req->source]     = _req->address     ;
                                    size_all[_req->source]        = _req->packetSize  ;
                                    destination_all[_req->source] = _req->dest        ;
                                    source_all[_req->source]      = _req->source      ;
                                    opcode_all[_req->source]      = _req->coType      ;
                                    id_all[_req->source]          = _req->id          ;
                                    valid_all[_req->source]       = 1                 ;
                                    //cout << "<inject> id: " << _req->id << " src: " << _req->source << " dst: " << _req->dest << " size: " << _req->size << endl;
                                }
                                else
                                {
                                    _inject_buffer.push(_req);
                                    //cout << "<wait> id: " << _req->id << endl;
                                }
 
                            }
                        }
                        //cout << "<end cycle>" << endl;
 
                        // fall-through and increment your network one cycle
                        process_more = false;
 
                       break;
                    }
                case INJECT_REQ: //4
                    {
                        _req = (InjectReqMsg*) _msg;
                        _connection_manager->sendAckReqMsg(); 
                        noreq = 0;
 
                            //enqueue packets from synfull
                            _inject_buffer.push(_req);
 
                        //cout << "<inject> id:" << _req->id << " mt:" << _req->msgType << " ct:" << _req->coType 
                        //    << " src:" << _req->source << " dst:" << _req->dest << endl;
 
                        break;
                    }
                case EJECT_REQ:  //6
                    {
                        if(ejectReq == 1)
                        {
                            //cout << "\n*** EJECT_REQ *** " << endl;
                            for(int k=0; k<NE; k++)
                            {
                                if (rtrn_valid_all_[k] == 1){
                                    _res.id =  rtrn_pkgid_all[k];
                                    _eject_buffer.push(_res);
                                    rtrn_valid_all_[k] = 0;
                                }
                            }
                        }
                        else
                        {
                            _res.id = -1; //not pckage
                        }
 
                        if (!_eject_buffer.empty()) {
                                _res = _eject_buffer.front();
                                _eject_buffer.pop();
                                _res.remainingRequests = _eject_buffer.size();
                                _connection_manager->sendResMsg();
                                //cout << "<eject> id:" << _res.id << endl;
                        }
                        else
                        {
                            _connection_manager->sendResMsg();
                        }
 
                        break;
                    }
                case QUIT_REQ:
                    {
                        // acknowledge quit
                        QuitResMsg res;
                        *_channel << res;
 
                        *endCom = '1'; 
 
                        process_more = false;
 
                        break;
                    }
                default:
                    {
                        cout << "<ERROR:> Unknown message type: " << _msg->type << endl;
                        break;
                    }
 
            }
        }
 
        *newReq = msgDone     ;
 
 
        StreamMessage::destroy(_msg);
 
    }
 
}
 
//*****************************************************************
// Connection Manager
//*****************************************************************
connection_manager::connection_manager(){
    _channel = NULL;
    _sources = 4;
    _dests   = 4;
    _duplicate_networks = 1;
}
 
//--
int connection_manager::Init() {                            
    // Start listening for incoming connections
    if (_listenSocket.listen(NS_HOST, NS_PORT) < 0) {
        return -1;
    }
 
    // Waiting to connect
    _channel = _listenSocket.accept();
 
    cout << "Connected... " << endl;
 
    // Initialize client
    InitializeReqMsg req;
    InitializeResMsg res;
    *_channel >> req << res;
 
    return 0;
}
 
int connection_manager::readMsg() 
{    
    _msg = NULL;
 
    if (_channel) 
    {
        *_channel >> (StreamMessage*&) _msg;
    }
    return 0;
}
 
int connection_manager::sendResMsg() 
{   
    *_channel << _res;
    return 0;
}
 
int connection_manager::sendAckMsg() 
{   
    *_channel << _ackRes;
    return 0;
}
 
int connection_manager::sendAckReqMsg() 
{   
    *_channel << _ackReq;
    return 0;
}
 
int connection_manager::checkInjection(){
    return _newInjection;
}                            
 
int connection_manager::getPronocEndPoint(int node){
    return (node-(node%2))/2 ; 
}                            
 
int connection_manager::getSynfullEndPoint(int node){
    return (((node-(node%3))/3)*2)+!(node%3); 
}
 
int connection_manager::getMsgType(int opcode)
{
    int type;
    switch (opcode)
    {
        case 1: // readshared - read 
            type = 1; // req
            break;
        case 4: // compdata - data 
            type = 0; // req
            break;
        default:
            type = 2;
            break;
    }
    return type; 
}
 
int connection_manager::getChiOpc(int opcode, int type)
{
    int chiopc;
    switch (type)
    {
        case 1:
            switch (opcode)
            {
                case 1: // readshared - read 
                    chiopc = 1 ;
                    break; 
                default:
                    chiopc = 999;
                    cout << "(req) coherency message not supported" << endl;
                    break;
            }
            break;
        case 2:
            switch (opcode)
            {
                case 2: // compdata - data 
                    chiopc = 4;
                    break;
                case 5: // compack - unblock 
                    chiopc = 2;
                    break;
                default:
                    chiopc = 999;
                    cout << "(resp) coherency message not supported" << endl;
                    break;
            } 
            break;
        default:
            chiopc = 999;
            cout << "coherency message not supported" << endl;
            break;
    }
    return chiopc; 
}
 
//-------Debug functions Neiel-Leyva
 
int connection_manager::printResMsg(EjectResMsg res) {
    cout << "Debug Neiel: res.id                = " << res.id << endl;
    cout << "Debug Neiel: res.remainingRequests = " << res.remainingRequests << endl;
    cout << "Debug Neiel: res.source            = " << res.source << endl;
    cout << "Debug Neiel: res.destination       = " << res.dest << endl;
    cout << "Debug Neiel: req.packetSize        = " << res.packetSize   << endl;
    cout << "Debug Neiel: res.network           = " << res.network << endl;
    cout << "Debug Neiel: res.cl                = " << res.cl << endl;
    cout << "Debug Neiel: res.miss_prediction   = " << res.miss_pred << endl;
    return 0;
};
 
int connection_manager::printReqMsg(InjectReqMsg *req) {
    cout << "  " << endl;
    cout << "Debug Neiel: req.source     = " << req->source       << endl;
    cout << "Debug Neiel: req.dest       = " << req->dest         << endl;
    cout << "Debug Neiel: req.id         = " << req->id           << endl;
    cout << "Debug Neiel: req.packetSize = " << req->packetSize   << endl;
    cout << "Debug Neiel: req.network    = " << req->network      << endl;
    cout << "Debug Neiel: req.cl         = " << req->cl           << endl;
    cout << "Debug Neiel: req.msgType    = " << req->msgType      << endl; 
    cout << "Debug Neiel: req.coType     = " << req->coType       << endl; 
    cout << "Debug Neiel: req.address    = " << req->address      << endl; 
    return 0;                                                    
};
 
 
 
//*****************************************************************************
// SocketStream
//*****************************************************************************
 
int SocketStream::listen(const char *host, int port){
 
    char *socket_path = "./socket";
 
    // Create a socket
    if ( (so = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        cout << "Error creating socket." << endl;
        return -1;
    }
 
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
 
    // Bind it to the listening port
    unlink(socket_path);
    if (bind(so, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
         cout << "Error binding socket." << endl;
         return -1;
    }
 
    //// Listen for connections
    if (::listen(so, NS_MAX_PENDING) != 0) {
         cout << "Error listening on socket." << endl;
         return -1;
    }
 
    bIsAlive = true;
 
#ifdef NS_DEBUG
    cout << "Listening on socket" << endl;
#endif
 
    return 0;
}
 
// accept a new connection
SocketStream* SocketStream::accept()
{
    struct sockaddr_un clientaddr;
    socklen_t clientaddrlen = sizeof clientaddr;
    int clientsock = ::accept(so, (struct sockaddr*)&clientaddr, &clientaddrlen);
 
    if ( clientsock < 0 ){
        cout << "Error accepting a connection";
        return NULL;
    }
 
    return new SocketStream(clientsock, (struct sockaddr*)&clientaddr, clientaddrlen);
}
 
int SocketStream::connect(const char *host, int port)
{
    char *socket_path = "./socket";
    // Create a socket.
    if ( (so = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 ){
        cout << "Error creating socket." << endl;
        return -1;
    }
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
 
    // Connect to the server.
    if ( ::connect(so, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
        cout << "Connection failed." << endl;
        return -1;
    }
 
    bIsAlive = true;
 
#ifdef NS_DEBUG
    cout << "Connected to host" << endl;
#endif
 
    return 0;
}
 
// read from the socket
int SocketStream::get(void *data, int number)
{
 
    int remaining = number;
    int received = 0;
    char *dataRemaining = (char*) data;
 
    errno = 0;
    while (remaining > 0 && (errno == 0 || errno == EINTR))
    {
        received = recv(so, dataRemaining, remaining, 0); // MSG_WAITALL
        if (received > 0)
        {
            dataRemaining += received;
            remaining -= received;
        }
    }
 
    return number - remaining;
}
 
// write to socket
int SocketStream::put(const void *data, int number)
{
    // MSG_NOSIGNAL prevents SIGPIPE signal from being generated on failed send
    return send(so, data, number, MSG_NOSIGNAL);
}
 
 
//*****************************************************************
//*****************************************************************
 
 
using namespace std;
 
SocketStream& operator<<(SocketStream& os, StreamMessage& msg)
{
#ifdef NS_DEBUG_EXTRA
    std::cout << "<MessageSend> Sending message: " << msg.type << ", size: " << msg.size << std::endl;
#endif
 
    // cork the connection
    int flag = 1;
    setsockopt (os.so, SOL_TCP, TCP_CORK, &flag, sizeof (flag));
 
    os.put(&(msg.size), sizeof(int));
    os.put(&msg, msg.size);
 
    // uncork the connection
    flag = 0;
    setsockopt (os.so, SOL_TCP, TCP_CORK, &flag, sizeof (flag));
 
    // os.flush();
 
    return os;
}
 
SocketStream& operator>>(SocketStream& is, StreamMessage*& msg)
{
#ifdef NS_DEBUG_EXTRA
    std::cout << "<MessageRecv> Waiting for message" << std::endl;
#endif
 
    int msgSize = -1;
    int gotBytes = is.get(&msgSize, sizeof(int));
 
    if (gotBytes != sizeof(int))
        return is;
 
    assert(msgSize > 0);
 
    msg = (StreamMessage*) malloc(msgSize);
    is.get(msg, msgSize);
 
 
#ifdef NS_DEBUG_EXTRA
    std::cout << "<MessageRecv> Got message: " << msg->type << std::endl;
#endif
 
    return is;
}
 
SocketStream& operator>>(SocketStream& is, StreamMessage& msg)
{
#ifdef NS_DEBUG_EXTRA
    std::cout << "<MessageRecvSync> Waiting for message" << std::endl;
#endif
 
    int msgSize = -1;
    int gotBytes = is.get(&msgSize, sizeof(int));
 
    if (gotBytes != sizeof(int))
        return is;
 
    assert(msgSize == msg.size);
    is.get(&msg, msgSize);
 
#ifdef NS_DEBUG_EXTRA
    std::cout << "<MessageRecvSync> Got message: " << msg.type << std::endl;
#endif
 
    return is;
}
 
void StreamMessage::destroy(StreamMessage* msg)
{
    assert (msg != NULL);
    free(msg);
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.