Пример #1
0
int otherTest()
{
    lc3 lc3;
    lc3_init(&lc3);
    ldb db;
    ldb_init(&db, &lc3);
    if(ldb_loadObj(&db,"testcases/Project1.obj")!=OPEN)
        return -1;
    lc3.mem[0x30f0] = 25;
    lc3.mem[0x30f1] = 4;
    //ldb_setUnconBP(&db,0x3001);
    //ldb_setBP(&db, 0x3001, 1, bp_neq, bp_reg, 0, 0xbeef);
    ldb_run(&db);

    for(int i = 0; i < GPR_NUM; i++)
    {
        printf("R%d    : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]);
    }
    for(int i = 0; i < 8; i++)
    {
        printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]);
    }
    printf("x%x : x%04x | %d\n",0x30f2,lc3.mem[0x30f2],(int16_t)lc3.mem[0x30f2]);
    printf("%llu cycles\n",(long long unsigned int)db.cycleCount);

    ldb_dump_lc3_r(&db,"dump/dump.lc3rdump");
    ldb_dump_lc3_t(&db,"dump/dump.lc3tdump");
    ldb_dump_lc3_b(&db,"dump/dump.lc3bdump");

    return 0;
}
Пример #2
0
/** OnInit
  *
  * Called when the machine needs to be initialized
  */
void ComplxFrame::OnInit(void)
{
    static bool first = true;
    lc3_init(state, true);

    if (console != NULL) delete console;
    console = new LC3Console(this);

    state.input = &console->inputStream;
    state.reader = complx_reader;
    state.peek = complx_peek;
    state.writer = complx_writer;
    // For keyboard interrupts
    state.interrupt_test.push_back(complx_step);

    console->Show();

    int x, y;
    GetScreenPosition(&x, &y);
    if (first)
    {
        Move(x + console->GetSize().GetX() / 2, y);
        console->Move(x - console->GetSize().GetX() / 2, y);
        first = false;
    }
    else
    {
        console->Move(x - console->GetSize().GetX(), y);
    }

    lc3_set_true_traps(state, menuStateTrueTraps->IsChecked());
    state.interrupt_enabled = menuStateInterrupts->IsChecked();
    state.max_stack_size = stack_size;
    state.max_call_stack_size = call_stack_size;
}
Пример #3
0
/** DoLoadFile
  *
  * Handles loading an assembly file into the simulator
  */
