diff --git a/myhdl/simrunc.c b/myhdl/simrunc.c new file mode 100644 index 00000000..51017b30 --- /dev/null +++ b/myhdl/simrunc.c @@ -0,0 +1,205 @@ +#include "Python.h" + +#include + +static PyObject *_simulator; +static PyObject *_siglist; +static PyObject *_futureEvents; +static PyObject *_WaiterList; +static PyObject *_Waiter; +static PyObject *Signal; +static PyObject *delay; +static PyObject *StopSimulation; +static PyObject *SuspendSimulation; + + +PyObject * +run(PyObject *self, PyObject *args, PyObject *kwargs) +{ + + PyObject *sim; + long int duration = 0; + int quiet = 0; + static char *argnames[] = {"sim", "duration", "quiet", NULL}; + + PyObject *waiters, *waiter, *clauses, *clone, *clause, *type, *newtO, *event; + long long int maxTime = -1; + long long int t = 0; + long long int ct = 0; + long long int newt = 0; + int nr; + int len, i, j; + PyObject *tO, *extl, *s, *hr, *hgl, *nt, *c, *wl, *ev, *ctO, *r; + + + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|li", argnames, + &sim, &duration, &quiet)) { + return NULL; + } + waiters = PyObject_GetAttrString(sim, "_waiters"); + tO = PyObject_GetAttrString(_simulator, "_time"); + t = PyLong_AsLongLong(tO); + Py_DECREF(tO); + + + for (;;) { + + + len = PyList_Size(_siglist); + for (i = 0; i < len; i++) { + s = PyList_GetItem(_siglist, i); + extl = PyObject_CallMethod(s, "_update", NULL); + for (j = 0; j < PyList_Size(extl); j++) { + PyList_Append(waiters, PyList_GetItem(extl, j)); + } + Py_DECREF(extl); + } + PySequence_DelSlice(_siglist, 0, len); + + while (PyList_Size(waiters) > 0) { + waiter = PyList_GetItem(waiters, 0); + Py_INCREF(waiter); + PySequence_DelItem(waiters, 0); + hr = PyObject_GetAttrString(waiter, "hasRun"); + if (PyObject_IsTrue(hr)) { + Py_DECREF(waiter); + Py_DECREF(hr); + continue; + } + Py_DECREF(hr); + hgl = PyObject_CallMethod(waiter, "hasGreenLight", NULL); + if (!PyObject_IsTrue(hgl)) { + Py_DECREF(waiter); + Py_DECREF(hgl); + continue; + } + Py_DECREF(hgl); + nt = PyObject_CallMethod(waiter, "next", NULL); + if (nt == NULL) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + c = PyObject_GetAttrString(waiter, "caller"); + if (c != Py_None) { + PyList_Append(waiters, c); + } + Py_DECREF(waiter); + Py_DECREF(c); + continue; + } else { + goto exception; + } + } + clauses = PyTuple_GetItem(nt, 0); + clone = PyTuple_GetItem(nt, 1); + nr = PyTuple_Size(clauses); + for (i = 0; i < nr; i++) { + clause = PySequence_GetItem(clauses, i); + type = PyObject_Type(clause); + if (type == _WaiterList) { + PyList_Append(clause, clone); + } else if (PyObject_IsInstance(clause, Signal)) { + wl = PyObject_GetAttrString(clause, "_eventWaiters"); + PyList_Append(wl, clone); + Py_DECREF(wl); + } else if (type == delay) { + ctO = PyObject_GetAttrString(clause, "_time"); + ct = PyLong_AsLongLong(ctO); + Py_DECREF(ctO); + ev = PyTuple_New(2); + newtO = PyLong_FromLongLong(t + ct); + PyTuple_SetItem(ev, 0, newtO); + PyTuple_SetItem(ev, 1, clone); + PyList_Append(_futureEvents, ev); + Py_DECREF(ev); + } else { + assert(0); + } + Py_DECREF(clause); + } + Py_DECREF(nt); + } + + + if (PyList_Size(_siglist) > 0) { + continue; + } + + if (PyList_Size(_futureEvents) > 0) { + PyObject_CallMethod(_futureEvents, "sort", NULL); + newtO = PyTuple_GetItem(PyList_GetItem(_futureEvents, 0), 0); + PyObject_SetAttrString(_simulator, "_time", newtO); + t = PyLong_AsLongLong(newtO); + while (PyList_Size(_futureEvents) > 0) { + ev = PyList_GetItem(_futureEvents, 0); + newtO = PyTuple_GetItem(ev, 0); + newt = PyLong_AsLongLong(newtO); + event = PyTuple_GetItem(ev, 1); + if (newt == t) { + if (PyObject_Type(event) == _Waiter) { + PyList_Append(waiters, event); + } else { + extl = PyObject_CallMethod(event, "apply", NULL); + for (j = 0; j < PyList_Size(extl); j++) { + PyList_Append(waiters, PyList_GetItem(extl, j)); + } + Py_DECREF(extl); + } + PySequence_DelItem(_futureEvents, 0); + } else { + break; + } + } + + } else { + PyErr_SetString(StopSimulation, "No more events"); + printf("No more events\n"); + goto exception; + } + } + + assert(0); /* should not get here */ + + exception: + if (PyErr_ExceptionMatches(StopSimulation)) { + printf("Stop simulation reached \n"); + PyErr_Clear(); + r = PyObject_CallMethod(sim, "_finalize", NULL); + Py_DECREF(r); + return PyInt_FromLong(0); + } + return Py_BuildValue(""); +} + + +static PyMethodDef simruncmethods[] = { + {"run", (PyCFunction)run, METH_VARARGS | METH_KEYWORDS}, + {NULL, NULL, 0, NULL} +}; + +void initsimrunc(void) { + PyObject *SignalModule; + PyObject *delayModule; + PyObject *_WaiterModule; + PyObject *utilModule; + + Py_InitModule("simrunc", simruncmethods); + + _simulator = PyImport_ImportModule("_simulator"); + _siglist = PyObject_GetAttrString(_simulator, "_siglist"); + _futureEvents = PyObject_GetAttrString(_simulator, "_futureEvents"); + SignalModule = PyImport_ImportModule("Signal"); + Signal = PyObject_GetAttrString(SignalModule, "Signal"); + _WaiterList = PyObject_GetAttrString(SignalModule, "_WaiterList"); + delayModule = PyImport_ImportModule("delay"); + delay = PyObject_GetAttrString(delayModule, "delay"); + _WaiterModule = PyImport_ImportModule("_Waiter"); + _Waiter = PyObject_GetAttrString(_WaiterModule, "_Waiter"); + utilModule = PyImport_ImportModule("util"); + StopSimulation = PyObject_GetAttrString(utilModule, "StopSimulation"); + SuspendSimulation = PyObject_GetAttrString(utilModule, "SuspendSimulation"); + + Py_DECREF(SignalModule); + Py_DECREF(delayModule); + Py_DECREF(_WaiterModule); + Py_DECREF(utilModule); +}