Implemented basic HiFive1-like platform with PLL,tracing etc.
This commit is contained in:
parent
b28595445c
commit
a899d30556
2
dbt-core
2
dbt-core
|
@ -1 +1 @@
|
|||
Subproject commit 34abe11e782335ae02dd74a3e47ae8bb366abc25
|
||||
Subproject commit 31263d4aaa6a7f01914c2decead091dc968f30d3
|
|
@ -16,14 +16,17 @@ namespace sysc {
|
|||
|
||||
class system: sc_core::sc_module {
|
||||
public:
|
||||
SC_HAS_PROCESS(system);
|
||||
|
||||
system(sc_core::sc_module_name nm);
|
||||
virtual ~system();
|
||||
|
||||
sc_core::sc_vector<tlm::tlm_signal<sc_dt::sc_logic>> s_gpio;
|
||||
|
||||
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::terminal i_terminal;
|
||||
void gen_por();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -47,13 +47,17 @@ class aon : public sc_core::sc_module, public scc::tlm_target<> {
|
|||
public:
|
||||
SC_HAS_PROCESS(aon);
|
||||
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);
|
||||
virtual ~aon() override; // need to keep it in source file because of fwd declaration of aon_regs
|
||||
|
||||
protected:
|
||||
void start_of_simulation() override;
|
||||
void clock_cb();
|
||||
void reset_cb();
|
||||
void reset_internal_cb();
|
||||
sc_core::sc_time clk;
|
||||
std::unique_ptr<aon_regs> regs;
|
||||
};
|
||||
|
|
|
@ -134,6 +134,7 @@ protected:
|
|||
void start_of_simulation();
|
||||
void run();
|
||||
void clk_cb();
|
||||
void rst_cb();
|
||||
void sw_irq_cb();
|
||||
void timer_irq_cb();
|
||||
void global_irq_cb();
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
inline sysc::prci_regs::prci_regs(sc_core::sc_module_name nm)
|
||||
: sc_core::sc_module(nm)
|
||||
, 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(plloutdiv, r_plloutdiv, 0, *this)
|
||||
, NAMED(coreclkcfg, r_coreclkcfg, 0, *this)
|
||||
|
|
|
@ -77,8 +77,13 @@ protected:
|
|||
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);
|
||||
sc_core::sc_time clk;
|
||||
std::array<bool, 32> last_iof0, last_iof1;
|
||||
std::unique_ptr<gpio_regs> regs;
|
||||
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 */
|
||||
|
|
|
@ -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_target_socket<sc_dt::sc_logic>> pins_i;
|
||||
|
||||
sc_core::sc_in<bool> erst_n;
|
||||
|
||||
platform(sc_core::sc_module_name nm);
|
||||
|
||||
private:
|
||||
|
|
|
@ -46,18 +46,21 @@ class prci_regs;
|
|||
class prci : public sc_core::sc_module, public scc::tlm_target<> {
|
||||
public:
|
||||
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_out<sc_core::sc_time> hfclk_o;
|
||||
prci(sc_core::sc_module_name nm);
|
||||
virtual ~prci() override; // need to keep it in source file because of fwd declaration of prci_regs
|
||||
|
||||
protected:
|
||||
void clock_cb();
|
||||
void hfxosc_cb();
|
||||
void reset_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;
|
||||
sc_core::sc_event hfrosc_en_evt;
|
||||
sc_core::sc_event hfrosc_en_evt, hfxosc_en_evt;
|
||||
};
|
||||
|
||||
} /* namespace sysc */
|
||||
|
|
|
@ -3,17 +3,17 @@ FILE(GLOB RiscVSCHeaders *.h */*.h)
|
|||
FILE(GLOB RiscvSCSources sysc/*.cpp)
|
||||
|
||||
set(LIB_HEADERS ${RiscVSCHeaders} )
|
||||
set(LIB_SOURCES ${RiscvSCSources}
|
||||
)
|
||||
set(LIB_SOURCES ${RiscvSCSources} )
|
||||
|
||||
set(APP_HEADERS )
|
||||
|
||||
set(APP_SOURCES sc_main.cpp
|
||||
)
|
||||
set(APP_SOURCES sc_main.cpp)
|
||||
|
||||
# Define two variables in order not to repeat ourselves.
|
||||
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
|
||||
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
|
||||
|
||||
|
|
|
@ -54,6 +54,16 @@ const size_t SUCCESS = 0;
|
|||
const size_t ERROR_UNHANDLED_EXCEPTION = 2;
|
||||
} // 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[]) {
|
||||
// sc_report_handler::set_handler(my_report_handler);
|
||||
scc::Logger<>::reporting_level() = logging::ERROR;
|
||||
|
@ -159,11 +169,15 @@ int sc_main(int argc, char *argv[]) {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// run simulation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
if(vm.count("max_time")){
|
||||
sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as<std::string>());
|
||||
sc_core::sc_start(max_time);
|
||||
} else
|
||||
sc_core::sc_start();
|
||||
try {
|
||||
if(vm.count("max_time")){
|
||||
sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as<std::string>());
|
||||
sc_core::sc_start(max_time);
|
||||
} 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();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -45,14 +45,19 @@ aon::aon(sc_core::sc_module_name nm)
|
|||
: sc_core::sc_module(nm)
|
||||
, tlm_target<>(clk)
|
||||
, NAMED(clk_i)
|
||||
, NAMED(rst_i)
|
||||
, NAMED(erst_n_i)
|
||||
, NAMED(lfclkc_o)
|
||||
, NAMED(rst_o)
|
||||
, NAMEDD(aon_regs, regs) {
|
||||
regs->registerResources(*this);
|
||||
SC_METHOD(clock_cb);
|
||||
sensitive << clk_i;
|
||||
SC_METHOD(reset_cb);
|
||||
sensitive << rst_i;
|
||||
dont_initialize();
|
||||
sensitive << erst_n_i;
|
||||
}
|
||||
|
||||
void aon::start_of_simulation() {
|
||||
rst_o=true;
|
||||
}
|
||||
|
||||
void aon::clock_cb() {
|
||||
|
@ -62,10 +67,17 @@ void aon::clock_cb() {
|
|||
aon::~aon() {}
|
||||
|
||||
void aon::reset_cb() {
|
||||
if (rst_i.read())
|
||||
if (!erst_n_i.read()){
|
||||
regs->reset_start();
|
||||
else
|
||||
rst_o=true;
|
||||
} else {
|
||||
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 */
|
||||
|
|
|
@ -101,6 +101,12 @@ public:
|
|||
|
||||
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; }
|
||||
|
||||
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_METHOD(clk_cb);
|
||||
sensitive << clk_i;
|
||||
SC_METHOD(rst_cb);
|
||||
sensitive << rst_i;
|
||||
SC_METHOD(sw_irq_cb);
|
||||
sensitive<<sw_irq_i;
|
||||
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() {
|
||||
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(){
|
||||
|
@ -314,13 +328,19 @@ void core_complex::global_irq_cb(){
|
|||
}
|
||||
|
||||
void core_complex::run() {
|
||||
wait(sc_core::SC_ZERO_TIME);
|
||||
cpu->reset(reset_address.get_value());
|
||||
try {
|
||||
vm->start(-1);
|
||||
} catch (simulation_stopped &e) {
|
||||
}
|
||||
sc_core::sc_stop();
|
||||
wait(SC_ZERO_TIME); // separate from elaboration phase
|
||||
do{
|
||||
if(rst_i.read()){
|
||||
cpu->reset(reset_address.get_value());
|
||||
wait(rst_i.negedge_event());
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
return tlm::TLM_COMPLETED;
|
||||
};
|
||||
|
@ -99,6 +101,13 @@ gpio::gpio(sc_core::sc_module_name nm)
|
|||
}
|
||||
return true;
|
||||
});
|
||||
regs->iof_en.set_write_cb([this](scc::sc_register<uint32_t> ®, 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();
|
||||
}
|
||||
|
||||
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() {
|
||||
sc_core::sc_inout_rv<32>::data_type out_val;
|
||||
tlm::tlm_signal_gp<sc_dt::sc_logic> gp;
|
||||
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)){
|
||||
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(regs->r_output_en&mask?regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0:sc_dt::Log_Z);
|
||||
pins_o.at(i)->nb_transport_fw(gp, phase, delay);
|
||||
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::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) {
|
||||
if(delay>SC_ZERO_TIME){
|
||||
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_signal_gp<sc_logic> new_gp;
|
||||
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);
|
||||
socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ platform::platform(sc_core::sc_module_name nm)
|
|||
: sc_core::sc_module(nm)
|
||||
, NAMED(pins_o, 32)
|
||||
, NAMED(pins_i, 32)
|
||||
, NAMED(erst_n)
|
||||
, NAMED(i_core_complex)
|
||||
, NAMED(i_router, 12, 1)
|
||||
, NAMED(i_uart0)
|
||||
|
@ -85,7 +86,8 @@ platform::platform(sc_core::sc_module_name nm)
|
|||
i_gpio0.clk_i(s_tlclk);
|
||||
i_plic.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.lfclk_i(s_lfclk);
|
||||
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_gpio0.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_clint.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.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.irq_o(s_dummy[0]);
|
||||
|
||||
SC_THREAD(gen_reset);
|
||||
|
||||
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 */
|
||||
|
|
|
@ -43,24 +43,35 @@ namespace sysc {
|
|||
|
||||
prci::prci(sc_core::sc_module_name nm)
|
||||
: sc_core::sc_module(nm)
|
||||
, tlm_target<>(clk)
|
||||
, NAMED(clk_i)
|
||||
, tlm_target<>(hfclk)
|
||||
, NAMED(rst_i)
|
||||
, NAMED(hfclk_o)
|
||||
, NAMEDD(prci_regs, regs) {
|
||||
regs->registerResources(*this);
|
||||
SC_METHOD(clock_cb);
|
||||
sensitive << clk_i;
|
||||
SC_METHOD(reset_cb);
|
||||
sensitive << rst_i;
|
||||
dont_initialize();
|
||||
SC_METHOD(hfxosc_cb);
|
||||
sensitive << hfxosc_i;
|
||||
SC_METHOD(hfrosc_en_cb);
|
||||
sensitive << hfrosc_en_evt;
|
||||
dont_initialize();
|
||||
|
||||
regs->hfxosccfg.set_write_cb([this](scc::sc_register<uint32_t> ®, 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> ®, uint32_t data) -> bool {
|
||||
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);
|
||||
} else {
|
||||
this->hfrosc_en_evt.notify(SC_ZERO_TIME);
|
||||
}
|
||||
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
|
||||
pllcfg.plllock = 1;
|
||||
}
|
||||
update_hfclk();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void prci::clock_cb() {
|
||||
this->clk = clk_i.read();
|
||||
|
||||
regs->plloutdiv.set_write_cb([this](scc::sc_register<uint32_t> ®, uint32_t data) -> bool {
|
||||
reg.put(data);
|
||||
update_hfclk();
|
||||
return true;
|
||||
});
|
||||
hfxosc_clk=62.5_ns;
|
||||
}
|
||||
|
||||
prci::~prci() {}
|
||||
|
@ -84,12 +97,49 @@ prci::~prci() {}
|
|||
void prci::reset_cb() {
|
||||
if (rst_i.read())
|
||||
regs->reset_start();
|
||||
else
|
||||
else {
|
||||
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() {
|
||||
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 */
|
||||
|
|
|
@ -12,19 +12,29 @@ using namespace sysc;
|
|||
system::system(sc_core::sc_module_name nm)
|
||||
: sc_module(nm)
|
||||
, NAMED(s_gpio, 32)
|
||||
, NAMED(s_rst_n)
|
||||
, NAMED(i_platform)
|
||||
, 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]);
|
||||
i_platform.pins_i[i](s_gpio[i].out);
|
||||
}
|
||||
// i_platform.pins_i(i_platform.pins_o);
|
||||
|
||||
s_gpio[17].out(i_terminal.rx_i);
|
||||
i_terminal.tx_o(s_gpio[16].in);
|
||||
}
|
||||
// connect other units
|
||||
s_gpio[17].out(i_terminal.rx_i);
|
||||
i_terminal.tx_o(s_gpio[16].in);
|
||||
SC_THREAD(gen_por);
|
||||
}
|
||||
|
||||
system::~system() {
|
||||
}
|
||||
|
||||
void sysc::system::gen_por() {
|
||||
// single shot
|
||||
s_rst_n = false;
|
||||
wait(10_ns);
|
||||
s_rst_n = true;
|
||||
}
|
||||
|
|
|
@ -134,54 +134,40 @@ void uart::reset_cb() {
|
|||
|
||||
void uart::transmit_data() {
|
||||
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_signal_gp<> gp;
|
||||
gp.set_command(tlm::TLM_WRITE_COMMAND);
|
||||
gp.set_value(true);
|
||||
tx_o->nb_transport_fw(gp, phase, delay);
|
||||
sc_core::sc_time delay(SC_ZERO_TIME);
|
||||
sc_core::sc_time bit_duration(SC_ZERO_TIME);
|
||||
|
||||
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){
|
||||
set_bit(true);
|
||||
wait(tx_fifo.data_written_event());
|
||||
while(tx_fifo.nb_read(txdata)){
|
||||
regs->r_txdata.full=tx_fifo.num_free()==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;
|
||||
sysc::tlm_signal_uart_extension ext;
|
||||
bit_duration = (regs->r_div.div+1)*clk;
|
||||
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.baud_rate=static_cast<unsigned>(1/bit_duration.to_seconds());
|
||||
ext.tx.data=txdata;
|
||||
delay=SC_ZERO_TIME;
|
||||
auto start = sc_time_stamp();
|
||||
gp.set_command(tlm::TLM_WRITE_COMMAND);
|
||||
gp.set_value(false);
|
||||
gp.set_extension(&ext);
|
||||
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();
|
||||
// }
|
||||
set_bit(false); // start bit
|
||||
for(int i = 8; i>0; --i)
|
||||
set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first
|
||||
set_bit(true); // stop bit 1
|
||||
if(regs->r_txctrl.nstop) set_bit(true); // stop bit 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@ protected:
|
|||
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
||||
bool interrupt_sim=false;
|
||||
<%
|
||||
def fcsr = allRegs.find {it.name=='FCSR'}
|
||||
if(fcsr != null) {%>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
||||
// Copyright (C) 2017,2018 MINRES Technologies GmbH
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 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
|
||||
// without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
|
|
@ -179,6 +179,8 @@ struct rv32gc: public arch_if {
|
|||
|
||||
uint64_t get_icount() { return reg.icount;}
|
||||
|
||||
bool should_stop(){return false;}
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if(addr.space != traits<rv32gc>::MEM ||
|
||||
addr.type == iss::address_type::PHYSICAL ||
|
||||
|
|
|
@ -144,8 +144,12 @@ struct rv32imac: public arch_if {
|
|||
/// deprecated
|
||||
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
|
||||
|
||||
inline
|
||||
uint64_t get_icount() { return reg.icount;}
|
||||
|
||||
inline
|
||||
bool should_stop() { return interrupt_sim;}
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if(addr.space != traits<rv32imac>::MEM ||
|
||||
addr.type == iss::address_type::PHYSICAL ||
|
||||
|
@ -204,6 +208,7 @@ protected:
|
|||
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
||||
bool interrupt_sim=false;
|
||||
|
||||
uint32_t get_fcsr(){return 0;}
|
||||
void set_fcsr(uint32_t val){}
|
||||
|
|
|
@ -146,6 +146,8 @@ struct rv64ia: public arch_if {
|
|||
|
||||
uint64_t get_icount() { return reg.icount;}
|
||||
|
||||
bool should_stop(){return false;}
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if(addr.space != traits<rv64ia>::MEM ||
|
||||
addr.type == iss::address_type::PHYSICAL ||
|
||||
|
|
|
@ -62,6 +62,7 @@ void rv32gc::reset(uint64_t address) {
|
|||
reg.NEXT_PC=reg.PC;
|
||||
reg.trap_state=0;
|
||||
reg.machine_state=0x0;
|
||||
reg.icount=0;
|
||||
}
|
||||
|
||||
uint8_t* rv32gc::get_regs_base_ptr(){
|
||||
|
|
|
@ -63,6 +63,7 @@ void rv64ia::reset(uint64_t address) {
|
|||
reg.NEXT_PC = reg.PC;
|
||||
reg.trap_state = 0;
|
||||
reg.machine_state = 0x3;
|
||||
reg.icount=0;
|
||||
}
|
||||
|
||||
uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(®); }
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 019a04132a8beb7fcab24d504e3347ca0771ea5f
|
||||
Subproject commit 57853f5df2ee573c35ef598a8a259696ae6059c0
|
Loading…
Reference in New Issue