void ComplxFrame::DoLoadFile(const wxFileName& filename)
{
    //CleanUp();
    lc3_state dummy_state;
    lc3_init(dummy_state);

    // Save the symbols
    std::map<std::string, unsigned short> symbol_table = state.symbols;
    std::map<unsigned short, std::string> rev_symbol_table = state.rev_symbols;

    state.symbols.clear();
    state.rev_symbols.clear();
    lc3_remove_plugins(state);

    try
    {
        lc3_assemble(dummy_state, filename.GetFullPath().ToStdString(), false);
        lc3_assemble(state, filename.GetFullPath().ToStdString());

    }
    catch (LC3AssembleException e)
    {
        wxMessageBox(wxString::Format("BAD STUDENT! %s", e.what()), _("Loading ") + filename.GetFullName() + _(" Failed"));
        goto merge;
    }
    catch (std::vector<LC3AssembleException> e)
    {
        std::stringstream oss;
        for (unsigned int i = 0; i < e.size(); i++)
            oss << e[i].what() << std::endl;
        wxMessageBox(wxString::Format("BAD STUDENT! %s", oss.str()), _("Loading ") + filename.GetFullName() + _(" Failed"));
        goto merge;
    }

    //if (DoAssemble(filename)) return;
    currentFile = filename;
    SetTitle(wxString::Format("Complx - %s", filename.GetFullPath()));
    merge:

    std::map<std::string, unsigned short>::const_iterator i;
    std::map<unsigned short, std::string>::const_iterator j;
    for (i = symbol_table.begin(); i != symbol_table.end(); ++i)
    {
        state.symbols[i->first] = i->second;
    }
    for (j = rev_symbol_table.begin(); j != rev_symbol_table.end(); ++j)
    {
        state.rev_symbols[j->first] = j->second;
    }

    //DoLoad(filename);
    UpdateStatus();
    UpdateRegisters();
    UpdateMemory();

}
Пример #4
0
void do_load(const std::string& filename)
{
    lc3_init(state);
    try
    {
        lc3_assemble(state, filename);
    }
    catch (LC3AssembleException e)
    {
        fprintf(stderr, "[ERROR] %s failed to assemble. %s\n", filename.c_str(), e.what().c_str());
        return;
    }
    current_filename = filename;
    memory->Update();
}
Пример #5
0
void do_reload(void)
{
    if (current_filename.empty())
        return;

    lc3_init(state);
    try
    {
        lc3_assemble(state, current_filename);
    }
    catch (LC3AssembleException e)
    {
        fprintf(stderr, "[ERROR] %s failed to assemble. %s\n", current_filename.c_str(), e.what().c_str());
        return;
    }
    memory->Update();
}
Пример #6
0
int dumpTest()
{
    lc3 lc3;
    lc3_init(&lc3);
    ldb db;
    ldb_init(&db, &lc3);
    if(ldb_dumpload_lc3_b(&db,"dump/dump.lc3bdump")!=OPEN)
        return -1;

    for(int i = 0; i < GPR_NUM; i++)
    {
        printf("R%d    : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]);
    }
    for(int i = 0; i < 8; i++)
    {
        printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]);
    }
    printf("x%x : x%04x | %d\n",0x30f2,lc3.mem[0x30f2],(int16_t)lc3.mem[0x30f2]);
    printf("%llu cycles\n",(long long unsigned int)db.cycleCount);
    return 0;
}
Пример #7
0
int test() {
    unsigned int cycles = 0;

    printf("Hello world\n");
    lc3 lc3;
    lc3_init(&lc3);

    for(lc3.mem[0xFFFE] |= 0x8000 ; lc3_cycle(&lc3) != HALT;cycles++);
    for(int i = 0; i < GPR_NUM; i++)
    {
        printf("R%d    : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]);
    }
    for(int i = 0; i < 8; i++)
    {
        printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]);
    }
    printf("%d cycles\n",cycles);


    return 0;
}
Пример #8
0
int debuggerTest()
{
    lc3 lc3;
    lc3_init(&lc3);
    ldb db;
    ldb_init(&db, &lc3);
    if(ldb_loadObj(&db,"testcases/lsi.obj") != OPEN)
        return -1;
    //ldb_setUnconBP(&db,0x3001);
    ldb_setBP(&db, 0x3001, 1, ldb_neq, ldb_reg, 0, 0xbeef);
    ldb_run(&db);

    for(int i = 0; i < GPR_NUM; i++)
    {
        printf("R%d    : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]);
    }
    for(int i = 0; i < 8; i++)
    {
        printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]);
    }
    printf("%llu cycles\n",(long long unsigned int) db.cycleCount);

    return 0;
}
Пример #9
0
void lc3_run_test_case(lc3_test& test, const std::string& filename, int seed)
{
    lc3_state state;

    // Preliminary stuff
    if (seed != -1) srand(seed);
    lc3_init(state, test.randomize, test.randomize);
    if (test.true_traps) lc3_set_true_traps(state, 1);
    if (test.interrupt_enabled) state.interrupt_enabled = 1;
    bool disable_plugins = test.disable_plugins;
    state.max_stack_size = 0;
    state.max_call_stack_size = -1;
    state.in_lc3test = true;

    try
    {
        LC3AssembleOptions options;
        options.multiple_errors = false;
        options.warnings_as_errors = false;
        options.process_debug_comments = false;
        options.enable_warnings = false;
        options.disable_plugins = disable_plugins;
        lc3_assemble(state, filename, options);
    }
    catch (LC3AssembleException e)
    {
        throw e.what();
    }


    std::stringstream* newinput = new std::stringstream();

    // Set up test environment
    for (unsigned int i = 0; i < test.input.size(); i++)
    {
        lc3_test_input& input = test.input[i];
        int value_calc;
        int address_calc = 0;
        unsigned short effective_address;

        ///TODO flip the condition here so that if new types are added you don't have to check for it here...
        if (input.type != TEST_IO && input.type != TEST_REGISTER && input.type != TEST_PC && input.type != TEST_SUBROUTINE &&
            lc3_calculate(state, input.address, address_calc) == -1)
            throw "An address expression " + input.address + " was not formed correctly.";
        else if (input.type == TEST_REGISTER)
        {
            if (input.address.size() != 2)
                throw "Register format is RX where x is between 0-7 found: " + input.address;

            address_calc = input.address[1] - '0';
            if (address_calc > 7 || address_calc < 0)
                throw "Invalid register " + input.address;
        }
        else
            lc3_calculate(state, input.address, address_calc);

        effective_address = (unsigned short) address_calc;

        switch (input.type)
        {
            case TEST_VALUE:
                if (lc3_calculate(state, input.value, value_calc))
                    throw "<in test-value> A value expression " + input.value + " was malformed.";
                state.mem[effective_address] = (short) value_calc;
                break;
            case TEST_REGISTER:
                if (lc3_calculate(state, input.registerval, value_calc))
                    throw "<in test-register> A value expression " + input.registerval + " was malformed.";
                state.regs[effective_address] = (short) value_calc;
                break;
            case TEST_PC:
                if (lc3_calculate(state, input.pcval, value_calc))
                    throw "<in test-pc> A value expression " + input.pcval + " was malformed.";
                state.pc = (unsigned short) value_calc;
                break;
            case TEST_POINTER:
                if (lc3_calculate(state, input.pointer, value_calc))
                    throw "<in test-pointer> An expression was " + input.pointer + " malformed.";
                state.mem[(unsigned short) state.mem[effective_address]] = (short) value_calc;
                break;
            case TEST_STRING:
                for (unsigned int j = 0; j < input.text.size(); j++)
                    state.mem[state.mem[effective_address] + j] = input.text[j];
                state.mem[(unsigned short) (state.mem[effective_address] + input.text.size())] = 0;
                break;
            case TEST_ARRAY:
                for (unsigned int j = 0; j < input.array.size(); j++)
                {
                    if (lc3_calculate(state, input.array[j], value_calc))
                        throw "<in test-array> An expression was " + input.array[j] + " malformed.";
                    state.mem[(unsigned short) (state.mem[effective_address] + j)] = (short) value_calc;
                }
                break;
            case TEST_IO:
                newinput->str(input.io);
                break;
            case TEST_SUBROUTINE:
                break;
            default:
                throw "Unknown test type";
        }

        if (input.type == TEST_SUBROUTINE)
        {
            lc3_subr_input& subr = input.subroutine;
            int pc;
            int r7;
            int r6;
            int r5;
            if (lc3_calculate(state, subr.name, pc) == -1)
                throw "<in test-subr> invalid subroutine name given " + subr.name;
            if (lc3_calculate(state, subr.stack, r6) == -1)
                throw "<in test-subr> stack expression was malformed " + subr.stack;
            if (lc3_calculate(state, subr.r7, r7) == -1)
                throw "<in test-subr> r7 expression was malformed " + subr.r7;
            if (lc3_calculate(state, subr.r5, r5) == -1)
                throw "<in test-subr> r5 expression was malformed " + subr.r5;

            state.pc = (unsigned short) pc;
            state.regs[6] = (unsigned short)(r6 - subr.params.size());
            state.regs[7] = (unsigned short) r7;
            state.regs[5] = (unsigned short) r5;
            state.mem[state.regs[7]] = 0xF025;

            for (unsigned int j = 0; j < subr.params.size(); j++)
            {
                if (lc3_calculate(state, subr.params[j], value_calc))
                    throw "<in test-subr> param expression " + subr.params[j] + " was malformed.";
                state.mem[(unsigned short)state.regs[6] + j] = (short) value_calc;
            }

            // This fixes the issue in which a subroutine is being tested, but it makes calls to other subroutines who takes a
            // different number of parameters than the subroutine under test.
            // If the file uses subroutine annotations then overwrite it.
            for (const auto& info : subr.subroutines)
            {
                int address = 0;
                if (lc3_calculate(state, info.name, address) == -1)
                    throw "<in test-subr> invalid subroutine name given " + info.name;

                lc3_subroutine_info test_info = info;
                test_info.address = (unsigned short) address;
                state.subroutines[(unsigned short)address] = test_info;
            }
        }
    }

    state.input = newinput;
    // Setup output capture device
    std::stringstream* newoutput = new std::stringstream();
    state.output = newoutput;
    std::stringstream* newwarning = new std::stringstream();
    state.warning = newwarning;

    if (test.has_max_executions)
    {
        unsigned long i = 0;
        // Do this num times or until halted.
        while (i < test.max_executions && !state.halted)
        {
            //printf("%04x: %s (%x)\n", state.pc, lc3_disassemble(state, state.mem[state.pc]).c_str(), (unsigned short)state.mem[state.pc]);
                /*printf("R0 %6d|x%04x\tR1 %6d|x%04x\tR2 %6d|x%04x\tR3 %6d|x%04x\nR4 %6d|x%04x\tR5 %6d|x%04x\tR6 %6d|x%04x\tR7 %6d|x%04x\nCC: %s\tPC: %04x\n\n",
                       state.regs[0], (unsigned short)state.regs[0], state.regs[1], (unsigned short)state.regs[1], state.regs[2], (unsigned short)state.regs[2],
                       state.regs[3], (unsigned short)state.regs[3], state.regs[4], (unsigned short)state.regs[4], state.regs[5], (unsigned short)state.regs[5],
                       state.regs[6], (unsigned short)state.regs[6], state.regs[7], (unsigned short)state.regs[7], (state.n ? "N" : (state.z ? "Z" : "P")),
                       (unsigned short) state.pc);*/
            // Step one instruction
            lc3_step(state);
            // Increment instruction count
            i++;
        }
        //lc3_run(state, test.max_executions);
    }
    else
        lc3_run(state);

    // Fill in the output values
    test.has_halted = state.halted;
    test.executions = state.executions;
    test.warnings = state.warnings;
    test.warning = newwarning->str();

    bool test_passed = true;
    unsigned int test_points = 0;
    unsigned int test_max_points = 0;
    // Check test environment
    for (unsigned int i = 0; i < test.output.size(); i++)
    {
        std::stringstream expected;
        std::stringstream actual;

        lc3_test_output& output = test.output[i];
        int value_calc;
        short short_cmp;
        int address_calc = 0;
        unsigned short effective_address;
        std::string str;
        std::vector<short> arrayexpected;
        std::vector<short> arrayactual;

        if (output.type != TEST_IO && output.type != TEST_REGISTER && output.type != TEST_PC && lc3_calculate(state, output.address, address_calc) == -1)
            throw "An address expression " + output.address + " was not formed correctly.";
        else if (output.type == TEST_REGISTER)
        {
            address_calc = output.address[1] - '0';
            if (address_calc > 7)
                throw "Invalid register " + output.address;
        }
        effective_address = (unsigned short) address_calc;

        output.passed = true;
        output.earned = 0;
        switch (output.type)
        {
            case TEST_VALUE:
                if (lc3_calculate(state, output.value, value_calc))
                    throw "<in test-value> An expression " + output.value + " was malformed.";

                short_cmp = (short) value_calc;
                output.passed = lc3_test_check(output, &state.mem[effective_address], &short_cmp);

                actual << state.mem[effective_address];
                expected << short_cmp;
                break;
            case TEST_REGISTER:
                if (lc3_calculate(state, output.registerval, value_calc))
                    throw "<in test-register> An expression " + output.registerval + " was malformed.";

                short_cmp = (short) value_calc;
                output.passed = lc3_test_check(output, &state.regs[effective_address], &short_cmp);

                actual << state.regs[effective_address];
                expected << short_cmp;
                break;
            case TEST_PC:
                if (lc3_calculate(state, output.pcval, value_calc))
                    throw "<in test-pc> An expression " + output.pcval + " was malformed.";

                short_cmp = (short) value_calc;
                output.passed = lc3_test_check(output, &state.pc, &short_cmp);

                actual << state.pc;
                expected << short_cmp;

                break;
            case TEST_POINTER:
                if (lc3_calculate(state, output.pointer, value_calc))
                    throw "<in test-pointer> An expression " + output.pointer + " was malformed.";

                short_cmp = (short) value_calc;
                output.passed = lc3_test_check(output, &state.mem[(unsigned short)state.mem[effective_address]], &short_cmp);

                actual << state.mem[(unsigned short)state.mem[effective_address]];
                expected << short_cmp;

                break;
            case TEST_STRING:
                value_calc = (unsigned short)state.mem[effective_address];
                short_cmp = state.mem[(unsigned short)value_calc];

                while(short_cmp > 0 && short_cmp <= 255)
                {
                    actual.put((char) short_cmp);
                    value_calc++;
                    short_cmp = state.mem[(unsigned short)value_calc];
                }

                str = actual.str();
                output.passed = lc3_test_check(output, &str, &output.text);
                expected << output.text;
                break;
            case TEST_ARRAY:
                for (unsigned int j = 0; j < output.array.size(); j++)
                {
                    if (lc3_calculate(state, output.array[j], value_calc))
                        throw "<in test-array> An expression " + output.array[j] + " was malformed.";

                    arrayexpected.push_back(state.mem[(unsigned short)(state.mem[effective_address] + j)]);
                    arrayactual.push_back((short)value_calc);

                    actual << state.mem[(unsigned short)(state.mem[effective_address] + j)] << " ";
                    expected << (short)value_calc << " ";
                }

                output.passed = lc3_test_check(output, &arrayactual, &arrayexpected);
                break;
            case TEST_IO:
                str = newoutput->str();
                output.passed = lc3_test_check(output, &str, &output.io);
                actual << str;
                expected << output.io;
                break;
            case TEST_SUBROUTINE:
                break;
            default:
                throw "Unknown test type";
        }

        if (output.type != TEST_SUBROUTINE)
        {
            if (output.passed)
                output.earned = output.points;
        }

        if (output.type == TEST_SUBROUTINE)
        {
            std::stringstream extra;
            lc3_subr_output& subr = output.subroutine;

            std::vector<short> expected_stack;
            std::vector<short> actual_stack;

            std::vector<short> locals;
            std::vector<short> params;
            for (int j = (int)subr.locals.size() - 1; j >= 0; j--)
            {
                if (lc3_calculate(state, subr.locals[j], value_calc))
                    throw "<in test-subr> A local variable expression " + subr.locals[i] + "was malformed.";

                expected_stack.push_back((short)value_calc);
                locals.push_back((short) value_calc);
            }

            int r7;
            int r6;
            int r5;
            int answer;
            if (lc3_calculate(state, subr.stack, r6) == -1)
                throw "<in test-subr> stack expression " + subr.stack + " was malformed";
            if (lc3_calculate(state, subr.r7, r7) == -1)
                throw "<in test-subr> r7 expression " + subr.r7 + " was malformed";
            if (lc3_calculate(state, subr.r5, r5) == -1)
                throw "<in test-subr> r5 expression " + subr.r5 + " was malformed";
            if (lc3_calculate(state, subr.answer, answer) == -1)
                throw "<in test-subr> answer expression " + subr.answer + " was malformed";

            expected_stack.push_back((short)r5);
            expected_stack.push_back((short)r7);
            expected_stack.push_back((short)answer);

            for (unsigned int j = 0; j < subr.params.size(); j++)
            {
                if (lc3_calculate(state, subr.params[j], value_calc))
                    throw "<in test-subr> A param expression " + subr.params[j] + " was malformed.";
                expected_stack.push_back((short)value_calc);
                params.push_back((short) value_calc);
            }

            // Code to get the students stack frame
            unsigned short actual_r6 = (unsigned short) r6;
            if (state.first_level_calls.size() >= 1)
            {
                const auto& call_info = state.first_level_calls[0];
                unsigned short subr_location = call_info.address;
                if (state.subroutines.find(subr_location) == state.subroutines.end())
                {
                    extra << "      [WARNING] Could not determine number of parameters for subroutine " <<
                        lc3_sym_rev_lookup(state, subr_location) << " at address " <<
                        std::hex << "0x" << subr_location << "\n";
                }
                unsigned short start = call_info.r6 + call_info.params.size();
                // Screams...
                if (start >= actual_r6)
                    extra << "      [WARNING] Could not get students stack frame.\n"
                             "      Is the student managing the stack correctly?\n";
                else
                    actual_stack.assign(state.mem + start, state.mem + actual_r6);
            }
            else if (state.first_level_calls.empty())
            {
                int num_params = subr.params.size();
                // Get at least the parameters student could probably not save anything...
                actual_stack.assign(state.mem + (actual_r6 - num_params), state.mem + actual_r6);
                // Get additional addresses modified
                unsigned short start = actual_r6 - num_params - 1;
                while (state.memory_ops.find(start) != state.memory_ops.end())
                {
                    if (!state.memory_ops[start].writes) break;
                    actual_stack.insert(actual_stack.begin(), state.mem[start]);
                    start--;
                }
            }

            for (unsigned int j = 0; j < expected_stack.size(); j++)
                expected << std::hex << "0x" << expected_stack[j] << " ";
            expected << " r5: " << std::hex << "0x" << (short)r5 <<
                        " r6: " << std::hex << "0x" << (actual_r6 - subr.params.size() - 1) <<
                        " r7: " << std::hex << "0x" << (short)(r7 + 1);


            for (unsigned int j = 0; j < actual_stack.size(); j++)
                actual << std::hex << "0x" << actual_stack[j] << " ";
            actual << " r5: " << std::hex << "0x" << state.regs[5] <<
                      " r6: " << std::hex << "0x" << state.regs[6] <<
                      " r7: " << std::hex << "0x" << state.regs[7];

            // now that I have all information available time for some checks.
            std::map<short, int> actual_stack_map;
            for (unsigned int j = 0; j < actual_stack.size(); j++)
                actual_stack_map[actual_stack[j]] += 1;

            int points = 0;
            // If they get something wrong then it will also be wrong in edit distance
            // so cut some slack if you get a value wrong.
            int ed_forgiveness = 0;

            if (actual_stack_map[(short)answer] > 0)
            {
                actual_stack_map[(short)answer] -= 1;
                points += subr.points_answer;
                extra << CHECK << ANSWER_FOUND << " +" << subr.points_answer << ".\n";
            }
            else
            {
                ed_forgiveness++;
                extra << MISS << ANSWER_FOUND << " -" << subr.points_answer << ".\n";
            }

            if (state.regs[6] == (short)(actual_r6 - subr.params.size() - 1))
            {
                points += subr.points_r6;
                extra << CHECK << R6_FOUND << " +" << subr.points_r6 << ".\n";
            }
            else
            {
                extra << MISS << R6_FOUND << " -" << subr.points_r6 << ".\n";
            }

            if (actual_stack_map[(short)r7] > 0 && state.regs[7] == (short)(r7+1))
            {
                actual_stack_map[(short)r7] -= 1;
                points += subr.points_r7;
                extra << CHECK << R7_FOUND << " +" << subr.points_r7 << ".\n";
            }
            else
            {
                // Don't count if just r7 was clobbered
                if (actual_stack_map[(short)r7] <= 0)
                    ed_forgiveness++;
                extra << MISS << R7_FOUND << " -" << subr.points_r7 << ".\n";
            }

            if (actual_stack_map[(short)r5] > 0 && state.regs[5] == (short)r5)
            {
                actual_stack_map[(short)r5] -= 1;
                points += subr.points_r5;
                extra << CHECK << R5_FOUND << " +" << subr.points_r5 << ".\n";
            }
            else
            {
                if (actual_stack_map[(short)r5] <= 0)
                    ed_forgiveness++;
                extra << MISS << R5_FOUND << " -" << subr.points_r5 << ".\n";
            }

            for (unsigned int j = 0; j < params.size(); j++)
            {
                if (actual_stack_map[params[j]] > 0)
                {
                    actual_stack_map[params[j]] -= 1;
                    points += subr.points_params;
                    extra << CHECK << params[j] << " " << PARAM_FOUND << " +" << subr.points_params << ".\n";
                }
                else
                {
                    ed_forgiveness++;
                    extra << MISS << params[j] << " " << PARAM_FOUND << " -" << subr.points_params << ".\n";
                }
            }

            bool all_locals_wrong = true;
            for (unsigned int j = 0; j < locals.size(); j++)
            {
                if (actual_stack_map[locals[j]] > 0)
                {
                    actual_stack_map[locals[j]] -= 1;
                    points += subr.points_locals;
                    all_locals_wrong = false;
                    extra << CHECK << locals[j] << " " << LOCAL_FOUND << " +" << subr.points_locals << ".\n";
                }
                else
                {
                    ed_forgiveness++;
                    extra << MISS << locals[j] << " " << LOCAL_FOUND << " -" << subr.points_locals << ".\n";
                }
            }

            // Subroutine calls check.
            std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> actual_calls(state.first_level_calls.begin(), state.first_level_calls.end());
            std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> expected_calls;
            for (const auto& expected_call : subr.calls)
            {
                lc3_subroutine_call_info info;
                int addr = lc3_sym_lookup(state, expected_call.name);
                if (addr == -1)
                    throw "Invalid subroutine name given in <call> " + expected_call.name;
                for (unsigned int i = 0; i < expected_call.params.size(); i++)
                {
                    int param;
                    if (lc3_calculate(state, expected_call.params[i], param) == -1)
                        throw "<in test-subr/call> param expression " + expected_call.params[i] + " was malformed";
                    info.params.push_back(param);
                }
                info.address = addr;
                info.r6 = 0;
                expected_calls.insert(info);
            }

            for (const auto& call : expected_calls)
            {
                std::stringstream call_name;
                call_name << lc3_sym_rev_lookup(state, call.address) << "(";
                if (state.subroutines.find(call.address) == state.subroutines.end())
                    call_name << "?";
                for (unsigned int i = 0; i < call.params.size(); i++)
                {

                    call_name << std::hex << "0x" << call.params[i];
                    if (i != call.params.size() - 1)
                        call_name << ",";
                }
                call_name << ")";

                if (actual_calls.find(call) != actual_calls.end())
                {
                    extra << CHECK << "Call " << call_name.str() << " made correctly.\n";
                    points += subr.points_calls;
                }
                else
                {
                    extra << MISS << "Call " << call_name.str() << " was not made.\n";
                }
            }
            for (const auto& call : actual_calls)
            {
                std::stringstream call_name;

                std::string name = lc3_sym_rev_lookup(state, call.address);
                if (name.empty())
                    call_name << "0x" << std::hex << call.address << "(";
                else
                    call_name << name << "(";
                if (state.subroutines.find(call.address) == state.subroutines.end())
                    call_name << "?";
                for (unsigned int i = 0; i < call.params.size(); i++)
                {

                    call_name << std::hex << "0x" << call.params[i];
                    if (i != call.params.size() - 1)
                        call_name << ",";
                }
                call_name << ")";

                if (expected_calls.find(call) == expected_calls.end())
                {
                    extra << MISS << "Unexpected Call " << call_name.str() << " made.\n";
                }
            }

            // Read answer check sigh...
            if (subr.points_read_answer > 0)
            {
                for (const auto& call : actual_calls)
                {
                    if (expected_calls.find(call) != expected_calls.end() && !call.params.empty())
                    {
                        if (state.memory_ops[call.r6 - 1].reads > 0)
                        {
                            extra << CHECK << "Read answer from stack.\n";
                            points += subr.points_read_answer;
                        }
                        else
                            extra << MISS << "Did not read answer from stack.\n";
                    }
                }
            }

            // If all local variables are wrong then it can be argued that they was saving registers
            // And forgot to save locals...
            if (all_locals_wrong)
            {
                // Bro do you even calling convention
                if (actual_stack.size() > subr.params.size() + 3)
                    // Truncate stack to last num_params + 3 elements the stuff we care about (don't do expected since ed forgiveness handles it).
                    actual_stack.erase(actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - subr.params.size() - 3));
                if (!subr.locals.empty())
                    extra << "      All locals were not found, so locals aren't included in structure check.\n";
            }
            else
            {
                if (actual_stack.size() > expected_stack.size())
                    expected_stack.insert(expected_stack.begin(), actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - expected_stack.size()));
            }

            int ed_grade = edit_distance(actual_stack, expected_stack);
            points -= (ed_grade - ed_forgiveness) * subr.deductions_edist;
            int mistakes = ed_grade - ed_forgiveness;


            if (mistakes == 0)
                extra << "      Found no structural mistakes in the stack.  No changes needed.\n";
            else
                extra << "      Found " << mistakes << " structural mistakes in stack -" << subr.deductions_edist * mistakes << ".\n";

            output.passed = (ed_grade == 0) && (ed_forgiveness == 0);
            output.extra_output += extra.str();
            output.earned = points;
        }

        test_passed = test_passed && output.passed;
        test_points += output.earned;
        test_max_points += output.points;

        output.expected = expected.str();
        output.actual = actual.str();
    }

    // Tear down
    delete state.input;
    delete state.output;
    delete state.warning;

    test.passed = test_passed;
    test.points = test_points;
    test.max_points = test_max_points;
}
Пример #10
0
/** DoLoadFile
  *
  * Handles loading an assembly file into the simulator
  */
