Implemented basic HiFive1-like platform with PLL,tracing etc.

This commit is contained in:
Eyck Jentzsch 2018-07-13 20:04:07 +02:00
parent b28595445c
commit a899d30556
25 changed files with 268 additions and 112 deletions

@ -1 +1 @@
Subproject commit 34abe11e782335ae02dd74a3e47ae8bb366abc25 Subproject commit 31263d4aaa6a7f01914c2decead091dc968f30d3

View File

@ -16,14 +16,17 @@ namespace sysc {
class system: sc_core::sc_module { class system: sc_core::sc_module {
public: public:
SC_HAS_PROCESS(system);
system(sc_core::sc_module_name nm); system(sc_core::sc_module_name nm);
virtual ~system(); virtual ~system();
sc_core::sc_vector<tlm::tlm_signal<sc_dt::sc_logic>> s_gpio;
private: private:
sc_core::sc_vector<tlm::tlm_signal<sc_dt::sc_logic>> s_gpio;
sc_core::sc_signal<bool> s_rst_n;
sysc::platform i_platform; sysc::platform i_platform;
sysc::terminal i_terminal; sysc::terminal i_terminal;
void gen_por();
}; };
} }

View File

@ -47,13 +47,17 @@ class aon : public sc_core::sc_module, public scc::tlm_target<> {
public: public:
SC_HAS_PROCESS(aon); SC_HAS_PROCESS(aon);
sc_core::sc_in<sc_core::sc_time> clk_i; sc_core::sc_in<sc_core::sc_time> clk_i;
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> erst_n_i;
sc_core::sc_out<sc_core::sc_time> lfclkc_o;
sc_core::sc_out<bool> rst_o;
aon(sc_core::sc_module_name nm); aon(sc_core::sc_module_name nm);
virtual ~aon() override; // need to keep it in source file because of fwd declaration of aon_regs virtual ~aon() override; // need to keep it in source file because of fwd declaration of aon_regs
protected: protected:
void start_of_simulation() override;
void clock_cb(); void clock_cb();
void reset_cb(); void reset_cb();
void reset_internal_cb();
sc_core::sc_time clk; sc_core::sc_time clk;
std::unique_ptr<aon_regs> regs; std::unique_ptr<aon_regs> regs;
}; };

View File

@ -134,6 +134,7 @@ protected:
void start_of_simulation(); void start_of_simulation();
void run(); void run();
void clk_cb(); void clk_cb();
void rst_cb();
void sw_irq_cb(); void sw_irq_cb();
void timer_irq_cb(); void timer_irq_cb();
void global_irq_cb(); void global_irq_cb();

View File

@ -95,7 +95,7 @@ public:
inline sysc::prci_regs::prci_regs(sc_core::sc_module_name nm) inline sysc::prci_regs::prci_regs(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm)
, NAMED(hfrosccfg, r_hfrosccfg, 0, *this) , NAMED(hfrosccfg, r_hfrosccfg, 0, *this)
, NAMED(hfxosccfg, r_hfxosccfg, 0, *this) , NAMED(hfxosccfg, r_hfxosccfg, 0x40000000, *this)
, NAMED(pllcfg, r_pllcfg, 0, *this) , NAMED(pllcfg, r_pllcfg, 0, *this)
, NAMED(plloutdiv, r_plloutdiv, 0, *this) , NAMED(plloutdiv, r_plloutdiv, 0, *this)
, NAMED(coreclkcfg, r_coreclkcfg, 0, *this) , NAMED(coreclkcfg, r_coreclkcfg, 0, *this)

View File

@ -77,8 +77,13 @@ protected:
void forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp); void forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp);
void iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay); void iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay);
sc_core::sc_time clk; sc_core::sc_time clk;
std::array<bool, 32> last_iof0, last_iof1;
std::unique_ptr<gpio_regs> regs; std::unique_ptr<gpio_regs> regs;
std::shared_ptr<sysc::WsHandler> handler; std::shared_ptr<sysc::WsHandler> handler;
private:
tlm::tlm_phase write_output(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, size_t i, sc_dt::sc_logic val);
void enable_outputs(uint32_t new_data);
}; };
} /* namespace sysc */ } /* namespace sysc */

View File

