Skip to content

File sync_protocol.h

File List > includes > sync_protocol.h

Go to the documentation of this file.

#pragma once

#include <fcntl.h>
#include <unistd.h>

#include <cstring>
#include <iostream>
#include <sstream>

#include "global_define.h"

#define NSINTERCHIPLET_CMD_HEAD "[INTERCMD]"

namespace InterChiplet {
inline std::string pipeName(const AddrType& __src, const AddrType& __dst) {
    std::stringstream ss;
    ss << "./buffer" << DIM_X(__src) << "_" << DIM_Y(__src) << "_" << DIM_X(__dst) << "_"
       << DIM_Y(__dst);
    return ss.str();
}

inline SyncCommand parseCmd(const std::string& __message) {
    // Remove command head.
    std::string message;
    if (__message.substr(0, 10) == NSINTERCHIPLET_CMD_HEAD) {
        message = __message.substr(11);
    } else {
        message = __message;
    }

    // Read command from message
    std::stringstream ss(message);
    std::string command;
    ss >> command;

    // Decode command to enumerate.
    SyncCommand cmd;
    cmd.m_type = command == "CYCLE"        ? SC_CYCLE
                 : command == "SEND"       ? SC_SEND
                 : command == "RECEIVE"    ? SC_RECEIVE
                 : command == "BARRIER"    ? SC_BARRIER
                 : command == "LOCK"       ? SC_LOCK
                 : command == "UNLOCK"     ? SC_UNLOCK
                 : command == "LAUNCH"     ? SC_LAUNCH
                 : command == "WAITLAUNCH" ? SC_WAITLAUNCH
                 : command == "READ"       ? SC_READ
                 : command == "WRITE"      ? SC_WRITE
                 : command == "SYNC"       ? SC_SYNC
                 : command == "RESULT"     ? SC_RESULT
                                           : SC_CYCLE;

    // Read cycle.
    if (cmd.m_type == SC_CYCLE || cmd.m_type == SC_READ || cmd.m_type == SC_WRITE ||
        cmd.m_type == SC_SYNC) {
        ss >> cmd.m_cycle;
    } else {
        cmd.m_cycle = 0;
    }
    // Read source address.
    if (cmd.m_type == SC_SEND || cmd.m_type == SC_RECEIVE || cmd.m_type == SC_BARRIER ||
        cmd.m_type == SC_LOCK || cmd.m_type == SC_UNLOCK || cmd.m_type == SC_LAUNCH ||
        cmd.m_type == SC_WAITLAUNCH || cmd.m_type == SC_READ || cmd.m_type == SC_WRITE) {
        long src_x, src_y;
        ss >> src_x >> src_y;
        cmd.m_src.push_back(src_x);
        cmd.m_src.push_back(src_y);
    } else {
        cmd.m_src.push_back(-1);
        cmd.m_src.push_back(-1);
    }
    // Read destination address.
    if (cmd.m_type == SC_SEND || cmd.m_type == SC_RECEIVE || cmd.m_type == SC_LAUNCH ||
        cmd.m_type == SC_WAITLAUNCH || cmd.m_type == SC_READ || cmd.m_type == SC_WRITE) {
        long dst_x, dst_y;
        ss >> dst_x >> dst_y;
        cmd.m_dst.push_back(dst_x);
        cmd.m_dst.push_back(dst_y);
    }
    // Read target address.
    else if (cmd.m_type == SC_BARRIER || cmd.m_type == SC_LOCK || cmd.m_type == SC_UNLOCK) {
        long dst_x;
        ss >> dst_x;
        cmd.m_dst.push_back(dst_x);
        cmd.m_dst.push_back(0);
    } else {
        cmd.m_dst.push_back(-1);
        cmd.m_dst.push_back(-1);
    }
    // Read number of bytes and descriptor.
    if (cmd.m_type == SC_READ || cmd.m_type == SC_WRITE) {
        ss >> cmd.m_nbytes >> cmd.m_desc;
    }
    // Read barrier count.
    else if (cmd.m_type == SC_BARRIER) {
        ss >> cmd.m_nbytes;
        cmd.m_desc = 0;
    } else {
        cmd.m_nbytes = 0;
        cmd.m_desc = 0;
    }

    // Read result
    if (cmd.m_type == SC_RESULT) {
        int res_cnt;
        ss >> res_cnt;
        for (int i = 0; i < res_cnt; i++) {
            std::string item;
            ss >> item;
            cmd.m_res_list.push_back(item);
        }
    } else {
        cmd.m_res_list.clear();
    }

    return cmd;
}

inline SyncCommand parseCmd(int __fd_in = STDIN_FILENO) {
    // Read message from input file descriptor.
    char* message = new char[1024];
    while (read(__fd_in, message, 1024) == 0);

    // Split message from '\n', ignore characters after '\n'.
    for (std::size_t i = 0; i < strlen(message); i++) {
        if (message[i] == '\n') message[i + 1] = 0;
    }
    std::cout << "[RESPONSE]" << message;

    // Parse command.
    SyncCommand cmd = parseCmd(std::string(message));
    delete message;

    // Return message.
    return cmd;
}

inline std::string dumpCmd(const SyncCommand& __cmd) {
    std::stringstream ss;
    std::string type_str = __cmd.m_type == SC_CYCLE        ? "CYCLE"
                           : __cmd.m_type == SC_SEND       ? "SEND"
                           : __cmd.m_type == SC_RECEIVE    ? "RECEIVE"
                           : __cmd.m_type == SC_BARRIER    ? "BARRIER"
                           : __cmd.m_type == SC_LOCK       ? "LOCK"
                           : __cmd.m_type == SC_UNLOCK     ? "UNLOCK"
                           : __cmd.m_type == SC_LAUNCH     ? "LAUNCH"
                           : __cmd.m_type == SC_WAITLAUNCH ? "WAITLAUNCH"
                           : __cmd.m_type == SC_READ       ? "READ"
                           : __cmd.m_type == SC_WRITE      ? "WRITE"
                           : __cmd.m_type == SC_SYNC       ? "SYNC"
                           : __cmd.m_type == SC_RESULT     ? "RESULT"
                                                           : "CYCLE";
    ss << type_str << " command";

    // Write cycle
    if (__cmd.m_type == SC_CYCLE || __cmd.m_type == SC_READ || __cmd.m_type == SC_WRITE ||
        __cmd.m_type == SC_SYNC) {
        ss << " at " << static_cast<TimeType>(__cmd.m_cycle) << " cycle";
    }
    // Write source address.
    if (__cmd.m_type == SC_SEND || __cmd.m_type == SC_RECEIVE || __cmd.m_type == SC_BARRIER ||
        __cmd.m_type == SC_LOCK || __cmd.m_type == SC_UNLOCK || __cmd.m_type == SC_LAUNCH ||
        __cmd.m_type == SC_WAITLAUNCH || __cmd.m_type == SC_READ || __cmd.m_type == SC_WRITE) {
        ss << " from " << DIM_X(__cmd.m_src) << "," << DIM_Y(__cmd.m_src);
    }
    // Write destination address.
    if (__cmd.m_type == SC_SEND || __cmd.m_type == SC_RECEIVE || __cmd.m_type == SC_LAUNCH ||
        __cmd.m_type == SC_WAITLAUNCH || __cmd.m_type == SC_READ || __cmd.m_type == SC_WRITE) {
        ss << " to " << DIM_X(__cmd.m_dst) << "," << DIM_Y(__cmd.m_dst);
    }
    // Write target address.
    if (__cmd.m_type == SC_BARRIER || __cmd.m_type == SC_LOCK || __cmd.m_type == SC_UNLOCK) {
        ss << " to " << DIM_X(__cmd.m_dst);
    }
    // Write Result.
    if (__cmd.m_type == SC_RESULT) {
        ss << ":";
        for (auto& item : __cmd.m_res_list) {
            ss << " " << item;
        }
    }
    ss << ".";
    return ss.str();
}

inline void sendCycleCmd(TimeType __cycle) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " CYCLE " << __cycle << std::endl;
}

inline void sendSendCmd(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " SEND " << __src_x << " " << __src_y << " " << __dst_x
              << " " << __dst_y << std::endl;
}

inline void sendReceiveCmd(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " RECEIVE " << __src_x << " " << __src_y << " "
              << __dst_x << " " << __dst_y << std::endl;
}

inline void sendBarrierCmd(int __src_x, int __src_y, int __uid, int __count) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " BARRIER " << __src_x << " " << __src_y << " " << __uid
              << " " << __count << std::endl;
}

inline void sendLockCmd(int __src_x, int __src_y, int __uid) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " LOCK " << __src_x << " " << __src_y << " " << __uid
              << std::endl;
}

inline void sendUnlockCmd(int __src_x, int __src_y, int __uid) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " UNLOCK " << __src_x << " " << __src_y << " " << __uid
              << std::endl;
}

inline void sendLaunchCmd(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " LAUNCH " << __src_x << " " << __src_y << " "
              << __dst_x << " " << __dst_y << std::endl;
}

inline void sendWaitlaunchCmd(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " WAITLAUNCH " << __src_x << " " << __src_y << " "
              << __dst_x << " " << __dst_y << std::endl;
}

inline void sendReadCmd(TimeType __cycle, int __src_x, int __src_y, int __dst_x, int __dst_y,
                        int __nbyte, long __desc) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " READ " << __cycle << " " << __src_x << " " << __src_y
              << " " << __dst_x << " " << __dst_y << " " << __nbyte << " " << __desc << std::endl;
}

inline void sendWriteCmd(TimeType __cycle, int __src_x, int __src_y, int __dst_x, int __dst_y,
                         int __nbyte, long __desc) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " WRITE " << __cycle << " " << __src_x << " " << __src_y
              << " " << __dst_x << " " << __dst_y << " " << __nbyte << " " << __desc << std::endl;
}

inline void sendSyncCmd(TimeType __cycle) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " SYNC " << __cycle << std::endl;
}

inline void sendSyncCmd(int __fd, TimeType __cycle) {
    std::stringstream ss;
    ss << NSINTERCHIPLET_CMD_HEAD << " SYNC " << __cycle << std::endl;
    if (write(__fd, ss.str().c_str(), ss.str().size()) < 0) {
        perror("write");
        exit(EXIT_FAILURE);
    };
}

inline void sendResultCmd() {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " RESULT " << 0 << std::endl;
}

inline void sendResultCmd(const std::vector<std::string>& __res_list) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " RESULT " << __res_list.size();
    for (auto& item : __res_list) {
        std::cout << " " << item;
    }
    std::cout << std::endl;
}

inline void sendResultCmd(const std::vector<long>& __res_list) {
    std::cout << NSINTERCHIPLET_CMD_HEAD << " RESULT " << __res_list.size();
    for (auto& item : __res_list) {
        std::cout << " " << item;
    }
    std::cout << std::endl;
}

inline void sendResultCmd(int __fd) {
    std::stringstream ss;
    ss << NSINTERCHIPLET_CMD_HEAD << " RESULT " << 0 << std::endl;
    if (write(__fd, ss.str().c_str(), ss.str().size()) < 0) {
        perror("write");
        exit(EXIT_FAILURE);
    };
}

inline void sendResultCmd(int __fd, const std::vector<std::string>& __res_list) {
    std::stringstream ss;
    ss << NSINTERCHIPLET_CMD_HEAD << " RESULT " << __res_list.size();
    for (auto& item : __res_list) {
        ss << " " << item;
    }
    ss << std::endl;
    if (write(__fd, ss.str().c_str(), ss.str().size()) < 0) {
        perror("write");
        exit(EXIT_FAILURE);
    };
}

inline void sendResultCmd(int __fd, const std::vector<long>& __res_list) {
    std::stringstream ss;
    ss << NSINTERCHIPLET_CMD_HEAD << " RESULT " << __res_list.size();
    for (auto& item : __res_list) {
        ss << " " << item;
    }
    ss << std::endl;
    if (write(__fd, ss.str().c_str(), ss.str().size()) < 0) {
        perror("write");
        exit(EXIT_FAILURE);
    };
}

inline TimeType cycleSync(TimeType __cycle) {
    // Send CYCLE command.
    sendCycleCmd(__cycle);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    // Only handle SYNC message, return cycle to receive SYNC command.
    return resp_cmd.m_type == SC_SYNC ? resp_cmd.m_cycle : -1;
}

inline std::string sendSync(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    // Send SEND command.
    sendSendCmd(__src_x, __src_y, __dst_x, __dst_y);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    // Return Pipe name.
    return resp_cmd.m_res_list[0];
}

inline std::string receiveSync(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    // Send RECEIVE command.
    sendReceiveCmd(__src_x, __src_y, __dst_x, __dst_y);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    // Return Pipe name.
    return resp_cmd.m_res_list[0];
}

inline void launchSync(int __src_x, int __src_y, int __dst_x, int __dst_y) {
    // Send LAUNCH command.
    sendLaunchCmd(__src_x, __src_y, __dst_x, __dst_y);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();

    return;
}

inline void waitlaunchSync(int* __src_x, int* __src_y, int __dst_x, int __dst_y) {
    // Send LAUNCH command.
    sendWaitlaunchCmd(*__src_x, *__src_y, __dst_x, __dst_y);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    *__src_x = atoi(resp_cmd.m_res_list[0].c_str());
    *__src_y = atoi(resp_cmd.m_res_list[1].c_str());

    return;
}

inline void barrierSync(int __src_x, int __src_y, int __uid, int __count) {
    // Send BARRIER command.
    sendBarrierCmd(__src_x, __src_y, __uid, __count);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();

    return;
}

inline void lockSync(int __src_x, int __src_y, int __uid) {
    // Send UNLOCK command.
    sendLockCmd(__src_x, __src_y, __uid);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();

    return;
}

inline void unlockSync(int __src_x, int __src_y, int __uid) {
    // Send UNLOCK command.
    sendUnlockCmd(__src_x, __src_y, __uid);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();

    return;
}

inline TimeType readSync(TimeType __cycle, int __src_x, int __src_y, int __dst_x, int __dst_y,
                         int __nbyte, long __desc) {
    // Send READ command.
    sendReadCmd(__cycle, __src_x, __src_y, __dst_x, __dst_y, __nbyte, __desc);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    // Only handle SYNC message, return cycle to receive SYNC command.
    return resp_cmd.m_type == SC_SYNC ? resp_cmd.m_cycle : -1;
}

inline TimeType writeSync(TimeType __cycle, int __src_x, int __src_y, int __dst_x, int __dst_y,
                          int __nbyte, long __desc) {
    // Send WRITE command.
    sendWriteCmd(__cycle, __src_x, __src_y, __dst_x, __dst_y, __nbyte, __desc);
    // Read message from stdin.
    SyncCommand resp_cmd = parseCmd();
    // Only handle SYNC message, return cycle to receive SYNC command.
    return resp_cmd.m_type == SC_SYNC ? resp_cmd.m_cycle : -1;
}
}  // namespace InterChiplet