From a473a5b15d6aadf147306e0ed6533ece62f4e15c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 May 2024 15:27:48 +0200 Subject: [PATCH 1/4] KW11-L pulse-rate now depends on the (estimated) cycle count --- cpu.cpp | 18 ++++++++++++------ cpu.h | 2 ++ kw11-l.cpp | 26 +++++++++++++++----------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 103dc01..2cdc883 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -18,6 +18,12 @@ #define IS_0(x, wm) ((wm) == wm_byte ? ((x) & 0xff) == 0 : (x) == 0) +// see https://retrocomputing.stackexchange.com/questions/6960/what-was-the-clock-speed-and-ips-for-the-original-pdp-11 +constexpr const double pdp11_clock_cycle = 150; // ns, for the 11/70 +constexpr const double pdp11_MHz = 1000.0 / pdp11_clock_cycle; +constexpr const double pdp11_avg_cycles_per_instruction = (1 + 5) / 2.0; +constexpr const double pdp11_estimated_mips = pdp11_MHz / pdp11_avg_cycles_per_instruction; + cpu::cpu(bus *const b, std::atomic_uint32_t *const event) : b(b), event(event) { reset(); @@ -97,15 +103,15 @@ std::tuple cpu::get_mips_rel_speed(c double mips = t_diff ? instr_count / double(t_diff) : 0; - // see https://retrocomputing.stackexchange.com/questions/6960/what-was-the-clock-speed-and-ips-for-the-original-pdp-11 - constexpr double pdp11_clock_cycle = 150; // ns, for the 11/70 - constexpr double pdp11_MHz = 1000.0 / pdp11_clock_cycle; - constexpr double pdp11_avg_cycles_per_instruction = (1 + 5) / 2.0; - constexpr double pdp11_estimated_mips = pdp11_MHz / pdp11_avg_cycles_per_instruction; - return { mips, mips * 100 / pdp11_estimated_mips, instr_count, t_diff, wait_time }; } +uint32_t cpu::get_effective_run_time(const uint64_t instruction_count) const +{ + // division is to go from ns to ms + return instruction_count * pdp11_clock_cycle / 1000000l; +} + void cpu::add_to_stack_trace(const uint16_t p) { auto da = disassemble(p); diff --git a/cpu.h b/cpu.h index 9c5c40f..56e37eb 100644 --- a/cpu.h +++ b/cpu.h @@ -133,6 +133,8 @@ public: uint64_t get_instructions_executed_count() const; uint64_t get_wait_time() const { return wait_time; } std::tuple get_mips_rel_speed(const std::optional & instruction_count, const std::optional & t_diff_1s) const; + // how many ms would've really passed when executing `instruction_count` instructions + uint32_t get_effective_run_time(const uint64_t instruction_count) const; bool get_debug() const { return debug_mode; } void set_debug(const bool d) { debug_mode = d; stacktrace.clear(); } diff --git a/kw11-l.cpp b/kw11-l.cpp index 2d23054..6114ee7 100644 --- a/kw11-l.cpp +++ b/kw11-l.cpp @@ -68,22 +68,26 @@ void kw11_l::operator()() TRACE("Starting KW11-L thread"); + uint64_t prev_cycle_count = b->getCpu()->get_instructions_executed_count(); + while(!stop_flag) { if (*cnsl->get_running_flag()) { - set_lf_crs_b7(); - - if (get_lf_crs() & 64) - b->getCpu()->queue_interrupt(6, 0100); + myusleep(1000000 / 100); // 100 Hz - // TODO: depending on cpu cycles processed -#if defined(ESP32) - myusleep(1000000 / 20); // 50ms -#else - myusleep(1000000 / 50); // 20ms -#endif + uint64_t current_cycle_count = b->getCpu()->get_instructions_executed_count(); + uint32_t took_ms = b->getCpu()->get_effective_run_time(current_cycle_count - prev_cycle_count); + + if (took_ms >= 1000 / 50) { + set_lf_crs_b7(); + + if (get_lf_crs() & 64) + b->getCpu()->queue_interrupt(6, 0100); + + prev_cycle_count = current_cycle_count; + } } else { - myusleep(1000000 / 10); // 100ms + myusleep(1000000 / 10); // 10 Hz } } From b77f1cf9d359af300547a89d01c8b3e55f07f9ed Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 May 2024 15:29:30 +0200 Subject: [PATCH 2/4] fix for cycles per instruction --- cpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.cpp b/cpu.cpp index 2cdc883..6eca7c0 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -109,7 +109,7 @@ std::tuple cpu::get_mips_rel_speed(c uint32_t cpu::get_effective_run_time(const uint64_t instruction_count) const { // division is to go from ns to ms - return instruction_count * pdp11_clock_cycle / 1000000l; + return instruction_count * pdp11_avg_cycles_per_instruction * pdp11_clock_cycle / 1000000l; } void cpu::add_to_stack_trace(const uint16_t p) From cd70bc96ccb9b5ea4bd0ce7bb21e318c640831bb Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 May 2024 15:55:22 +0200 Subject: [PATCH 3/4] load BIC/LDA file --- debugger.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/debugger.cpp b/debugger.cpp index cf57419..bda975d 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -987,6 +987,19 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (parts[0] == "bic" && parts.size() == 2) { + auto rc = load_tape(b, parts[1].c_str()); + if (rc.has_value()) { + c->setPC(rc.value()); + + cnsl->put_string_lf("BIC/LDA file loaded"); + } + else { + cnsl->put_string_lf("BIC/LDA failed to load"); + } + + continue; + } else if (parts[0] == "lt") { if (parts.size() == 2) tm11_load_tape(cnsl, b, parts[1]); @@ -1053,6 +1066,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto "setmem - set memory (a=) to value (v=), both in octal, one byte", "toggle - set switch (s=, 0...15 (decimal)) of the front panel to state (t=, 0 or 1)", "cls - clear screen", + "bic - run BIC/LDA file", "lt - load tape (parameter is filename)", "ult - unload tape", "stats - show run statistics", From 722cdc98e767c8053ce8461e012480defa40c78d Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 May 2024 16:04:59 +0200 Subject: [PATCH 4/4] dir/ls --- debugger.cpp | 159 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 66 deletions(-) diff --git a/debugger.cpp b/debugger.cpp index bda975d..3b22212 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -78,55 +78,94 @@ std::optional select_nbd_server(console *const cnsl) } #endif -std::optional select_host_file(console *const c) +void start_disk(console *const cnsl) { - for(;;) { -#if defined(linux) - DIR *dir = opendir("."); - if (!dir) { - c->put_string_lf("Cannot access directory"); - return { }; - } + static bool disk_started = false; + if (disk_started) + return; - dirent *dr = nullptr; - while((dr = readdir(dir))) { - struct stat st { }; +#if defined(ESP32) + cnsl->put_string_lf(format("MISO: %d", int(MISO))); + cnsl->put_string_lf(format("MOSI: %d", int(MOSI))); + cnsl->put_string_lf(format("SCK : %d", int(SCK ))); + cnsl->put_string_lf(format("SS : %d", int(SS ))); - if (stat(dr->d_name, &st) == 0) - c->put_string_lf(format("%s\t\t%ld", dr->d_name, st.st_size)); - } - - closedir(dir); -#elif defined(BUILD_FOR_RP2040) - File root = SD.open("/"); - - for(;;) { - auto entry = root.openNextFile(); - if (!entry) - break; - - if (!entry.isDirectory()) { - c->put_string(entry.name()); - c->put_string("\t\t"); - c->put_string_lf(format("%ld", entry.size())); - } - - entry.close(); - } -#elif defined(_WIN32) -#else - SD.ls("/", LS_DATE | LS_SIZE | LS_R); #endif - c->flush_input(); +#if defined(SHA2017) + if (SD.begin(21, SD_SCK_MHZ(10))) + disk_started = true; + else + SD.initErrorHalt(); +#elif !defined(BUILD_FOR_RP2040) + if (SD.begin(SS, SD_SCK_MHZ(15))) + disk_started = true; + else { + auto err = SD.sdErrorCode(); + if (err) + cnsl->put_string_lf(format("SDerror: 0x%x, data: 0x%x", err, SD.sdErrorData())); + else + cnsl->put_string_lf("Failed to initialize SD card"); + } +#endif +} - std::string selected_file = c->read_line("Enter filename (or empty to abort): "); +void ls_l(console *const cnsl) +{ + start_disk(cnsl); + +#if defined(linux) + DIR *dir = opendir("."); + if (!dir) { + cnsl->put_string_lf("Cannot access directory"); + return { }; + } + + dirent *dr = nullptr; + while((dr = readdir(dir))) { + struct stat st { }; + + if (stat(dr->d_name, &st) == 0) + cnsl->put_string_lf(format("%s\t\t%ld", dr->d_name, st.st_size)); + } + + closedir(dir); +#elif defined(BUILD_FOR_RP2040) + File root = SD.open("/"); + + for(;;) { + auto entry = root.openNextFile(); + if (!entry) + break; + + if (!entry.isDirectory()) { + cnsl->put_string(entry.name()); + cnsl->put_string("\t\t"); + cnsl->put_string_lf(format("%ld", entry.size())); + } + + entry.close(); + } +#elif defined(_WIN32) +#else + SD.ls("/", LS_DATE | LS_SIZE | LS_R); +#endif +} + +std::optional select_host_file(console *const cnsl) +{ + for(;;) { + ls_l(cnsl); + + cnsl->flush_input(); + + std::string selected_file = cnsl->read_line("Enter filename (or empty to abort): "); if (selected_file.empty()) return { }; - c->put_string("Opening file: "); - c->put_string_lf(selected_file.c_str()); + cnsl->put_string("Opening file: "); + cnsl->put_string_lf(selected_file.c_str()); bool can_open_file = false; @@ -143,41 +182,23 @@ std::optional select_host_file(console *const c) if (can_open_file) return selected_file; - c->put_string_lf("open failed"); + cnsl->put_string_lf("open failed"); } } // disk image files -std::optional select_disk_file(console *const c) +std::optional select_disk_file(console *const cnsl) { + start_disk(cnsl); + #if IS_POSIX || defined(_WIN32) - c->put_string_lf("Files in current directory: "); + cnsl->put_string_lf("Files in current directory: "); #else - c->put_string_lf(format("MISO: %d", int(MISO))); - c->put_string_lf(format("MOSI: %d", int(MOSI))); - c->put_string_lf(format("SCK : %d", int(SCK ))); - c->put_string_lf(format("SS : %d", int(SS ))); - - c->put_string_lf("Files on SD-card:"); - -#if defined(SHA2017) - if (!SD.begin(21, SD_SCK_MHZ(10))) - SD.initErrorHalt(); -#elif !defined(BUILD_FOR_RP2040) - if (!SD.begin(SS, SD_SCK_MHZ(15))) { - auto err = SD.sdErrorCode(); - if (err) - c->put_string_lf(format("SDerror: 0x%x, data: 0x%x", err, SD.sdErrorData())); - else - c->put_string_lf("Failed to initialize SD card"); - - return { }; - } -#endif + cnsl->put_string_lf("Files on SD-card:"); #endif for(;;) { - auto selected_file = select_host_file(c); + auto selected_file = select_host_file(cnsl); if (selected_file.has_value() == false) break; @@ -189,8 +210,8 @@ std::optional select_disk_file(console *const c) #endif if (!temp->begin(false)) { - c->put_string("Cannot use: "); - c->put_string_lf(selected_file.value().c_str()); + cnsl->put_string("Cannot use: "); + cnsl->put_string_lf(selected_file.value().c_str()); delete temp; @@ -1008,6 +1029,11 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (cmd == "dir" || cmd == "ls") { + ls_l(cnsl); + + continue; + } else if (cmd == "ult") { tm11_unload_tape(b); @@ -1066,6 +1092,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto "setmem - set memory (a=) to value (v=), both in octal, one byte", "toggle - set switch (s=, 0...15 (decimal)) of the front panel to state (t=, 0 or 1)", "cls - clear screen", + "dir - list files", "bic - run BIC/LDA file", "lt - load tape (parameter is filename)", "ult - unload tape",