@ -63,6 +63,8 @@ public:
sc_core::sc_vector<tlm::tlm_signal_initiator_socket<sc_dt::sc_logic>> pins_o; sc_core::sc_vector<tlm::tlm_signal_initiator_socket<sc_dt::sc_logic>> pins_o;
sc_core::sc_vector<tlm::tlm_signal_target_socket<sc_dt::sc_logic>> pins_i; sc_core::sc_vector<tlm::tlm_signal_target_socket<sc_dt::sc_logic>> pins_i;
sc_core::sc_in<bool> erst_n;
platform(sc_core::sc_module_name nm); platform(sc_core::sc_module_name nm);
private: private:

View File

@ -46,18 +46,21 @@ class prci_regs;
class prci : public sc_core::sc_module, public scc::tlm_target<> { class prci : public sc_core::sc_module, public scc::tlm_target<> {
public: public:
SC_HAS_PROCESS(prci); SC_HAS_PROCESS(prci);
sc_core::sc_in<sc_core::sc_time> clk_i; sc_core::sc_port<sc_core::sc_signal_in_if<sc_core::sc_time>,1,SC_ZERO_OR_MORE_BOUND> hfxosc_i;
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
sc_core::sc_out<sc_core::sc_time> hfclk_o;
prci(sc_core::sc_module_name nm); prci(sc_core::sc_module_name nm);
virtual ~prci() override; // need to keep it in source file because of fwd declaration of prci_regs virtual ~prci() override; // need to keep it in source file because of fwd declaration of prci_regs
protected: protected:
void clock_cb(); void hfxosc_cb();
void reset_cb(); void reset_cb();
void hfrosc_en_cb(); void hfrosc_en_cb();
sc_core::sc_time clk; void hfxosc_en_cb();
void update_hfclk();
sc_core::sc_time hfxosc_clk, hfrosc_clk, pll_clk, hfclk;
std::unique_ptr<prci_regs> regs; std::unique_ptr<prci_regs> regs;
sc_core::sc_event hfrosc_en_evt; sc_core::sc_event hfrosc_en_evt, hfxosc_en_evt;
}; };
} /* namespace sysc */ } /* namespace sysc */

View File

@ -3,17 +3,17 @@ FILE(GLOB RiscVSCHeaders *.h */*.h)
FILE(GLOB RiscvSCSources sysc/*.cpp) FILE(GLOB RiscvSCSources sysc/*.cpp)
set(LIB_HEADERS ${RiscVSCHeaders} ) set(LIB_HEADERS ${RiscVSCHeaders} )
set(LIB_SOURCES ${RiscvSCSources} set(LIB_SOURCES ${RiscvSCSources} )
)
set(APP_HEADERS ) set(APP_HEADERS )
set(APP_SOURCES sc_main.cpp)
set(APP_SOURCES sc_main.cpp
)
# Define two variables in order not to repeat ourselves. # Define two variables in order not to repeat ourselves.
set(LIBRARY_NAME risc-v.sc) set(LIBRARY_NAME risc-v.sc)
## the following setting needs to be consistent with the library
#add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS)
# Define the library # Define the library
add_library(${LIBRARY_NAME} ${LIB_SOURCES}) add_library(${LIBRARY_NAME} ${LIB_SOURCES})

View File

@ -54,6 +54,16 @@ const size_t SUCCESS = 0;
const size_t ERROR_UNHANDLED_EXCEPTION = 2; const size_t ERROR_UNHANDLED_EXCEPTION = 2;
} // namespace } // namespace
#include "sysc/kernel/sc_externs.h"
int
main( int argc, char* argv[]){
#ifdef _POSIX_SOURCE
putenv(const_cast<char*>("SC_SIGNAL_WRITE_CHECK=DISABLE"));
putenv(const_cast<char*>("SC_VCD_SCOPES=ENABLE"));
#endif
return sc_core::sc_elab_and_sim( argc, argv );
}
int sc_main(int argc, char *argv[]) { int sc_main(int argc, char *argv[]) {
// sc_report_handler::set_handler(my_report_handler); // sc_report_handler::set_handler(my_report_handler);
scc::Logger<>::reporting_level() = logging::ERROR; scc::Logger<>::reporting_level() = logging::ERROR;
@ -159,11 +169,15 @@ int sc_main(int argc, char *argv[]) {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// run simulation // run simulation
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
if(vm.count("max_time")){ try {
sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as<std::string>()); if(vm.count("max_time")){
sc_core::sc_start(max_time); sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as<std::string>());
} else sc_core::sc_start(max_time);
sc_core::sc_start(); } else
sc_core::sc_start();
} catch(sc_core::sc_report& rep){
CLOG(FATAL, SystemC)<<"IWEF"[rep.get_severity()]<<"("<<rep.get_id()<<") "<<rep.get_msg_type()<<": "<<rep.get_msg()<<std::endl;
}
if (!sc_core::sc_end_of_simulation_invoked()) sc_core::sc_stop(); if (!sc_core::sc_end_of_simulation_invoked()) sc_core::sc_stop();
return 0; return 0;
} }

View File

@ -45,14 +45,19 @@ aon::aon(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm)
, tlm_target<>(clk) , tlm_target<>(clk)
, NAMED(clk_i) , NAMED(clk_i)
, NAMED(rst_i) , NAMED(erst_n_i)
, NAMED(lfclkc_o)
, NAMED(rst_o)
, NAMEDD(aon_regs, regs) { , NAMEDD(aon_regs, regs) {
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb); SC_METHOD(clock_cb);
sensitive << clk_i; sensitive << clk_i;
SC_METHOD(reset_cb); SC_METHOD(reset_cb);
sensitive << rst_i; sensitive << erst_n_i;
dont_initialize(); }
void aon::start_of_simulation() {
rst_o=true;
} }
void aon::clock_cb() { void aon::clock_cb() {
@ -62,10 +67,17 @@ void aon::clock_cb() {
aon::~aon() {} aon::~aon() {}
void aon::reset_cb() { void aon::reset_cb() {
if (rst_i.read()) if (!erst_n_i.read()){
regs->reset_start(); regs->reset_start();
else rst_o=true;
} else {
regs->reset_stop(); regs->reset_stop();
rst_o=false;
}
lfclkc_o.write(sc_core::sc_time(1/32768., sc_core::SC_SEC));
}
void aon::reset_internal_cb() {
} }
} /* namespace sysc */ } /* namespace sysc */

View File

