Commit 8223ee70 authored by Georg Martin Reinke's avatar Georg Martin Reinke
Browse files

use a CV for Python/simulation thread communication

parent 97be4bb4
...@@ -34,15 +34,22 @@ bool parseInt(const char *s, int *i) { ...@@ -34,15 +34,22 @@ bool parseInt(const char *s, int *i) {
} }
std::vector<BaseComponent*> components; std::vector<BaseComponent*> components;
//
enum SimState {
StateStopped = 0,
StateRunning,
StatePaused
};
static pthread_t simThread; static pthread_t simThread;
struct SimContext { struct SimContext {
Simulation *sim; Simulation *sim;
Logger *log; Logger *log, *llog, *rlog;
pthread_mutex_t S, M; pthread_cond_t cond;
std::atomic_int stop; pthread_mutex_t mut;
std::atomic_int stop, numStep;
SimState state;
}; };
static SimContext globalCtx; static SimContext globalCtx;
...@@ -51,41 +58,112 @@ static void* simThreadFunction(void* arg) { ...@@ -51,41 +58,112 @@ static void* simThreadFunction(void* arg) {
bool running = true; bool running = true;
SimContext* ctx = (SimContext*) arg; SimContext* ctx = (SimContext*) arg;
pthread_mutex_lock(&ctx->S); ctx->numStep = 0;
while (running) { while (running) {
running = ctx->sim->step(*ctx->log); running = ctx->sim->step(*ctx->log, *ctx->llog, *ctx->rlog);
ctx->numStep++;
ctx->sim->increaseByTimeStep(); ctx->sim->increaseByTimeStep();
if (ctx->stop) { if (ctx->stop) {
pthread_mutex_unlock(&ctx->S); pthread_mutex_lock(&ctx->mut);
pthread_mutex_lock(&ctx->M); ctx->state = StatePaused;
pthread_mutex_unlock(&ctx->M); pthread_cond_signal(&ctx->cond);
pthread_mutex_lock(&ctx->S); pthread_cond_wait(&ctx->cond, &ctx->mut);
ctx->state = StateRunning;
pthread_mutex_unlock(&ctx->mut);
} }
} }
pthread_mutex_unlock(&ctx->S); pthread_mutex_lock(&ctx->mut);
ctx->state = StateStopped;
pthread_cond_signal(&ctx->cond);
pthread_mutex_unlock(&ctx->mut);
return nullptr; return nullptr;
} }
static PyObject* void initContext(SimContext* ctx) {
pythonStart(PyObject *self, PyObject *args) { // TODO: pass parameters like frequency, timestep to this function, or read them from the command line
globalCtx.log = new Logger(); ctx->log = new Logger();
globalCtx.sim = new Simulation(components, 2*PI*50, 1e-3, 1000, *globalCtx.log); ctx->llog = new Logger("lvector-python.log");
ctx->rlog = new Logger("rvector-python.log");
ctx->sim = new Simulation(components, 2*PI*50, 1e-3, 100, *globalCtx.log);
pthread_mutex_init(&ctx->mut, nullptr);
pthread_cond_init(&ctx->cond, nullptr);
}
static PyObject* pythonStart(PyObject *self, PyObject *args) {
pthread_mutex_lock(&globalCtx.mut);
if (globalCtx.state != StateStopped) {
PyErr_SetString(PyExc_SystemError, "Simulation already started");
pthread_mutex_unlock(&globalCtx.mut);
return nullptr;
}
globalCtx.stop = 0; globalCtx.stop = 0;
pthread_mutex_init(&globalCtx.M, nullptr); globalCtx.state = StateRunning;
pthread_mutex_init(&globalCtx.S, nullptr);
pthread_create(&simThread, nullptr, simThreadFunction, &globalCtx); pthread_create(&simThread, nullptr, simThreadFunction, &globalCtx);
//pthread_join(simThread, nullptr); pthread_mutex_unlock(&globalCtx.mut);
Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
static PyObject* static PyObject* pythonStep(PyObject *self, PyObject *args) {
pythonWait(PyObject *self, PyObject *args) { pthread_mutex_lock(&globalCtx.mut);
pthread_join(simThread, nullptr); int oldStep = globalCtx.numStep;
if (globalCtx.state == StateStopped) {
globalCtx.state = StateRunning;
globalCtx.stop = 1;
pthread_create(&simThread, nullptr, simThreadFunction, &globalCtx);
} else if (globalCtx.state == StatePaused) {
globalCtx.stop = 1;
pthread_cond_signal(&globalCtx.cond);
} else {
PyErr_SetString(PyExc_SystemError, "Simulation currently running");
pthread_mutex_unlock(&globalCtx.mut);
return nullptr;
}
while (globalCtx.numStep == oldStep)
pthread_cond_wait(&globalCtx.cond, &globalCtx.mut);
pthread_mutex_unlock(&globalCtx.mut);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* pythonPause(PyObject *self, PyObject *args) {
pthread_mutex_lock(&globalCtx.mut);
if (globalCtx.state != StateRunning) {
PyErr_SetString(PyExc_SystemError, "Simulation not currently running");
pthread_mutex_unlock(&globalCtx.mut);
return nullptr;
}
globalCtx.stop = 1;
pthread_cond_signal(&globalCtx.cond);
while (globalCtx.state == StateRunning)
pthread_cond_wait(&globalCtx.cond, &globalCtx.mut);
pthread_mutex_unlock(&globalCtx.mut);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* pythonWait(PyObject *self, PyObject *args) {
pthread_mutex_lock(&globalCtx.mut);
if (globalCtx.state == StateStopped) {
pthread_mutex_unlock(&globalCtx.mut);
Py_INCREF(Py_None);
return Py_None;
} else if (globalCtx.state == StatePaused) {
pthread_mutex_unlock(&globalCtx.mut);
PyErr_SetString(PyExc_SystemError, "Simulation currently paused");
return nullptr;
}
while (globalCtx.state == StateRunning)
pthread_cond_wait(&globalCtx.cond, &globalCtx.mut);
pthread_mutex_unlock(&globalCtx.mut);
Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
static PyMethodDef pythonMethods[] = { static PyMethodDef pythonMethods[] = {
{"start", pythonStart, METH_VARARGS, "Start the simulation."}, {"start", pythonStart, METH_VARARGS, "Start the simulation."},
{"step", pythonStep, METH_VARARGS, "Perform a single simulation step."},
{"pause", pythonPause, METH_VARARGS, "Pause the already running simulation."},
{"wait", pythonWait, METH_VARARGS, "Wait for the simulation to finish."}, {"wait", pythonWait, METH_VARARGS, "Wait for the simulation to finish."},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
...@@ -95,8 +173,7 @@ static PyModuleDef dpsimModule = { ...@@ -95,8 +173,7 @@ static PyModuleDef dpsimModule = {
NULL, NULL, NULL, NULL NULL, NULL, NULL, NULL
}; };
static PyObject* static PyObject* PyInit_dpsim(void) {
PyInit_dpsim(void) {
return PyModule_Create(&dpsimModule); return PyModule_Create(&dpsimModule);
} }
...@@ -269,6 +346,7 @@ int pythonMain(int argc, const char* argv[]) { ...@@ -269,6 +346,7 @@ int pythonMain(int argc, const char* argv[]) {
components.push_back(new VoltSourceRes("V_in", 1, 0, 10, 1, 1)); components.push_back(new VoltSourceRes("V_in", 1, 0, 10, 1, 1));
components.push_back(new LinearResistor("R_load", 1, 0, 100)); components.push_back(new LinearResistor("R_load", 1, 0, 100));
initContext(&globalCtx);
while (std::cin.good() && Py_IsInitialized()) { while (std::cin.good() && Py_IsInitialized()) {
std::cout << "> "; std::cout << "> ";
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment