// threadId of ALL_THREADS means run all threads.  Otherwise, run just the
// indicated thread.
static void runUntilInterrupt(Core *core, uint32_t threadId, bool enableFbWindow)
{
    fd_set readFds;
    int result;
    struct timeval timeout;

    FD_ZERO(&readFds);

    while (true)
    {
        if (!executeInstructions(core, threadId, gScreenRefreshRate))
            break;

        if (enableFbWindow)
        {
            updateFramebuffer(core);
            pollFbWindowEvent();
            checkInterruptPipe(core);
        }

        FD_SET(gClientSocket, &readFds);
        timeout.tv_sec = 0;
        timeout.tv_usec = 0;
        result = select(gClientSocket + 1, &readFds, NULL, NULL, &timeout);
        if ((result < 0 && errno != EINTR) || result == 1)
            break;
    }
}
Beispiel #2
0
int main(int argc, char *argv[])
{
    Core *core;
    int option;
    bool enableMemoryDump = false;
    uint32_t memDumpBase = 0;
    uint32_t memDumpLength = 0;
    char *memDumpFilename = NULL;
    size_t memDumpFilenameLen = 0;
    bool verbose = false;
    uint32_t fbWidth = 640;
    uint32_t fbHeight = 480;
    bool blockDeviceOpen = false;
    bool enableFbWindow = false;
    uint32_t totalThreads = 4;
    char *separator;
    uint32_t memorySize = 0x1000000;
    const char *sharedMemoryFile = NULL;
    struct stat st;

    enum
    {
        MODE_NORMAL,
        MODE_COSIMULATION,
        MODE_GDB_REMOTE_DEBUG
    } mode = MODE_NORMAL;

    while ((option = getopt(argc, argv, "f:d:vm:b:t:c:r:s:i:o:")) != -1)
    {
        switch (option)
        {
            case 'v':
                verbose = true;
                break;

            case 'r':
                gScreenRefreshRate = parseNumArg(optarg);
                break;

            case 'f':
                enableFbWindow = true;
                separator = strchr(optarg, 'x');
                if (!separator)
                {
                    fprintf(stderr, "Invalid framebuffer size %s\n", optarg);
                    return 1;
                }

                fbWidth = parseNumArg(optarg);
                fbHeight = parseNumArg(separator + 1);
                break;

            case 'm':
                if (strcmp(optarg, "normal") == 0)
                    mode = MODE_NORMAL;
                else if (strcmp(optarg, "cosim") == 0)
                    mode = MODE_COSIMULATION;
                else if (strcmp(optarg, "gdb") == 0)
                    mode = MODE_GDB_REMOTE_DEBUG;
                else
                {
                    fprintf(stderr, "Unkown execution mode %s\n", optarg);
                    return 1;
                }

                break;

            case 'd':
                // Memory dump, of the form: filename,start,length
                separator = strchr(optarg, ',');
                if (separator == NULL)
                {
                    fprintf(stderr, "bad format for memory dump\n");
                    usage();
                    return 1;
                }

                memDumpFilenameLen = (size_t)(separator - optarg);
                memDumpFilename = (char*) malloc(memDumpFilenameLen + 1);
                strncpy(memDumpFilename, optarg, memDumpFilenameLen);
                memDumpFilename[memDumpFilenameLen] = '\0';
                memDumpBase = parseNumArg(separator + 1);

                separator = strchr(separator + 1, ',');
                if (separator == NULL)
                {
                    fprintf(stderr, "bad format for memory dump\n");
                    usage();
                    return 1;
                }

                memDumpLength = parseNumArg(separator + 1);
                enableMemoryDump = true;
                break;

            case 'b':
                if (openBlockDevice(optarg) < 0)
                    return 1;

                blockDeviceOpen = true;
                break;

            case 'c':
                memorySize = parseNumArg(optarg);
                break;

            case 't':
                totalThreads = parseNumArg(optarg);
                if (totalThreads < 1 || totalThreads > 32)
                {
                    fprintf(stderr, "Total threads must be between 1 and 32\n");
                    return 1;
                }

                break;

            case 's':
                sharedMemoryFile = optarg;
                break;

            case 'i':
                recvInterruptFd = open(optarg, O_RDWR);
                if (recvInterruptFd < 0)
                {
                    perror("main: failed to open receive interrupt pipe");
                    return 1;
                }

                if (fstat(recvInterruptFd, &st) < 0)
                {
                    perror("main: stat failed on receive interrupt pipe");
                    return 1;
                }

                if ((st.st_mode & S_IFMT) != S_IFIFO)
                {
                    fprintf(stderr, "%s is not a pipe\n", optarg);
                    return 1;
                }

                break;

            case 'o':
                sendInterruptFd = open(optarg, O_RDWR);
                if (sendInterruptFd < 0)
                {
                    perror("main: failed to open send interrupt pipe");
                    return 1;
                }

                if (fstat(sendInterruptFd, &st) < 0)
                {
                    perror("main: stat failed on send interrupt pipe");
                    return 1;
                }

                if ((st.st_mode & S_IFMT) != S_IFIFO)
                {
                    fprintf(stderr, "%s is not a pipe\n", optarg);
                    return 1;
                }

                break;

            case '?':
                usage();
                return 1;
        }
    }

    if (optind == argc)
    {
        fprintf(stderr, "No image filename specified\n");
        usage();
        return 1;
    }

    // Don't randomize memory for cosimulation mode, because
    // memory is checked against the hardware model to ensure a match

    core = initCore(memorySize, totalThreads, mode != MODE_COSIMULATION,
                    sharedMemoryFile);
    if (core == NULL)
        return 1;

    if (loadHexFile(core, argv[optind]) < 0)
    {
        fprintf(stderr, "Error reading image %s\n", argv[optind]);
        return 1;
    }

    if (enableFbWindow)
    {
        if (initFramebuffer(fbWidth, fbHeight) < 0)
            return 1;
    }

    switch (mode)
    {
        case MODE_NORMAL:
            if (verbose)
                enableTracing(core);

            setStopOnFault(core, false);
            if (enableFbWindow)
            {
                while (executeInstructions(core, ALL_THREADS, gScreenRefreshRate))
                {
                    updateFramebuffer(core);
                    pollFbWindowEvent();
                    checkInterruptPipe(core);
                }
            }
            else
            {
                while (executeInstructions(core, ALL_THREADS, 1000000))
                    checkInterruptPipe(core);
            }

            break;

        case MODE_COSIMULATION:
            setStopOnFault(core, false);
            if (runCosimulation(core, verbose) < 0)
                return 1;	// Failed

            break;

        case MODE_GDB_REMOTE_DEBUG:
            setStopOnFault(core, true);
            remoteGdbMainLoop(core, enableFbWindow);
            break;
    }

    if (enableMemoryDump)
        writeMemoryToFile(core, memDumpFilename, memDumpBase, memDumpLength);

    dumpInstructionStats(core);
    if (blockDeviceOpen)
        closeBlockDevice();

    if (stoppedOnFault(core))
        return 1;

    return 0;
}