diff --git a/cosimulation/icarus/myhdl.c b/cosimulation/icarus/myhdl.c index 108a4cec..fa5c84ea 100644 --- a/cosimulation/icarus/myhdl.c +++ b/cosimulation/icarus/myhdl.c @@ -2,17 +2,28 @@ #include #include #include "vpi_user.h" +#include #define MAXLINE 4096 #define MAXWIDTH 10 +// #define DEBUG 1 -typedef int PLI_INT32; -typedef char PLI_BYTE8; +/* Sized variables */ +#ifndef PLI_TYPES +#define PLI_TYPES +typedef int PLI_INT32; +typedef unsigned int PLI_UINT32; +typedef short PLI_INT16; +typedef unsigned short PLI_UINT16; +typedef char PLI_BYTE8; +typedef unsigned char PLI_UBYTE8; +#endif static int rpipe; static int wpipe; static vpiHandle from_myhdl_systf_handle = NULL; +static vpiHandle to_myhdl_systf_handle = NULL; typedef struct to_myhdl_data { vpiHandle systf_handle; @@ -23,7 +34,8 @@ typedef struct to_myhdl_data { static PLI_INT32 from_myhdl_calltf(PLI_BYTE8 *user_data); static PLI_INT32 to_myhdl_calltf(PLI_BYTE8 *user_data); static PLI_INT32 to_myhdl_sensitivity_callback(p_cb_data cb_data); -static PLI_INT32 to_myhdl_write_callback(p_cb_data cb_data); +static PLI_INT32 to_myhdl_readwrite_callback(p_cb_data cb_data); +static PLI_INT32 to_myhdl_delay_callback(p_cb_data cb_data); static int init_pipes(); @@ -35,7 +47,6 @@ static int init_pipes() static int init_pipes_flag = 0; if (init_pipes_flag) { - vprintf("INFO: pipes already initialized\n"); return(0); } @@ -63,6 +74,7 @@ static PLI_INT32 from_myhdl_calltf(PLI_BYTE8 *user_data) char buf[MAXLINE]; char s[MAXWIDTH]; int n; + vpiHandle q; static int from_myhdl_flag = 0; @@ -92,19 +104,18 @@ static PLI_INT32 from_myhdl_calltf(PLI_BYTE8 *user_data) write(wpipe, buf, strlen(buf)); if ((n = read(rpipe, buf, MAXLINE)) == 0) { - vpi_printf("Info: myhdl down\n"); + vpi_printf("Info: MyHDL simulator down\n"); vpi_control(vpiFinish, 1); /* abort simulation */ return(0); } buf[n] = '\0'; + return(0); - - } static PLI_INT32 to_myhdl_calltf(PLI_BYTE8 *user_data) { - vpiHandle systf_handle, net_iter, net_handle; + vpiHandle net_iter, net_handle; vpiHandle cb_h; char buf[MAXLINE]; char s[MAXWIDTH]; @@ -126,30 +137,15 @@ static PLI_INT32 to_myhdl_calltf(PLI_BYTE8 *user_data) init_pipes(); vpi_printf("Hello from $to_myhdl %d %d\n", rpipe, wpipe); - systf_handle = vpi_handle(vpiSysTfCall, NULL); + to_myhdl_systf_handle = vpi_handle(vpiSysTfCall, NULL); - to_myhdl_data = (p_to_myhdl_data)malloc(sizeof(s_to_myhdl_data)); - to_myhdl_data->systf_handle = systf_handle; - to_myhdl_data->sync_flag = 0; - - /* setup sensitivity callback */ - time_s.type = vpiSuppressTime; - value_s.format = vpiSuppressVal; - cb_data_s.reason = cbValueChange; - cb_data_s.user_data = (PLI_BYTE8 *)to_myhdl_data; - cb_data_s.cb_rtn = to_myhdl_sensitivity_callback; - cb_data_s.time = &time_s; - cb_data_s.value = NULL; - - net_iter = vpi_iterate(vpiArgument, systf_handle); + net_iter = vpi_iterate(vpiArgument, to_myhdl_systf_handle); current_time.type = vpiSimTime; vpi_get_time(NULL, ¤t_time); sprintf(buf, "TO %x%08x ", current_time.high, current_time.low); while ((net_handle = vpi_scan(net_iter)) != NULL) { - cb_data_s.obj = net_handle; - vpi_register_cb(&cb_data_s); strcat(buf, vpi_get_str(vpiName, net_handle)); strcat(buf, " "); sprintf(s, "%d ", vpi_get(vpiSize, net_handle)); @@ -158,89 +154,58 @@ static PLI_INT32 to_myhdl_calltf(PLI_BYTE8 *user_data) write(wpipe, buf, strlen(buf)); if ((n = read(rpipe, buf, MAXLINE)) == 0) { - vpi_printf("Info: myhdl down\n"); + vpi_printf("Info: MyHDL simulator down\n"); vpi_control(vpiFinish, 1); /* abort simulation */ return(0); } buf[n] = '\0'; - // register write callback by default at time 0 // - vpi_printf("register cb\n"); - to_myhdl_data->sync_flag = 1; + // register write callback // time_s.type = vpiSimTime; time_s.high = 0; time_s.low = 0; cb_data_s.reason = cbReadWriteSynch; - cb_data_s.user_data = (PLI_BYTE8 *)to_myhdl_data; - cb_data_s.cb_rtn = to_myhdl_write_callback; + cb_data_s.user_data = NULL; + cb_data_s.cb_rtn = to_myhdl_readwrite_callback; cb_data_s.obj = NULL; cb_data_s.time = &time_s; cb_data_s.value = NULL; vpi_register_cb(&cb_data_s); return(0); - } -static PLI_INT32 to_myhdl_sensitivity_callback(p_cb_data cb_data) -{ - vpiHandle cb_h; - s_cb_data cb_data_s; - s_vpi_time time_s; - p_to_myhdl_data to_myhdl_data; - vpiHandle net_handle; - - to_myhdl_data = (p_to_myhdl_data)cb_data->user_data; - vpi_printf("sens triggered\n"); - if (!to_myhdl_data->sync_flag) { - vpi_printf("register cb\n"); - to_myhdl_data->sync_flag = 1; - time_s.type = vpiSimTime; - time_s.high = 0; - time_s.low = 0; - cb_data_s.reason = cbReadWriteSynch; - cb_data_s.user_data = (PLI_BYTE8 *)to_myhdl_data; - cb_data_s.cb_rtn = to_myhdl_write_callback; - cb_data_s.obj = NULL; - cb_data_s.time = &time_s; - cb_data_s.value = NULL; - vpi_register_cb(&cb_data_s); - } - return(0); -} - -static PLI_INT32 to_myhdl_write_callback(p_cb_data cb_data) +static PLI_INT32 to_myhdl_readwrite_callback(p_cb_data cb_data) { vpiHandle systf_handle; vpiHandle net_iter, net_handle; vpiHandle reg_iter, reg_handle; - p_to_myhdl_data to_myhdl_data; s_vpi_time current_time; s_vpi_value value_s; + s_cb_data cb_data_s; + s_vpi_time time_s; char buf[MAXLINE]; int n; + char *time_high_string; + char *time_low_string; + PLI_UINT32 time_low; + PLI_UINT32 time_high; + PLI_UINT32 delay; static int start_flag = 1; - vpi_printf("write callback\n"); - if (start_flag) { start_flag = 0; write(wpipe, "START", 5); if ((n = read(rpipe, buf, MAXLINE)) == 0) { - vpi_printf("Info: myhdl down\n"); + vpi_printf("Info: MyHDL simulator down\n"); vpi_control(vpiFinish, 1); /* abort simulation */ buf[n] = '\0'; } } - to_myhdl_data = (p_to_myhdl_data)cb_data->user_data; - vpi_printf("sync flag: %d\n", to_myhdl_data->sync_flag); - to_myhdl_data->sync_flag = 0; - systf_handle = to_myhdl_data->systf_handle; - - net_iter = vpi_iterate(vpiArgument, systf_handle); + net_iter = vpi_iterate(vpiArgument, to_myhdl_systf_handle); buf[0] = '\0'; current_time.type = vpiSimTime; vpi_get_time(systf_handle, ¤t_time); @@ -253,22 +218,86 @@ static PLI_INT32 to_myhdl_write_callback(p_cb_data cb_data) } write(wpipe, buf, strlen(buf)); if ((n = read(rpipe, buf, MAXLINE)) == 0) { - vpi_printf("Info: myhdl down\n"); + vpi_printf("Info: MyHDL simulator down\n"); vpi_control(vpiFinish, 1); /* abort simulation */ return(0); } buf[n] = '\0'; - vpi_printf("C Read %d %s\n", n, buf); + reg_iter = vpi_iterate(vpiArgument, from_myhdl_systf_handle); + time_high_string = strtok(buf, " "); + time_low_string = strtok(NULL, " "); + time_high = (PLI_UINT32) strtoul(time_high_string, (char **) NULL, 16); + time_low = (PLI_UINT32) strtoul(time_low_string, (char **) NULL, 16); + + assert(time_high == current_time.high); + if (time_low != current_time.low) { // schedule cbAfterDelay callback + if (time_low < current_time.low) { + delay = 0xFFFFFFFF - current_time.low + time_low; + } else { + delay = time_low - current_time.low; + } + // register cbAfterDelay callback // + time_s.type = vpiSimTime; + time_s.high = 0; + time_s.low = delay; + cb_data_s.reason = cbAfterDelay; + cb_data_s.user_data = NULL; + cb_data_s.cb_rtn = to_myhdl_delay_callback; + cb_data_s.obj = NULL; + cb_data_s.time = &time_s; + cb_data_s.value = NULL; + vpi_register_cb(&cb_data_s); + // We're done for now + if (reg_iter != NULL) { + vpi_free_object(reg_iter); + } +/* while ((reg_handle = vpi_scan(reg_iter)) != NULL) { */ +/* value_s.value.str = strtok(NULL, " "); */ + // } + return(0); + } + while ((reg_handle = vpi_scan(reg_iter)) != NULL) { - assert(sscanf(buf, "%s", value_s.value.str)); + value_s.value.str = strtok(NULL, " "); vpi_put_value(reg_handle, &value_s, NULL, vpiNoDelay); } + // register myself again // + time_s.type = vpiSimTime; + time_s.high = 0; + time_s.low = 0; + cb_data_s.reason = cbReadWriteSynch; + cb_data_s.user_data = NULL; + cb_data_s.cb_rtn = to_myhdl_readwrite_callback; + cb_data_s.obj = NULL; + cb_data_s.time = &time_s; + cb_data_s.value = NULL; + vpi_register_cb(&cb_data_s); + return(0); } +static PLI_INT32 to_myhdl_delay_callback(p_cb_data cb_data) +{ + s_cb_data cb_data_s; + s_vpi_time time_s; + s_vpi_time current_time; + vpi_get_time(NULL, ¤t_time); + // register readwrite callback // + time_s.type = vpiSimTime; + time_s.high = 0; + time_s.low = 0; + cb_data_s.reason = cbReadWriteSynch; + cb_data_s.user_data = NULL; + cb_data_s.cb_rtn = to_myhdl_readwrite_callback; + cb_data_s.obj = NULL; + cb_data_s.time = &time_s; + cb_data_s.value = NULL; + vpi_register_cb(&cb_data_s); + return(0); +} void myhdl_register() { diff --git a/myhdl/Cosimulation.py b/myhdl/Cosimulation.py index 9bf1b1c2..a77da52f 100644 --- a/myhdl/Cosimulation.py +++ b/myhdl/Cosimulation.py @@ -69,7 +69,6 @@ class Cosimulation(object): if _simulator._cosim: raise MultipleCosimError _simulator._cosim = 1 - print _simulator._cosim self._rt, self._wt = rt, wt = os.pipe() self._rf, self._wf = rf, wf = os.pipe() @@ -81,9 +80,9 @@ class Cosimulation(object): self._toSizes = toSizes = [] self._toSigs = toSigs = [] - self._changeFlag = 0 + self._hasChange = 0 - child_pid = os.fork() + child_pid = self._child_pid = os.fork() if child_pid == 0: os.close(rt) @@ -136,6 +135,7 @@ class Cosimulation(object): break else: raise Error, "Unexpected cosim input" + # os.waitpid(child_pid, 0) def _get(self): s = os.read(self._rt, _MAXLINE) @@ -151,8 +151,8 @@ class Cosimulation(object): if s.val != next: s.next = next - def _put(self): - t = hex(_simulator._time)[2:] + def _put(self, time): + t = hex(time)[2:] if t[-1] == 'L': t = t[:-1] # strip trailing L t = (9 - len(t)) * '0' + t # zero-extend to more than 32 bits @@ -160,14 +160,14 @@ class Cosimulation(object): for s in self._fromSigs: buf += hex(s)[2:] buf += " " - self._changeFlag = 0 + self._hasChange = 0 os.write(self._wf, buf) def _waiter(self): sigs = tuple(self._fromSigs) while 1: yield sigs - self._changeFlag = 1 + self._hasChange = 1 def __del__(self): """ Clear flag when this object destroyed - to suite unittest. """ diff --git a/myhdl/Simulation.py b/myhdl/Simulation.py index 5f71f81c..78af8854 100644 --- a/myhdl/Simulation.py +++ b/myhdl/Simulation.py @@ -25,6 +25,7 @@ __date__ = "$Date$" from __future__ import generators import sys +import os import exceptions from warnings import warn @@ -128,15 +129,19 @@ class Simulation(object): if cosim: cosim._get() - cosim._put() - - if _siglist: continue + if _siglist or cosim._hasChange: + cosim._put(t) + continue + elif _siglist: + continue if t == maxTime: raise StopSimulation, "Simulated for duration %s" % duration if _futureEvents: _futureEvents.sort() t = sim._time = _futureEvents[0][0] + if cosim: + cosim._put(t) while _futureEvents: newt, event = _futureEvents[0] if newt == t: @@ -148,6 +153,10 @@ class Simulation(object): else: break else: + if cosim: + os.close(cosim._rt) + os.close(cosim._wf) + os.waitpid(cosim._child_pid, 0) raise StopSimulation, "No more events" except StopSimulation, e: diff --git a/myhdl/test_Cosimulation.py b/myhdl/test_Cosimulation.py index 3fd0d0a3..980438d4 100644 --- a/myhdl/test_Cosimulation.py +++ b/myhdl/test_Cosimulation.py @@ -201,7 +201,7 @@ class CosimulationTest(TestCase): def testFromSignalVals(self): cosim = Cosimulation(exe + ".cosimFromSignalVals", **allSigs) os.read(cosim._rt, MAXLINE) - cosim._put() + cosim._put(0) def cosimFromSignalVals(self): wt = int(os.environ['MYHDL_TO_PIPE'])