void ComplxFrame::DoLoadFile(const LoadingOptions& opts)
{
    auto* config = wxConfigBase::Get();

    wxFileName filename(opts.file);
    bool randomize_registers = opts.registers == RANDOMIZE;
    bool randomize_memory = opts.memory == RANDOMIZE;
    short fill_registers = opts.registers;
    short fill_memory = opts.memory;

    lc3_init(state, randomize_registers, randomize_memory, fill_registers, fill_memory);
    state.pc = opts.pc;

    PostInit();

    // Now the actual loading
    if (opts.file.empty())
        return;

    lc3_state dummy_state;
    lc3_init(dummy_state);

    // Save the symbols
    std::map<std::string, unsigned short> symbol_table = state.symbols;
    std::map<unsigned short, std::string> rev_symbol_table = state.rev_symbols;

    state.symbols.clear();
    state.rev_symbols.clear();
    lc3_remove_plugins(state);

    bool tvt_modification = false;
    bool ivt_modification = false;
    bool subroutine_found = false;

    try
    {
        ///TODO should only make one call to lc3_assemble.
        std::vector<code_range> ranges;
        LC3AssembleOptions options;
        options.multiple_errors = false;
        lc3_assemble(dummy_state, filename.GetFullPath().ToStdString(), options);
        options.multiple_errors = true;
        options.warnings_as_errors = false;
        options.process_debug_comments = true;
        options.enable_warnings = false;
        options.disable_plugins = false;
        lc3_assemble(state, filename.GetFullPath().ToStdString(), ranges, options);

        // Update list of addresses modified for Show only Code/Data option.
        modified_addresses.clear();
        for (const auto& code_range : ranges)
            modified_addresses.push_back(ViewRange(code_range.location, code_range.location + code_range.size));
        /// TODO Automatically determine state of true traps and interrupts via the code ranges.
        // Dummy call to update hidden addresses.
        wxCommandEvent event;
        OnUpdateHideAddresses(event);
        // Check for TVT and IVT modification
        for (const auto& code_range : ranges)
        {
            if ((code_range.location >= 0 && code_range.location <= 0xFF) || (code_range.location + code_range.size >= 0 && code_range.location + code_range.size <= 0xFF))
                tvt_modification = true;
            if ((code_range.location >= 0x100 && code_range.location <= 0x1FF) || (code_range.location + code_range.size >= 0x100 && code_range.location + code_range.size <= 0x1FF))
                ivt_modification = true;
        }
        subroutine_found = DetectSubroutine(ranges);
    }
    catch (LC3AssembleException e)
    {
        wxMessageBox(wxString::Format("ERROR! %s", e.what()), wxString::Format("Loading %s failed", filename.GetFullName()));
        goto merge;
    }
    catch (std::vector<LC3AssembleException> e)
    {
        std::stringstream oss;
        for (unsigned int i = 0; i < e.size(); i++)
            oss << e[i].what() << std::endl;
        wxMessageBox(wxString::Format("ERROR! %s", oss.str()), wxString::Format("Loading %s failed", filename.GetFullName()));
        goto merge;
    }

    lc3_set_true_traps(state, opts.true_traps || tvt_modification);
    state.interrupt_enabled = opts.interrupts || ivt_modification;
    console->SetInput(opts.console_input);
    state.strict_execution = opts.strict_execution;
    // Update menus
    menuStateTrueTraps->Check(opts.true_traps || tvt_modification);
    menuStateInterrupts->Check(opts.interrupts || ivt_modification);
    menuStateStrictExecution->Check(opts.strict_execution);

    if (tvt_modification)
    {
        bool tvt_popup = config->Read("/firsttimetrap", "").IsEmpty();
        if (tvt_popup)
        {
            wxMessageBox("Pardon the interruption!\n"
                         "It appears you have loaded a file with a custom trap.\n"
                         "This will automatically enable true traps mode.\n"
                         "This will allow you to step into the code for the standard traps (IN,OUT,GETC,PUTS,HALT) and your own custom trap.\n"
                         "This notice to to remind you of the above, executing HALT will jump to some random code, but I assure you this random code is the code to HALT the LC-3.\n"
                         "If you'd rather stop the execution right at the HALT statement then put a breakpoint on your HALT statement.\n",
                         "Notice");
            config->Write("/firsttimetrap", "1");
        }
    }

    if (subroutine_found)
    {
        wxCommandEvent event;
        OnControlModeAdvanced(event);
        bool subroutine_popup = config->Read("/firsttimesubroutine", "").IsEmpty();
        if (subroutine_popup)
        {
            wxMessageBox("Pardon the interruption!\n"
                         "It appears you have loaded a file with a custom trap or subroutine.\n"
                         "You may notice 3 new buttons in the control area.\n"
                         "Next Line\n    Allows you to STEP OVER a subroutine or trap, meaning it will skip over it (but still execute it).\n"
                         "Prev Line\n    Allows you to BACK STEP OVER a subroutine or trap.\n"
                         "Finish\n    Allows you to STEP OUT of a subroutine, it finishes execution of it.\n\n"
                         "Another thing to note if you want to always step over/out a subroutine to select the subroutine label and select mark as blackbox.\n"
                         "If you use step on a JSR/JSRR/TRAP instruction that is blackboxed it will never step into it.\n"
                         "For more information Read The Manual :)\n"
                         , "Notice");
            config->Write("/firsttimesubroutine", "1");
        }
    }

    SetTitle(wxString::Format("%s - %s", base_title, filename.GetFullPath()));

merge:
    std::map<std::string, unsigned short>::const_iterator i;
    std::map<unsigned short, std::string>::const_iterator j;
    for (i = symbol_table.begin(); i != symbol_table.end(); ++i)
    {
        state.symbols[i->first] = i->second;
    }
    for (j = rev_symbol_table.begin(); j != rev_symbol_table.end(); ++j)
    {
        state.rev_symbols[j->first] = j->second;
    }

    UpdateStatus();
    UpdateRegisters();
    UpdateMemory();

    // Save in reload options
    reload_options = opts;

    // Update timestamps
    wxFileName file_loaded(reload_options.file);
    reload_options.file_modification_time = file_loaded.GetModificationTime();
}
Пример #11
0
void do_randomize(void)
{
    lc3_init(state, true, true);
    registers->Update();
    memory->Update();
}
Пример #12
0
void do_reset(void)
{
    lc3_init(state);
    registers->Update();
    memory->Update();
}
Пример #13
0
 LC3BasicTest()
 {
     lc3_init(state, false, false);
 }