@ -101,6 +101,12 @@ public:
uint32_t get_mode(){ return this->reg.machine_state; } uint32_t get_mode(){ return this->reg.machine_state; }
inline
void set_interrupt_execution(bool v){ this->interrupt_sim=v;}
inline
bool get_interrupt_execution(){ return this->interrupt_sim;}
base_type::hart_state<base_type::reg_t>& get_state() { return this->state; } base_type::hart_state<base_type::reg_t>& get_state() { return this->state; }
void notify_phase(exec_phase p) override { void notify_phase(exec_phase p) override {
@ -241,6 +247,8 @@ core_complex::core_complex(sc_core::sc_module_name name)
SC_THREAD(run); SC_THREAD(run);
SC_METHOD(clk_cb); SC_METHOD(clk_cb);
sensitive << clk_i; sensitive << clk_i;
SC_METHOD(rst_cb);
sensitive << rst_i;
SC_METHOD(sw_irq_cb); SC_METHOD(sw_irq_cb);
sensitive<<sw_irq_i; sensitive<<sw_irq_i;
SC_METHOD(timer_irq_cb); SC_METHOD(timer_irq_cb);
@ -299,6 +307,12 @@ void core_complex::disass_output(uint64_t pc, const std::string instr_str) {
void core_complex::clk_cb() { void core_complex::clk_cb() {
curr_clk = clk_i.read(); curr_clk = clk_i.read();
if(curr_clk==SC_ZERO_TIME) cpu->set_interrupt_execution(true);
}
void core_complex::rst_cb() {
if(rst_i.read())
cpu->set_interrupt_execution(true);
} }
void core_complex::sw_irq_cb(){ void core_complex::sw_irq_cb(){
@ -314,13 +328,19 @@ void core_complex::global_irq_cb(){
} }
void core_complex::run() { void core_complex::run() {
wait(sc_core::SC_ZERO_TIME); wait(SC_ZERO_TIME); // separate from elaboration phase
cpu->reset(reset_address.get_value()); do{
try { if(rst_i.read()){
vm->start(-1); cpu->reset(reset_address.get_value());
} catch (simulation_stopped &e) { wait(rst_i.negedge_event());
} }
sc_core::sc_stop(); while(clk_i.read()==SC_ZERO_TIME){
wait(clk_i.value_changed_event());
}
cpu->set_interrupt_execution(false);
vm->start();
} while(cpu->get_interrupt_execution());
sc_stop();
} }
bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) { bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) {

View File

@ -73,6 +73,7 @@ gpio::gpio(sc_core::sc_module_name nm)
} }
auto iof0_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp, auto iof0_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp,
tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
last_iof0[tag]=gp.get_value();
this->iof_input(tag, 0, gp, delay); this->iof_input(tag, 0, gp, delay);
return tlm::TLM_COMPLETED; return tlm::TLM_COMPLETED;
}; };
@ -83,6 +84,7 @@ gpio::gpio(sc_core::sc_module_name nm)
} }
auto iof1_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp, auto iof1_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp,
tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
last_iof1[tag]=gp.get_value();
this->iof_input(tag, 1, gp, delay); this->iof_input(tag, 1, gp, delay);
return tlm::TLM_COMPLETED; return tlm::TLM_COMPLETED;
}; };
@ -99,6 +101,13 @@ gpio::gpio(sc_core::sc_module_name nm)
} }
return true; return true;
}); });
regs->iof_en.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
if (!this->regs->in_reset()) {
enable_outputs(data);
reg.put(data);
}
return true;
});
} }
@ -123,21 +132,51 @@ void gpio::clock_cb() {
this->clk = clk_i.read(); this->clk = clk_i.read();
} }
tlm::tlm_phase gpio::write_output(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, size_t i, sc_dt::sc_logic val) {
sc_core::sc_time delay{SC_ZERO_TIME};
tlm::tlm_phase phase{ tlm::BEGIN_REQ };
gp.set_command(tlm::TLM_WRITE_COMMAND);
gp.set_response_status(tlm::TLM_OK_RESPONSE);
gp.set_value(val);
pins_o.at(i)->nb_transport_fw(gp, phase, delay);
return phase;
}
void gpio::update_pins() { void gpio::update_pins() {
sc_core::sc_inout_rv<32>::data_type out_val; sc_core::sc_inout_rv<32>::data_type out_val;
tlm::tlm_signal_gp<sc_dt::sc_logic> gp; tlm::tlm_signal_gp<sc_dt::sc_logic> gp;
for(size_t i=0, mask = 1; i<32; ++i, mask<<=1){ for(size_t i=0, mask = 1; i<32; ++i, mask<<=1){
if((regs->iof_en&mask == 0) || (iof0_i[i].size()==0 && iof1_i[i].size()==0)){ if((regs->iof_en&mask == 0) || (iof0_i[i].size()==0 && iof1_i[i].size()==0)){
sc_core::sc_time delay{SC_ZERO_TIME}; auto val = regs->r_output_en&mask?
tlm::tlm_phase phase{tlm::BEGIN_REQ}; regs->r_port&mask?
gp.set_command(tlm::TLM_WRITE_COMMAND); sc_dt::Log_1:
gp.set_response_status(tlm::TLM_OK_RESPONSE); sc_dt::Log_0:
gp.set_value(regs->r_output_en&mask?regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0:sc_dt::Log_Z); sc_dt::Log_Z;
pins_o.at(i)->nb_transport_fw(gp, phase, delay); tlm::tlm_phase phase = write_output(gp, i, val);
} }
} }
} }
void gpio::enable_outputs(uint32_t new_data) {
auto changed_bits = regs->r_iof_en^new_data;
tlm::tlm_signal_gp<sc_dt::sc_logic> gp;
for(size_t i=0, mask=1; i<32; ++i, mask<<=1){
if(changed_bits&mask){
if(new_data&mask){
if((regs->r_iof_sel&mask)==0 && iof0_i[i].size()>0){
tlm::tlm_phase phase = write_output(gp, i, last_iof0[i]?sc_dt::Log_1:sc_dt::Log_0);
} else if((regs->r_iof_sel&mask)==1 && iof1_i[i].size()>0)
tlm::tlm_phase phase = write_output(gp, i, last_iof1[i]?sc_dt::Log_1:sc_dt::Log_0);
} else {
auto val = regs->r_output_en&mask?
regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0:
sc_dt::Log_Z;
tlm::tlm_phase phase = write_output(gp, i, val);
}
}
}
}
void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp, sc_core::sc_time& delay) { void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp, sc_core::sc_time& delay) {
if(delay>SC_ZERO_TIME){ if(delay>SC_ZERO_TIME){
wait(delay); wait(delay);
@ -187,7 +226,8 @@ void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& g
tlm::tlm_phase phase{tlm::BEGIN_REQ}; tlm::tlm_phase phase{tlm::BEGIN_REQ};
tlm::tlm_signal_gp<sc_logic> new_gp; tlm::tlm_signal_gp<sc_logic> new_gp;
new_gp.set_command(tlm::TLM_WRITE_COMMAND); new_gp.set_command(tlm::TLM_WRITE_COMMAND);
new_gp.set_value(gp.get_value()?sc_dt::Log_1:sc_dt::Log_0); auto val = gp.get_value();
new_gp.set_value(val?sc_dt::Log_1:sc_dt::Log_0);
new_gp.copy_extensions_from(gp); new_gp.copy_extensions_from(gp);
socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum
} }

View File

@ -42,6 +42,7 @@ platform::platform(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm)
, NAMED(pins_o, 32) , NAMED(pins_o, 32)
, NAMED(pins_i, 32) , NAMED(pins_i, 32)
, NAMED(erst_n)
, NAMED(i_core_complex) , NAMED(i_core_complex)
, NAMED(i_router, 12, 1) , NAMED(i_router, 12, 1)
, NAMED(i_uart0) , NAMED(i_uart0)
@ -85,7 +86,8 @@ platform::platform(sc_core::sc_module_name nm)
i_gpio0.clk_i(s_tlclk); i_gpio0.clk_i(s_tlclk);
i_plic.clk_i(s_tlclk); i_plic.clk_i(s_tlclk);
i_aon.clk_i(s_tlclk); i_aon.clk_i(s_tlclk);
i_prci.clk_i(s_tlclk); i_aon.lfclkc_o(s_lfclk);
i_prci.hfclk_o(s_tlclk); // clock driver
i_clint.tlclk_i(s_tlclk); i_clint.tlclk_i(s_tlclk);
i_clint.lfclk_i(s_lfclk); i_clint.lfclk_i(s_lfclk);
i_core_complex.clk_i(s_tlclk); i_core_complex.clk_i(s_tlclk);
@ -97,11 +99,13 @@ platform::platform(sc_core::sc_module_name nm)
i_qspi2.rst_i(s_rst); i_qspi2.rst_i(s_rst);
i_gpio0.rst_i(s_rst); i_gpio0.rst_i(s_rst);
i_plic.rst_i(s_rst); i_plic.rst_i(s_rst);
i_aon.rst_i(s_rst); i_aon.rst_o(s_rst);
i_prci.rst_i(s_rst); i_prci.rst_i(s_rst);
i_clint.rst_i(s_rst); i_clint.rst_i(s_rst);
i_core_complex.rst_i(s_rst); i_core_complex.rst_i(s_rst);
i_aon.erst_n_i(erst_n);
i_clint.mtime_int_o(s_mtime_int); i_clint.mtime_int_o(s_mtime_int);
i_clint.msip_int_o(s_msie_int); i_clint.msip_int_o(s_msie_int);
@ -124,17 +128,7 @@ platform::platform(sc_core::sc_module_name nm)
i_uart1.rx_i(s_dummy_sck_o[0]); i_uart1.rx_i(s_dummy_sck_o[0]);
i_uart1.irq_o(s_dummy[0]); i_uart1.irq_o(s_dummy[0]);
SC_THREAD(gen_reset);
for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false; for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false;
} }
void platform::gen_reset() {
s_tlclk = 10_ns;
s_lfclk = 30517_ns;
s_rst = true;
wait(10_ns);
s_rst = false;
}
} /* namespace sysc */ } /* namespace sysc */

