forked from ultraembedded/cores
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
af78870
commit b354382
Showing
10 changed files
with
466 additions
and
465 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#ifndef __SC_VPI_CLOCK_H__ | ||
#define __SC_VPI_CLOCK_H__ | ||
|
||
#include <systemc.h> | ||
#include <vpi_user.h> | ||
|
||
|
||
static int sc_vpi_clock_after_delay(p_cb_data cb_data); | ||
|
||
class sc_vpi_clock | ||
{ | ||
public: | ||
|
||
sc_signal <bool> m_clk; | ||
int m_low_ns; | ||
int m_high_ns; | ||
uint64_t m_last_time; | ||
|
||
sc_module_name m_name; | ||
|
||
vpiHandle m_vpi_handle; | ||
|
||
sc_vpi_clock(sc_module_name name) : m_clk(name), m_name(name) | ||
{ | ||
m_low_ns = 5; | ||
m_high_ns = 5; | ||
m_last_time = 0; | ||
|
||
m_vpi_handle = vpi_handle_by_name((const char*)name, NULL); | ||
sc_assert(m_vpi_handle != NULL); | ||
} | ||
|
||
void start(void) { after_delay(); } | ||
|
||
int after_delay(void) | ||
{ | ||
bool clk_next = !m_clk.read(); | ||
s_vpi_time vpi_time_s; | ||
s_cb_data cb_data_s; | ||
|
||
vpi_time_s.type = vpiSimTime; | ||
vpi_time_s.high = 0; | ||
vpi_time_s.low = 0; | ||
|
||
s_vpi_value value_s; | ||
value_s.format = vpiIntVal; | ||
value_s.value.integer = clk_next; | ||
vpi_put_value(m_vpi_handle, &value_s, &vpi_time_s, vpiInertialDelay); | ||
|
||
// Setup wait time | ||
vpi_time_s.high = 0; | ||
vpi_time_s.low = clk_next ? m_high_ns : m_low_ns; | ||
vpi_time_s.type = vpiSimTime; | ||
|
||
m_clk.write(clk_next); | ||
|
||
// Get current time | ||
uint64_t time_value = 0; | ||
s_vpi_time time_now; | ||
time_now.type = vpiSimTime; | ||
vpi_get_time (0, &time_now); | ||
|
||
time_value = time_now.high; | ||
time_value <<= 32; | ||
time_value |= time_now.low; | ||
|
||
// Update systemC TB | ||
if(sc_pending_activity()) | ||
sc_start((int)(time_value-m_last_time),SC_NS); | ||
|
||
// Attach value change callbacks for outputs | ||
cb_data_s.user_data = (PLI_BYTE8*)this; | ||
cb_data_s.reason = cbAfterDelay; | ||
cb_data_s.cb_rtn = sc_vpi_clock_after_delay; | ||
cb_data_s.time = &vpi_time_s; | ||
cb_data_s.value = NULL; | ||
vpi_register_cb(&cb_data_s); | ||
} | ||
}; | ||
|
||
static int sc_vpi_clock_after_delay(p_cb_data cb_data) | ||
{ | ||
sc_vpi_clock *p = (sc_vpi_clock*)cb_data->user_data; | ||
return p->after_delay(); | ||
} | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#ifndef __SC_VPI_MODULE_H__ | ||
#define __SC_VPI_MODULE_H__ | ||
|
||
#include <systemc.h> | ||
#include <assert.h> | ||
#include <vpi_user.h> | ||
|
||
static int sc_vpi_module_value_change(p_cb_data cb_data); | ||
|
||
#define sc_vpi_module_read_output_int(obj, name) \ | ||
{ \ | ||
s_vpi_value value_s; \ | ||
s_vpi_time vpi_time_s; \ | ||
\ | ||
value_s.format = vpiIntVal; \ | ||
\ | ||
vpi_time_s.type = vpiSimTime; \ | ||
vpi_time_s.high = 0; \ | ||
vpi_time_s.low = 0; \ | ||
\ | ||
std::string path = m_hdl_name; \ | ||
path = path + "." + name; \ | ||
vpiHandle handle = vpi_handle_by_name(path.c_str(), NULL); \ | ||
assert(handle != NULL); \ | ||
\ | ||
vpi_get_value(handle, &value_s); \ | ||
obj.write(value_s.value.integer); \ | ||
} | ||
|
||
#define sc_vpi_module_write_input_int(obj, name) \ | ||
{ \ | ||
s_vpi_value value_s; \ | ||
s_vpi_time vpi_time_s; \ | ||
\ | ||
value_s.format = vpiIntVal; \ | ||
\ | ||
vpi_time_s.type = vpiSimTime; \ | ||
vpi_time_s.high = 0; \ | ||
vpi_time_s.low = 0; \ | ||
\ | ||
std::string path = m_hdl_name; \ | ||
path = path + "." + name; \ | ||
vpiHandle handle = vpi_handle_by_name(path.c_str(), NULL); \ | ||
assert(handle != NULL); \ | ||
\ | ||
value_s.value.integer = obj.read(); \ | ||
vpi_put_value(handle, &value_s, &vpi_time_s, vpiInertialDelay); \ | ||
} | ||
|
||
class sc_vpi_module | ||
{ | ||
public: | ||
std::string m_hdl_name; | ||
uint64_t m_last_time; | ||
sc_signal<bool> m_stop; | ||
|
||
sc_vpi_module(sc_module_name name) : m_hdl_name((std::string)name) | ||
{ | ||
m_last_time = 0; | ||
m_stop.write(false); | ||
} | ||
|
||
// Simulation control | ||
void stopSimulation() { m_stop.write(true); } | ||
bool isStopped() { return m_stop.read(); } | ||
|
||
virtual void read_outputs(void) { } | ||
virtual void write_inputs(void) { } | ||
|
||
bool register_signal(const char *name) | ||
{ | ||
static s_vpi_value value_s; | ||
static s_vpi_time vpi_time; | ||
s_cb_data cb_data_s; | ||
|
||
vpi_time.high = 0; | ||
vpi_time.low = 0; | ||
vpi_time.type = vpiSimTime; | ||
|
||
// For each I/O | ||
std::string path = m_hdl_name; | ||
path = path + "." + name; | ||
vpiHandle handle = vpi_handle_by_name(path.c_str(), NULL); | ||
if (!handle) | ||
return false; | ||
|
||
// Attach value change callbacks for outputs | ||
cb_data_s.user_data = (PLI_BYTE8*)this; | ||
cb_data_s.reason = cbValueChange; | ||
cb_data_s.cb_rtn = sc_vpi_module_value_change; | ||
cb_data_s.time = &vpi_time; | ||
cb_data_s.value = &value_s; | ||
|
||
value_s.format = vpiIntVal; | ||
|
||
cb_data_s.obj = handle; | ||
vpi_register_cb(&cb_data_s); | ||
|
||
return true; | ||
} | ||
|
||
int value_change(void) | ||
{ | ||
s_vpi_time vpi_time_s; | ||
|
||
vpi_time_s.type = vpiSimTime; | ||
vpi_time_s.high = 0; | ||
vpi_time_s.low = 0; | ||
|
||
// Outputs | ||
read_outputs(); | ||
|
||
// Get current time | ||
uint64_t time_value = 0; | ||
s_vpi_time time_now; | ||
time_now.type = vpiSimTime; | ||
vpi_get_time (0, &time_now); | ||
|
||
time_value = time_now.high; | ||
time_value <<= 32; | ||
time_value |= time_now.low; | ||
|
||
// Update systemC TB | ||
if(sc_pending_activity()) | ||
sc_start((int)(time_value-m_last_time),SC_NS); | ||
|
||
m_last_time = time_value; | ||
|
||
// Inputs | ||
write_inputs(); | ||
|
||
if (isStopped()) | ||
vpi_sim_control(vpiFinish, 0); | ||
|
||
return 0; | ||
} | ||
}; | ||
|
||
static int sc_vpi_module_value_change(p_cb_data cb_data) | ||
{ | ||
sc_vpi_module *p = (sc_vpi_module*)cb_data->user_data; | ||
return p->value_change(); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.