diff options
| -rw-r--r-- | rtl/core/fetch/fetch.sv | 4 | ||||
| -rw-r--r-- | sim/gdbstub.py | 23 | ||||
| -rwxr-xr-x | sim/sim.py | 9 | ||||
| -rw-r--r-- | tb/avalon.hpp | 2 | ||||
| -rw-r--r-- | tb/avalon.impl.hpp | 9 | ||||
| -rw-r--r-- | tb/top/conspiracion.cpp | 49 |
6 files changed, 82 insertions, 14 deletions
diff --git a/rtl/core/fetch/fetch.sv b/rtl/core/fetch/fetch.sv index c024e7d..ba9d677 100644 --- a/rtl/core/fetch/fetch.sv +++ b/rtl/core/fetch/fetch.sv @@ -7,7 +7,7 @@ module core_fetch rst_n, stall, fetched, - explicit_branch, + explicit_branch /*verilator public*/ /*verilator forceable*/, wr_pc, prefetch_flush, input ptr branch_target, @@ -24,7 +24,7 @@ module core_fetch fetch_head ); - ptr hold_addr, target; + ptr target /*verilator public*/ /*verilator forceable*/, hold_addr; logic branch, prefetch_ready, fetched_valid, discard, pending, next_pending; assign fetch = prefetch_ready && !discard; diff --git a/sim/gdbstub.py b/sim/gdbstub.py index 74d046c..3833da7 100644 --- a/sim/gdbstub.py +++ b/sim/gdbstub.py @@ -84,6 +84,9 @@ def yield_to_gdb(): out = b'OK' elif data == b'g': out = hexout(read_reg(gdb_reg(r)) for r in range(16)) + elif data[0] == b'G': + for reg, value in enumerate(hexin(data[1:])): + write_reg(reg, value) elif data[0] == b'm'[0]: addr, length = (int(x, 16) for x in data[1:].split(b',')) out = hexout(read_mem(addr, length, may_fail = True)) @@ -99,6 +102,9 @@ def yield_to_gdb(): elif data[0] == b'p'[0]: reg = gdb_reg(int(data[1:], 16)) out = hexout(read_reg(reg) if reg is not None else None) + elif data[0] == b'P'[0]: + reg, value = data[1:].split(b'=') + write_reg(gdb_reg(int(reg, 16)), hexin(value, single=True)) elif data == b's' and not dead: return 'step' else: @@ -107,7 +113,7 @@ def yield_to_gdb(): reply(out) def reply(out): - client.send(b'$' + out + b'#' + hexout(sum(out) & 0xff, 1)) + client.send(b'$' + out + b'#' + hexout(sum(out) & 0xff, size=1)) def gdb_reg(n): if 0 <= n < 8: @@ -147,7 +153,20 @@ def gdb_reg(n): print('bad gdb regnum:', n, file=sys.stderr) return None -def hexout(data, size=4): +def hexin(data, *, single=False): + if type(data) is bytes: + data = str(data, 'ascii') + + output = [] + for i in range(len(data) >> 3): + output.append(int.from_bytes(bytes.fromhex(data[i << 3:(i + 1) << 3]), 'little')) + + if single: + output, = output + + return output + +def hexout(data, *, size=4): if data is None: return b'' elif type(data) is bytes: @@ -73,6 +73,14 @@ all_regs = [ regs = {} read_reg = lambda r: regs.setdefault(r, 0) +def write_reg(reg, value): + assert halted + + value = unsigned(value) + regs[reg] = value + + print('patch-reg', value, reg, file=sim_end, flush=True) + dumped = [] halted = False @@ -278,6 +286,7 @@ module = importlib.util.module_from_spec(spec) prelude = { 'read_reg': read_reg, + 'write_reg': write_reg, 'read_mem': read_mem, 'write_mem': write_mem, 'assert_reg': assert_reg, diff --git a/tb/avalon.hpp b/tb/avalon.hpp index 763065c..347c8bd 100644 --- a/tb/avalon.hpp +++ b/tb/avalon.hpp @@ -81,7 +81,7 @@ namespace taller::avalon void bail() noexcept; bool dump(std::uint32_t addr, std::uint32_t &word); - void patch(std::uint32_t addr, std::uint32_t readdata); + bool patch(std::uint32_t addr, std::uint32_t readdata); private: struct binding diff --git a/tb/avalon.impl.hpp b/tb/avalon.impl.hpp index 4dee4f2..6f4bfb9 100644 --- a/tb/avalon.impl.hpp +++ b/tb/avalon.impl.hpp @@ -146,12 +146,15 @@ namespace taller::avalon } template<class Platform> - void interconnect<Platform>::patch(std::uint32_t addr, std::uint32_t writedata) + bool interconnect<Platform>::patch(std::uint32_t addr, std::uint32_t writedata) { std::uint32_t avl_address = addr << 2; auto *dev = resolve_external(avl_address); - assert(dev); + if(!dev) + { + return false; + } auto pos = (avl_address & ~dev->address_mask()) >> dev->word_bits(); @@ -159,6 +162,8 @@ namespace taller::avalon { continue; } + + return true; } template<class Platform> diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp index b7ec3eb..55798cc 100644 --- a/tb/top/conspiracion.cpp +++ b/tb/top/conspiracion.cpp @@ -17,6 +17,7 @@ #include "Vconspiracion_platform.h" #include "Vconspiracion_vga_domain.h" #include "Vconspiracion_core_control.h" +#include "Vconspiracion_core_fetch.h" #include "Vconspiracion_core_mmu.h" #include "Vconspiracion_core_psr.h" #include "Vconspiracion_core_regs.h" @@ -347,11 +348,11 @@ int main(int argc, char **argv) std::fclose(img_file); } + auto &core = *top.conspiracion->core; for(const auto &init : init_regs) { - auto ®s = *top.conspiracion->core->regs; - regs.a->file[init.index] = init.value; - regs.b->file[init.index] = init.value; + core.regs->a->file[init.index] = init.value; + core.regs->b->file[init.index] = init.value; } int time = 0; @@ -411,7 +412,6 @@ int main(int argc, char **argv) { std::fputs("=== dump-regs ===\n", ctrl); - const auto &core = *top.conspiracion->core; const auto ®file = core.regs->a->file; int i = 0; @@ -432,8 +432,8 @@ int main(int argc, char **argv) auto do_mem_dump = [&](const mem_region *dumps, std::size_t count) { - bool mmu_enabled = top.conspiracion->core->mmu->mmu_enable; - std::uint32_t ttbr = top.conspiracion->core->mmu->mmu_ttbr; + bool mmu_enabled = core.mmu->mmu_enable; + std::uint32_t ttbr = core.mmu->mmu_ttbr; auto pagewalk = [&](std::uint32_t &addr) { @@ -519,6 +519,8 @@ int main(int argc, char **argv) std::signal(SIGUSR1, async_halt_handler); + core.fetch->explicit_branch__VforceVal = 1; + unsigned i = 0; // Abuse unsigned overflow (cycles is UINT_MAX by default) while(!failed && i + 1 <= *cycles) @@ -536,7 +538,7 @@ int main(int argc, char **argv) halt_or_fail: top.step = 0; - top.halt = 0; + core.fetch->target__VforceVal = core.control->pc; do_reg_dump(); std::fprintf(ctrl, "=== %s ===\n", failed ? "fault" : "halted"); @@ -600,11 +602,44 @@ halt_or_fail: avl.patch(addr++, word); } + } else if(!std::strcmp(cmd, "patch-reg")) + { + std::uint32_t value; + std::sscanf(std::strtok(nullptr, " "), "%u", &value); + + const char *name = std::strtok(nullptr, " "); + if(!std::strcmp(name, "pc")) + { + core.fetch->target__VforceVal = value >> 2; + } else + { + std::size_t index = 0; + for(const char *reg : gp_regs) + { + if(!strcmp(name, reg)) + { + core.regs->a->file[index] = value; + core.regs->b->file[index] = value; + break; + } + + ++index; + } + } } } std::free(line); async_halt = 0; + + core.fetch->target__VforceEn = 0xffff'ffff; + core.fetch->explicit_branch__VforceEn = 1; + + cycle(); + top.halt = 0; + + core.fetch->target__VforceEn = 0; + core.fetch->explicit_branch__VforceEn = 0; } if(!no_tty) |
