Skip to content

Commit

Permalink
sim: remove simstate, add read/write reg methods to backend api for d…
Browse files Browse the repository at this point in the history
…irect access
  • Loading branch information
saursin committed May 6, 2024
1 parent e7f3784 commit 9e034de
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 228 deletions.
32 changes: 20 additions & 12 deletions sim/atomsim.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "atomsim.hpp"
#include "simstate.hpp"
#include <iostream>
#include "util.hpp"

Expand Down Expand Up @@ -57,14 +56,11 @@ int Atomsim::run()
// *** Simulation Loop ***
while (bkend_running_)
{
// Refresh state
backend_.refresh_state();

int breakpoint_hit = -1;

// Evaluate breakpoints (early)
for(int i=0; i<NUM_MAX_BREAKPOINTS; i++) {
if(breakpoints_[i].active && breakpoints_[i].addr == simstate_.state_.pc_e){
if(breakpoints_[i].active && breakpoints_[i].addr == backend_.read_reg("pc")){
breakpoint_hit = i;
break;
}
Expand All @@ -78,17 +74,29 @@ int Atomsim::run()

if(breakpoint_hit != -1) {
// Make sure we enter debug mode after breakpoint hit
printf("Breakpoint %d hit %s0x%08x%s\n", breakpoint_hit, ansicode(FG_BLUE), simstate_.state_.pc_e, ansicode(FG_RESET));
printf("Breakpoint %d hit %s0x%08lx%s\n", breakpoint_hit, ansicode(FG_BLUE), backend_.read_reg("pc"), ansicode(FG_RESET));
in_debug_mode_ = true;
pending_steps = 0;
}

// check ebreak
if(simstate_.state_.ins_e == RV_INSTR_EBREAK) {
printf("EBreak hit at %ld ticks, PC=%s0x%08x%s\n", simstate_.state_.tickcount_total, ansicode(FG_BLUE), simstate_.state_.pc_e, ansicode(FG_RESET));

if(sim_config_.dump_on_ebreak_flag) // For SCAR
simstate_.dump_simstate(sim_config_.dump_file);
if(backend_.read_reg("ir") == RV_INSTR_EBREAK) {
printf("EBreak hit at %ld ticks, PC=%s0x%08lx%s\n", backend_.get_total_tick_count() , ansicode(FG_BLUE), backend_.read_reg("pc"), ansicode(FG_RESET));

if(sim_config_.dump_on_ebreak_flag){ // For SCAR
// Temporarily redirect stdout to file
FILE *stream;
if((stream = freopen(sim_config_.dump_file.c_str(), "w", stdout)) == NULL)
Atomsim_exception("Cannot open dump file");

// call info command
cmd_info({"reg", "--no-alt-names"});

// restore stdout
stream = freopen("/dev/tty", "w", stdout);
if(sim_config_.verbose_flag)
printf("State dumped to: %s\n", sim_config_.dump_file.c_str());
}

// ebreak hit while debug mode was enabled through cli
if(sim_config_.debug_flag) {
Expand All @@ -103,7 +111,7 @@ int Atomsim::run()
}

// check sim iterations
if(simstate_.state_.tickcount_total > sim_config_.maxitr) {
if(backend_.get_total_tick_count() > sim_config_.maxitr) {
throwError("SIM0", "Simulation iterations exceeded maxitr("+std::to_string(sim_config_.maxitr)+")\n");
exitcode = EXIT_FAILURE;
break;
Expand Down
16 changes: 0 additions & 16 deletions sim/atomsim.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// #include <memory>

#include TARGET_HEADER
#include "simstate.hpp"

enum Rcode{
RC_NONE, RC_OK, RC_STEP, RC_RUN, RC_EXIT
Expand Down Expand Up @@ -77,11 +76,6 @@ class Atomsim
* @brief Backend object
*/
Backend_atomsim backend_;

/**
* @brief Middle-end object (cached state of backend)
*/
Simstate simstate_;

/**
* @brief tracks if the VCD trace is opened
Expand All @@ -100,16 +94,6 @@ class Atomsim
*/
std::map<uint32_t, DisassembledLine> disassembly_;

/**
* @brief Register ABI names used in debug display
*/
const std::vector<std::string> reg_names_ =
{
"x0 (zero) ", "x1 (ra) ", "x2 (sp) ", "x3 (gp) ", "x4 (tp) ", "x5 (t0) ", "x6 (t1) ", "x7 (t2) ",
"x8 (s0/fp)", "x9 (s1) ", "x10 (a0) ", "x11 (a1) ", "x12 (a2) ", "x13 (a3) ", "x14 (a4) ", "x15 (a5) ",
"x16 (a6) ", "x17 (a7) ", "x18 (s2) ", "x19 (s3) ", "x20 (s4) ", "x21 (s5) ", "x22 (s6) ", "x23 (s7) ",
"x24 (s8) ", "x25 (s9) ", "x26 (s10) ", "x27 (s11) ", "x28 (t3) ", "x29 (t4) ", "x30 (t5) ", "x31 (t6) "
};

friend class Backend_atomsim;

Expand Down
105 changes: 85 additions & 20 deletions sim/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@

#include <string>

enum Regwidth_t {
R8=8,
R16=16,
R32=32,
R64=64
};

struct ArchReg_t {
std::string name;
std::string alt_name;
Regwidth_t width;
void * ptr;
bool is_arch_reg;
};

// Forward declaration
class Atomsim;
class Simstate;

/**
* @brief Backend class
Expand All @@ -27,7 +40,7 @@ class Backend
{
public:

Backend(Atomsim *sim_ptr, Simstate *simstate_ptr);
Backend(Atomsim *sim_ptr);

/**
* @brief Get the Target Name [** OVERRIDE **]
Expand All @@ -40,12 +53,6 @@ class Backend
*/
void reset();

/**
* @brief probe all internal signals and registers and
* update state of middle-end [** OVERRIDE **]
*/
virtual void refresh_state() = 0;

/**
* @brief Tick for one cycle
*/
Expand Down Expand Up @@ -100,39 +107,51 @@ class Backend
*/
virtual void store(const uint32_t start_addr, uint8_t *buf, const uint32_t buf_sz);

/**
* @brief read register value [** MAY OVERRIDE **]
*
* @param reg_id register ID
*/
virtual uint64_t read_reg(const std::string name);

/**
* @brief write register value [** MAY OVERRIDE **]
*
* @param reg_id register ID
* @param buf value
*/
virtual void write_reg(const std::string name, uint64_t value);

protected:
/**
* @brief Pointer to Atomsim object
*/
Atomsim *sim_;

/**
* @brief Pointer to middle-end
*/
Simstate *simstate_;

/**
* @brief Pointer to testbench object
* NOTE: To be initialized and deleted by child class
*/
Testbench<VTarget> *tb;

/**
* @brief Map or architectural registers
*/
std::vector<ArchReg_t> regs_;

friend class Atomsim;
};


template <class VTarget>
Backend<VTarget>::Backend(Atomsim *sim_ptr, Simstate *simstate_ptr):
sim_(sim_ptr),
simstate_(simstate_ptr)
Backend<VTarget>::Backend(Atomsim *sim_ptr):
sim_(sim_ptr)
{}

template <class VTarget>
void Backend<VTarget>::reset()
{
tb->reset();
// tb->m_core->eval();

// Update simstate
refresh_state();
}

template <class VTarget>
Expand Down Expand Up @@ -185,4 +204,50 @@ template <class VTarget>
void Backend<VTarget>::store(const uint32_t /*start_addr*/, uint8_t */*buf*/, const uint32_t /*buf_sz*/)
{
throw Atomsim_exception("storing to current target's memory is not supported");
}

template <class VTarget>
uint64_t Backend<VTarget>::read_reg(const std::string name)
{
if (regs_.size() == 0)
throw Atomsim_exception("Reading register value in current target is not supported");

uint64_t val;
for(auto it = regs_.begin(); it != regs_.end(); it++){
if(it->name == name || it->alt_name == name) {
switch(it->width){
case R8: val = *((uint64_t*)it->ptr) & 0xffULL; break;
case R16: val = *((uint64_t*)it->ptr) & 0xffffULL; break;
case R32: val = *((uint64_t*)it->ptr) & 0xffffffffULL; break;
case R64:
default:
val = *((uint64_t*)it->ptr); break;
}
return val;
}
}

throw Atomsim_exception("Invalid register: " + name);
}

template <class VTarget>
void Backend<VTarget>::write_reg(const std::string name, uint64_t value)
{
if (regs_.size() == 0)
throw Atomsim_exception("W`riting register value in current target is not supported");

for(auto it = regs_.begin(); it != regs_.end(); it++){
if(it->name == name || it->alt_name == name) {
switch(it->width){
case R8: *((uint8_t*)it->ptr) = (uint8_t) (value & 0xffULL); break;
case R16: *((uint16_t*)it->ptr) = (uint16_t) (value & 0xffffULL); break;
case R32: *((uint32_t*)it->ptr) = (uint32_t) (value & 0xffffffffULL); break;
case R64:
default:
*((uint64_t*)it->ptr) = value; break;
}
}
}

throw Atomsim_exception("Invalid register: " + name);
}
40 changes: 10 additions & 30 deletions sim/backend_atombones.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
#include "backend_atombones.hpp"

#include "atomsim.hpp"
#include "simstate.hpp"
// #include "testbench.hpp"
#include "memory.hpp"
#include "vuart.hpp"
#include "except.hpp"
#include "util.hpp"
#include "rvdefs.hpp"

#include "build/verilated/VAtomBones_headers.h"

#include "elfio/elfio.hpp"

#define UART_ADDR 0x40000000



Backend_atomsim::Backend_atomsim(Atomsim * sim, Backend_config config):
Backend(sim, &(sim->simstate_)),
Backend(sim),
config_(config),
using_vuart_(config.vuart_portname != "")
{
Expand All @@ -34,7 +31,14 @@ Backend_atomsim::Backend_atomsim(Atomsim * sim, Backend_config config):
{
std::cerr << e.what() << '\n';
}


// Construct reg map
regs_.push_back({.name="pc", .alt_name="", .width=R32, .ptr=(void *)&tb->m_core->AtomBones->atom_core->ProgramCounter_Old, .is_arch_reg=false});
regs_.push_back({.name="ir", .alt_name="", .width=R32, .ptr=(void *)&tb->m_core->AtomBones->atom_core->InstructionRegister, .is_arch_reg=false});
for (int i=0; i<32; i++) {
std::string regname = "x"+std::to_string(i);
regs_.push_back({.name=regname, .alt_name=rv_abi_regnames[i], .width=R32, .ptr=(void *)&tb->m_core->AtomBones->atom_core->rf->regs[i], .is_arch_reg=true});
}

// ====== Initialize ========
// Initialize memory
Expand Down Expand Up @@ -163,30 +167,6 @@ void Backend_atomsim::service_mem_req()
}


void Backend_atomsim::refresh_state()
{
// Get PC
simstate_->state_.pc_f = tb->m_core->AtomBones->atom_core->ProgramCounter;
simstate_->state_.pc_e = tb->m_core->AtomBones->atom_core->ProgramCounter_Old;

// Get IR
simstate_->state_.ins_e = tb->m_core->AtomBones->atom_core->InstructionRegister;

// Get Regs
for(int i=0; i<32; i++)
{
simstate_->state_.rf[i] = tb->m_core->AtomBones->atom_core->rf->regs[i];
}

// Get Signals
simstate_->signals_.jump_decision = tb->m_core->AtomBones->atom_core->__PVT__jump_decision;

// get Tickcounts
simstate_->state_.tickcount = tb->m_tickcount;
simstate_->state_.tickcount_total = tb->m_tickcount_total;
}


int Backend_atomsim::tick()
{
// return if backend finished
Expand Down
2 changes: 0 additions & 2 deletions sim/backend_atombones.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ class Backend_atomsim: public Backend<VAtomBones>
*/
void service_mem_req();

void refresh_state();

void UART();

int tick();
Expand Down
Loading

0 comments on commit 9e034de

Please sign in to comment.