View File

@ -43,24 +43,35 @@ namespace sysc {
prci::prci(sc_core::sc_module_name nm) prci::prci(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm)
, tlm_target<>(clk) , tlm_target<>(hfclk)
, NAMED(clk_i)
, NAMED(rst_i) , NAMED(rst_i)
, NAMED(hfclk_o)
, NAMEDD(prci_regs, regs) { , NAMEDD(prci_regs, regs) {
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb);
sensitive << clk_i;
SC_METHOD(reset_cb); SC_METHOD(reset_cb);
sensitive << rst_i; sensitive << rst_i;
dont_initialize(); dont_initialize();
SC_METHOD(hfxosc_cb);
sensitive << hfxosc_i;
SC_METHOD(hfrosc_en_cb); SC_METHOD(hfrosc_en_cb);
sensitive << hfrosc_en_evt; sensitive << hfrosc_en_evt;
dont_initialize(); dont_initialize();
regs->hfxosccfg.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
reg.put(data);
if (this->regs->r_hfxosccfg.hfxoscen==1) { // check rosc_en
this->hfxosc_en_evt.notify(1, sc_core::SC_US);
} else {
this->hfxosc_en_evt.notify(SC_ZERO_TIME);
}
return true;
});
regs->hfrosccfg.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool { regs->hfrosccfg.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
reg.put(data); reg.put(data);
if (this->regs->r_hfrosccfg & (1 << 30)) { // check rosc_en if (this->regs->r_hfrosccfg.hfroscen==1) { // check rosc_en
this->hfrosc_en_evt.notify(1, sc_core::SC_US); this->hfrosc_en_evt.notify(1, sc_core::SC_US);
} else {
this->hfrosc_en_evt.notify(SC_ZERO_TIME);
} }
return true; return true;
}); });
@ -70,13 +81,15 @@ prci::prci(sc_core::sc_module_name nm)
if (pllcfg.pllbypass == 0 && pllcfg.pllq != 0) { // set pll_lock if pll is selected if (pllcfg.pllbypass == 0 && pllcfg.pllq != 0) { // set pll_lock if pll is selected
pllcfg.plllock = 1; pllcfg.plllock = 1;
} }
update_hfclk();
return true; return true;
}); });
} regs->plloutdiv.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
reg.put(data);
void prci::clock_cb() { update_hfclk();
this->clk = clk_i.read(); return true;
});
hfxosc_clk=62.5_ns;
} }
prci::~prci() {} prci::~prci() {}
@ -84,12 +97,49 @@ prci::~prci() {}
void prci::reset_cb() { void prci::reset_cb() {
if (rst_i.read()) if (rst_i.read())
regs->reset_start(); regs->reset_start();
else else {
regs->reset_stop(); regs->reset_stop();
this->hfxosc_en_evt.notify(1, sc_core::SC_US);
}
}
void prci::hfxosc_cb() {
this->regs->r_hfxosccfg.hfxoscrdy=0;
this->hfxosc_en_evt.notify(1, sc_core::SC_US);
}
void prci::hfxosc_en_cb() {
update_hfclk();
if(regs->r_hfxosccfg.hfxoscen==1)// set rosc_rdy
regs->r_hfxosccfg.hfxoscrdy =1;
else
regs->r_hfxosccfg.hfxoscrdy =0;
} }
void prci::hfrosc_en_cb() { void prci::hfrosc_en_cb() {
regs->r_hfrosccfg |= (1 << 31); // set rosc_rdy update_hfclk();
auto& hfrosccfg=regs->r_hfrosccfg;
if(regs->r_hfrosccfg.hfroscen==1) {// set rosc_rdy
regs->r_hfrosccfg.hfroscrdy =1;
} else {
regs->r_hfrosccfg.hfroscrdy =0;
}
}
void prci::update_hfclk() {
auto& hfrosccfg=regs->r_hfrosccfg;
auto& pllcfg=regs->r_pllcfg;
auto& plldiv=regs->r_plloutdiv;
hfrosc_clk = sc_core::sc_time(((hfrosccfg.hfroscdiv+1)*1.0)/(1125000.0*(hfrosccfg.hfrosctrim+1)), sc_core::SC_SEC);
auto pll_ref = pllcfg.pllrefsel==1?hfxosc_clk:hfrosc_clk;
auto r = pllcfg.pllr+1;
auto f = 2*(pllcfg.pllf+1);
auto q = 1<<pllcfg.pllq;
auto pll_out = pllcfg.pllbypass==1 || pllcfg.plllock==0?pll_ref:((pll_ref*r)/f)*q;
auto pll_res = plldiv&0x100?pll_out:2*pll_out*((plldiv&0x3f)+1);
hfclk = pllcfg.pllsel?pll_res:hfrosc_clk;
hfclk_o.write(hfclk);
} }
} /* namespace sysc */ } /* namespace sysc */