Пример #14
0
int main(int argc, char **argv) {
	FILE *prog;
	lc3machine mach;

	/* We expect only one argument for the program... */
	if (argc != 2) {
		fprintf(stderr, "Usage: %s file.obj\n", argv[0]);
		return 1;
	}
	/* We want to open the file and make sure that it exists. */
	prog = fopen(argv[1], "rb");
	if (!prog) {
		fprintf(stderr, "Could not find file %s\n", argv[1]);
		return 2;
	}

	/* Make a call to lc3_init to initialize your lc3machine */
    lc3_init(&mach);
    
	/* Make a call to lc3_load to load the program */
    lc3_load(&mach, prog);
    fclose(prog);
    
	/* Print out start of program */
	printf("LC-3 simulator and debugger\n");
	printf("Written by Ryan Goodrich\n");

	/* Run this loop until we are told to stop debugging. */
    unsigned char emptyPrompt = 0;
    char userInput[30];
    int letter;
    int inputIndex = 0;
	while (1) {
		
        // check if there is a prompt on the screen
        if (!emptyPrompt)
            printf("%s", PROMPT), emptyPrompt = 1;
        
        else {
            
            // get the user input
            while ((letter = getchar()) != '\n')
                userInput[inputIndex < 30 ? inputIndex ++ : inputIndex] = letter;
            
            // check if input is exceeded buffer
            if (inputIndex > 29)
                printf("ERR: Input overflow\n");
            
            // run command if valid
            else {
                
                // clean out the rest of the buffer
                if (inputIndex) {
                    for (int i = inputIndex; i < 30; i ++)
                        userInput[i] = 0;
                }
                    
                // run command
                cmd_runprompt(&mach, userInput);
            }
            
            // rest input and prompt
            emptyPrompt = inputIndex = 0;
        }
	}

	return 0;
}