View File

@ -12,19 +12,29 @@ using namespace sysc;
system::system(sc_core::sc_module_name nm) system::system(sc_core::sc_module_name nm)
: sc_module(nm) : sc_module(nm)
, NAMED(s_gpio, 32) , NAMED(s_gpio, 32)
, NAMED(s_rst_n)
, NAMED(i_platform) , NAMED(i_platform)
, NAMED(i_terminal) , NAMED(i_terminal)
{ {
for(auto i=0U; i<s_gpio.size(); ++i){ // connect platform
i_platform.erst_n(s_rst_n);
for(auto i=0U; i<s_gpio.size(); ++i){
s_gpio[i].in(i_platform.pins_o[i]); s_gpio[i].in(i_platform.pins_o[i]);
i_platform.pins_i[i](s_gpio[i].out); i_platform.pins_i[i](s_gpio[i].out);
} }
// i_platform.pins_i(i_platform.pins_o); // connect other units
s_gpio[17].out(i_terminal.rx_i);
s_gpio[17].out(i_terminal.rx_i); i_terminal.tx_o(s_gpio[16].in);
i_terminal.tx_o(s_gpio[16].in); SC_THREAD(gen_por);
} }
system::~system() { system::~system() {
} }
void sysc::system::gen_por() {
// single shot
s_rst_n = false;
wait(10_ns);
s_rst_n = true;
}

View File

@ -134,54 +134,40 @@ void uart::reset_cb() {
void uart::transmit_data() { void uart::transmit_data() {
uint8_t txdata; uint8_t txdata;
sc_core::sc_time delay(SC_ZERO_TIME); sysc::tlm_signal_uart_extension ext;
tlm::tlm_phase phase(tlm::BEGIN_REQ); tlm::tlm_phase phase(tlm::BEGIN_REQ);
tlm::tlm_signal_gp<> gp; tlm::tlm_signal_gp<> gp;
gp.set_command(tlm::TLM_WRITE_COMMAND); sc_core::sc_time delay(SC_ZERO_TIME);
gp.set_value(true); sc_core::sc_time bit_duration(SC_ZERO_TIME);
tx_o->nb_transport_fw(gp, phase, delay);
gp.set_extension(&ext);
ext.tx.data_bits=8;
ext.tx.parity=false;
auto set_bit = [&](bool val){
gp.set_command(tlm::TLM_WRITE_COMMAND);
gp.set_value(val);
tlm::tlm_phase phase(tlm::BEGIN_REQ);
tx_o->nb_transport_fw(gp, phase, delay);
if(delay<bit_duration) wait(bit_duration-delay);
};
wait(delay);
while(true){ while(true){
set_bit(true);
wait(tx_fifo.data_written_event()); wait(tx_fifo.data_written_event());
while(tx_fifo.nb_read(txdata)){ while(tx_fifo.nb_read(txdata)){
regs->r_txdata.full=tx_fifo.num_free()==0; regs->r_txdata.full=tx_fifo.num_free()==0;
regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0; regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0;
auto bit_duration = (regs->r_div.div+1)*clk; bit_duration = (regs->r_div.div+1)*clk;
sysc::tlm_signal_uart_extension ext;
ext.start_time = sc_core::sc_time_stamp(); ext.start_time = sc_core::sc_time_stamp();
ext.tx.data_bits=8;
ext.tx.parity=false;
ext.tx.stop_bits=1+regs->r_txctrl.nstop; ext.tx.stop_bits=1+regs->r_txctrl.nstop;
ext.tx.baud_rate=static_cast<unsigned>(1/bit_duration.to_seconds()); ext.tx.baud_rate=static_cast<unsigned>(1/bit_duration.to_seconds());
ext.tx.data=txdata; ext.tx.data=txdata;
delay=SC_ZERO_TIME; set_bit(false); // start bit
auto start = sc_time_stamp(); for(int i = 8; i>0; --i)
gp.set_command(tlm::TLM_WRITE_COMMAND); set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first
gp.set_value(false); set_bit(true); // stop bit 1
gp.set_extension(&ext); if(regs->r_txctrl.nstop) set_bit(true); // stop bit 2
phase=tlm::BEGIN_REQ;
tx_o->nb_transport_fw(gp, phase, delay);
auto duration = bit_duration*(1+8+1+ext.tx.stop_bits);//start+data+parity+stop
auto diff=start+duration-sc_time_stamp();
if(diff>SC_ZERO_TIME) wait(diff);
delay=SC_ZERO_TIME;
gp.set_command(tlm::TLM_WRITE_COMMAND);
gp.set_value(true);
phase=tlm::BEGIN_REQ;
tx_o->nb_transport_fw(gp, phase, delay);
// if(txdata != '\r') queue.push_back(txdata);
// if (queue.size() >> 0 && (txdata == '\n' || txdata == 0)) {
// std::string msg(queue.begin(), queue.end()-1);
// LOG(INFO) << this->name() << " transmit: '" << msg << "'";
// sc_core::sc_time now = sc_core::sc_time_stamp();
// if(handler)
// sc_comm_singleton::inst().execute([this, msg, now](){
// std::stringstream os;
// os << "{\"time\":\"" << now << "\",\"message\":\""<<msg<<"\"}";
// this->handler->send(os.str());
// });
// queue.clear();
// }
} }
} }
} }

View File

@ -162,6 +162,7 @@ protected:
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
<% <%
def fcsr = allRegs.find {it.name=='FCSR'} def fcsr = allRegs.find {it.name=='FCSR'}
if(fcsr != null) {%> if(fcsr != null) {%>

View File

@ -1,21 +1,21 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH // Copyright (C) 2017,2018 MINRES Technologies GmbH
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: // modification, are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and/or other materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors // 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software // may be used to endorse or promote products derived from this software
// without specific prior written permission. // without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

View File

@ -179,6 +179,8 @@ struct rv32gc: public arch_if {
uint64_t get_icount() { return reg.icount;} uint64_t get_icount() { return reg.icount;}
bool should_stop(){return false;}
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32gc>::MEM || if(addr.space != traits<rv32gc>::MEM ||
addr.type == iss::address_type::PHYSICAL || addr.type == iss::address_type::PHYSICAL ||

View File

@ -144,8 +144,12 @@ struct rv32imac: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
inline
uint64_t get_icount() { return reg.icount;} uint64_t get_icount() { return reg.icount;}
inline
bool should_stop() { return interrupt_sim;}
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32imac>::MEM || if(addr.space != traits<rv32imac>::MEM ||
addr.type == iss::address_type::PHYSICAL || addr.type == iss::address_type::PHYSICAL ||
@ -204,6 +208,7 @@ protected:
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;} uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){} void set_fcsr(uint32_t val){}

View File

@ -146,6 +146,8 @@ struct rv64ia: public arch_if {
uint64_t get_icount() { return reg.icount;} uint64_t get_icount() { return reg.icount;}
bool should_stop(){return false;}
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv64ia>::MEM || if(addr.space != traits<rv64ia>::MEM ||
addr.type == iss::address_type::PHYSICAL || addr.type == iss::address_type::PHYSICAL ||

View File

@ -62,6 +62,7 @@ void rv32gc::reset(uint64_t address) {
reg.NEXT_PC=reg.PC; reg.NEXT_PC=reg.PC;
reg.trap_state=0; reg.trap_state=0;
reg.machine_state=0x0; reg.machine_state=0x0;
reg.icount=0;
} }
uint8_t* rv32gc::get_regs_base_ptr(){ uint8_t* rv32gc::get_regs_base_ptr(){

View File

@ -63,6 +63,7 @@ void rv64ia::reset(uint64_t address) {
reg.NEXT_PC = reg.PC; reg.NEXT_PC = reg.PC;
reg.trap_state = 0; reg.trap_state = 0;
reg.machine_state = 0x3; reg.machine_state = 0x3;
reg.icount=0;
} }
uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); } uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }

@ -1 +1 @@
Subproject commit 019a04132a8beb7fcab24d504e3347ca0771ea5f Subproject commit 57853f5df2ee573c35ef598a8a259696ae6059c0