diff --git a/.gitignore b/.gitignore
index 92eda074f..67ceeaffc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@
compile_commands.json
*.plan
results
+.oppfeaturestate
### coverage files
quisp/coverage*
diff --git a/.nedexclusions b/.nedexclusions
new file mode 100644
index 000000000..e69de29bb
diff --git a/.oppfeatures b/.oppfeatures
new file mode 100644
index 000000000..5644c45d3
--- /dev/null
+++ b/.oppfeatures
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/Makefile b/Makefile
index 56339fe8e..7ba77fd58 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,6 @@
-QUISP_MAKEFILE = "./quisp/Makefile"
+QUISP_SRC_DIR = "./quisp"
+QUISP_MAKEFILE = "$(QUISP_SRC_DIR)/Makefile
+QUISP_FEATURE = "$(QUISP_SRC_DIR)/feature_defines.h"
.PHONY: all tidy format ci makefile-exe makefile-lib checkmakefile googletest clean test coverage coverage-report help quispr
@@ -47,12 +49,15 @@ eigen/CMakeLists.txt:
eigen: eigen/CMakeLists.txt
-makefile-exe: eigen
+makefile-exe: eigen $(QUISP_FEATURE)
cd quisp && opp_makemake -f --deep -O out -i ./makefrag
-makefile-lib: eigen
+makefile-lib: eigen $(QUISP_FEATURE)
cd quisp && opp_makemake -f --deep -O out -i ./makefrag -M debug --make-so
+$(QUISP_FEATURE): $(wildcard .oppfeaturestate) .oppfeatures
+ opp_featuretool defines > $(QUISP_SRC_DIR)/feature_defines.h
+
clean:
@if [ -f "$(QUISP_MAKEFILE)" ]; then \
$(MAKE) -C quisp clean; \
diff --git a/quisp/.gitignore b/quisp/.gitignore
index 2211d28a0..494aec9bf 100644
--- a/quisp/.gitignore
+++ b/quisp/.gitignore
@@ -10,6 +10,7 @@ out/
.oppfeaturestate
quisp.dSYM/
Test*
+feature_defines.h
PhotonicQubit_m.cc
PhotonicQubit_m.h
diff --git a/quisp/.nedfolders b/quisp/.nedfolders
index 2c61d0d51..811f76d58 100644
--- a/quisp/.nedfolders
+++ b/quisp/.nedfolders
@@ -1,4 +1,4 @@
.
-./channels
-./modules
-./networks
+channels
+modules
+networks
diff --git a/quisp/app.py b/quisp/app.py
new file mode 100644
index 000000000..c11839a44
--- /dev/null
+++ b/quisp/app.py
@@ -0,0 +1,16 @@
+import opp
+import application
+
+def init_app_module(app):
+ num_resources = app.par("distant_measure_count").int()
+ pattern = app.par("TrafficPattern").int()
+ initiator_addr = app.par("LoneInitiatorAddress").int()
+
+ if pattern == 1 and app.my_address == initiator_addr:
+ dest_addr = app.get_one_random_endnode_addr()
+ pk = app.create_conn_setup_req(dest_addr,num_resources)
+ app.schedule_at(opp.sim_time(), pk)
+ if pattern == 2:
+ dest_addr = app.get_one_random_endnode_addr()
+ pk = app.create_conn_setup_req(dest_addr,num_resources)
+ app.schedule_at(opp.sim_time() + 0.00001 * app.my_address, pk)
diff --git a/quisp/modules/Application/Application.cc b/quisp/modules/Application/Application.cc
index b789eab48..24126dda1 100644
--- a/quisp/modules/Application/Application.cc
+++ b/quisp/modules/Application/Application.cc
@@ -6,15 +6,31 @@
*/
#include "Application.h"
#include
+#include
+#include
+#include
+#include
#include
+#include "messages/base_messages_m.h"
+#include "messages/connection_setup_messages_m.h"
+#include "modules/Application/IApplication.h"
#include "utils/ComponentProvider.h"
using namespace omnetpp;
using namespace quisp::messages;
+namespace py = pybind11;
namespace quisp {
namespace modules {
+PYBIND11_EMBEDDED_MODULE(application, m) {
+ py::class_, cSimpleModule> QuispApplication(m, "Application");
+ QuispApplication.def("create_conn_setup_req", &Application::createConnectionSetupRequest);
+ QuispApplication.def_readonly("my_address", &Application::my_address);
+ QuispApplication.def("get_one_random_endnode_addr", &Application::getOneRandomEndNodeAddress);
+ py::class_, omnetpp::cMessage>(m, "ConnectionSetupRequest");
+}
+
Application::Application() : provider(utils::ComponentProvider{this}) {}
/**
@@ -30,22 +46,26 @@ void Application::initialize() {
return;
}
- my_address = provider.getQNode()->par("address");
- is_e2e_connection = par("EndToEndConnection");
- num_measure = par("distant_measure_count");
+ WATCH_VECTOR(other_end_node_addresses);
+ storeEndNodeAddresses();
+#ifdef ENABLE_PYTHON
const char *app_py_path = par("app_py_path").stringValue();
compile_code(app_py_path);
+ auto obj = py::cast(this);
+ execute_python("init_app_module", obj);
- WATCH_VECTOR(other_end_node_addresses);
- storeEndNodeAddresses();
+#else
+
+ my_address = provider.getQNode()->par("address");
+ is_e2e_connection = par("EndToEndConnection");
+ num_measure = par("distant_measure_count");
+ traffic_pattern = par("TrafficPattern");
if (!is_e2e_connection) {
return;
}
- traffic_pattern = par("TrafficPattern");
-
if (traffic_pattern == 0) {
EV_INFO << "EndToEndConnection is set true. but no traffic pattern specified; proceeding with no traffic\n";
return;
@@ -76,6 +96,7 @@ void Application::initialize() {
}
error("Invalid TrafficPattern specified.");
+#endif
}
/**
diff --git a/quisp/modules/Application/Application.h b/quisp/modules/Application/Application.h
index 280c171a4..f44dc40b2 100644
--- a/quisp/modules/Application/Application.h
+++ b/quisp/modules/Application/Application.h
@@ -26,7 +26,6 @@ class Application : public IApplication, python_embeddable::PythonEmbeddable {
Application();
~Application() {}
- protected:
int my_address;
std::vector other_end_node_addresses;
diff --git a/quisp/modules/Application/Application.ned b/quisp/modules/Application/Application.ned
index a1cb4912e..c18f9d796 100644
--- a/quisp/modules/Application/Application.ned
+++ b/quisp/modules/Application/Application.ned
@@ -8,6 +8,7 @@ simple Application
{
parameters:
@display("i=block/app");
+ string app_py_path = default("app");
int address;
volatile double sendIaTime @unit(s) = default(exponential(1s)); // time between generating packets
string Other_endnodes_table = "";
diff --git a/quisp/modules/Application/Application_test.cc b/quisp/modules/Application/Application_test.cc
index 3113a67a2..937e4c1a7 100644
--- a/quisp/modules/Application/Application_test.cc
+++ b/quisp/modules/Application/Application_test.cc
@@ -37,7 +37,7 @@ class AppTestTarget : public quisp::modules::Application {
explicit AppTestTarget(TestQNode *parent_qnode) : Application(), toRouterGate(new TestGate(this, "toRouter")) {
this->provider.setStrategy(std::make_unique(parent_qnode));
setComponentType(new TestModuleType("test qnode"));
- setParStr(this, "app_py_path", "app.py");
+ setParStr(this, "app_py_path", "app");
}
virtual ~AppTestTarget() { EVCB.gateDeleted(toRouterGate); }
std::vector getOtherEndNodeAdresses() { return this->other_end_node_addresses; }
diff --git a/quisp/modules/Backend/Backend.cc b/quisp/modules/Backend/Backend.cc
index 3311cd435..5c0c4dc5f 100644
--- a/quisp/modules/Backend/Backend.cc
+++ b/quisp/modules/Backend/Backend.cc
@@ -2,7 +2,12 @@
namespace quisp::modules::backend {
-BackendContainer::BackendContainer() : interpreter(pybind11::scoped_interpreter{}) {}
+BackendContainer::BackendContainer()
+#ifdef ENABLE_PYTHON
+ : interpreter(pybind11::scoped_interpreter{})
+#endif
+{
+}
BackendContainer::~BackendContainer() {}
diff --git a/quisp/modules/Backend/Backend.h b/quisp/modules/Backend/Backend.h
index 26dd0034a..b1fec502c 100644
--- a/quisp/modules/Backend/Backend.h
+++ b/quisp/modules/Backend/Backend.h
@@ -4,6 +4,7 @@
#include
#include
#include "RNG.h"
+#include "feature_defines.h"
namespace quisp::modules::backend {
using quisp::modules::common::ErrorTrackingBackend;
@@ -16,6 +17,10 @@ class BackendContainer : public omnetpp::cSimpleModule {
~BackendContainer();
void initialize() override {
+#ifdef ENABLE_PYTHON
+ python_enabled = true;
+#endif
+ WATCH(python_enabled);
auto backend_type = std::string(par("backendType").stringValue());
if (backend_type == "ErrorTrackingBackend") {
backend = std::make_unique(std::make_unique(this));
@@ -36,7 +41,10 @@ class BackendContainer : public omnetpp::cSimpleModule {
protected:
void configureErrorTrackingBackend();
std::unique_ptr backend = nullptr;
+ bool python_enabled = false;
+#ifdef ENABLE_PYTHON
pybind11::scoped_interpreter interpreter;
+#endif
};
Define_Module(BackendContainer);
diff --git a/quisp/modules/Backend/Backend_test.cc b/quisp/modules/Backend/Backend_test.cc
index c8e2c517c..00dc16511 100644
--- a/quisp/modules/Backend/Backend_test.cc
+++ b/quisp/modules/Backend/Backend_test.cc
@@ -1,4 +1,5 @@
#include "Backend.h"
+#include
#include
#include
#include "modules/common_types.h"
@@ -29,6 +30,7 @@ TEST(BackendContainer, callInitialize) {
}
TEST(BackendContainer, callInitializeWithInvalidBackend) {
+ Py_Finalize();
auto *sim = utils::prepareSimulation();
BackendContainer *backend = new BackendContainer();
sim->registerComponent(backend);
@@ -37,7 +39,8 @@ TEST(BackendContainer, callInitializeWithInvalidBackend) {
EXPECT_THROW(backend->callInitialize(), omnetpp::cRuntimeError);
}
-TEST(BackendContainer, getQuantumBackend) {
+TEST(BackendConpainer, getQuantumBackend) {
+ Py_Finalize();
auto *sim = utils::prepareSimulation();
BackendContainer *backend = new BackendContainer();
sim->registerComponent(backend);
diff --git a/quisp/modules/Common/PythonEmbeddedable.cc b/quisp/modules/Common/PythonEmbeddedable.cc
new file mode 100644
index 000000000..8d36c8a9b
--- /dev/null
+++ b/quisp/modules/Common/PythonEmbeddedable.cc
@@ -0,0 +1,50 @@
+#include "PythonEmbeddedable.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "feature_defines.h"
+
+namespace py = pybind11;
+namespace opp = omnetpp;
+namespace fs = std::filesystem;
+namespace quisp::modules::python_embeddable {
+
+#ifdef ENABLE_PYTHON
+PYBIND11_EMBEDDED_MODULE(opp, m) {
+ py::class_> OppPar(m, "Par");
+ OppPar.def("str", &omnetpp::cPar::str);
+ OppPar.def("int", &omnetpp::cPar::intValue);
+
+ py::class_> OppSimpleModule(m, "SimpleModule");
+ OppSimpleModule.def("par", py::overload_cast(&opp::cSimpleModule::par), py::return_value_policy::reference);
+ OppSimpleModule.def("schedule_at", &opp::cSimpleModule::scheduleAt);
+ m.def("sim_time", &opp::simTime, py::return_value_policy::reference);
+
+ py::class_ OppSimTime(m, "SimTime");
+ OppSimTime.def(py::self + float());
+ OppSimTime.def(py::self += float());
+ OppSimTime.def(float() + py::self);
+
+ py::class_> OppCMessage(m, "Message");
+}
+#endif
+
+void PythonEmbeddable::compile_code(const char* file_name) {
+ auto* env = omnetpp::getEnvir();
+ auto* config = env->getConfigEx();
+ fs::path exe_path(env->getArgVector()[0]);
+ fs::path conf_path(env->resolveResourcePath(config->getFileName()));
+ py::module sys = py::module::import("sys");
+ py::cast(sys.attr("path")).append(fs::absolute(exe_path.parent_path()).string());
+ py::cast(sys.attr("path")).append(fs::absolute(conf_path.parent_path()).string());
+ py::print(sys.attr("path"));
+ module = pybind11::module_::import(file_name);
+}
+
+void PythonEmbeddable::execute_python(const char* func_name, py::object& arg1) { py::object ret = module.attr(func_name)(arg1); }
+
+} // namespace quisp::modules::python_embeddable
diff --git a/quisp/modules/Common/PythonEmbeddedable.h b/quisp/modules/Common/PythonEmbeddedable.h
index 0d76a7702..74251dc8f 100644
--- a/quisp/modules/Common/PythonEmbeddedable.h
+++ b/quisp/modules/Common/PythonEmbeddedable.h
@@ -1,37 +1,16 @@
#pragma once
-#include
-#include
-#include
-#include
-#include
-#include "pybind11/pybind11.h"
+#include
namespace quisp::modules::python_embeddable {
+namespace py = pybind11;
+
class PythonEmbeddable {
public:
PythonEmbeddable() {}
~PythonEmbeddable() {}
- void compile_code(const char* file_name) {
- FILE* file = std::fopen(file_name, "rt");
- if (file == NULL) {
- std::cout << file_name << " not found" << std::endl;
- return;
- }
- std::fseek(file, 0L, SEEK_END);
- auto length = std::ftell(file);
- std::rewind(file);
- char* source = (char*)malloc(length + 1);
- std::fread(source, sizeof(char), length, file);
- fclose(file);
- source[length] = '\0';
- std::cout << source << std::endl;
- code_object = Py_CompileString(source, file_name, Py_file_input);
- globals = pybind11::globals().ptr();
- }
-
- void execute_python() { PyEval_EvalCode(code_object, globals, pybind11::dict().ptr()); }
+ void compile_code(const char* file_name);
+ void execute_python(const char* func_name, py::object& arg1);
- PyObject* globals;
- PyObject* code_object = nullptr;
+ pybind11::module_ module;
};
} // namespace quisp::modules::python_embeddable
diff --git a/quisp/test_utils/Configuration.h b/quisp/test_utils/Configuration.h
index f478c44a8..af125842d 100644
--- a/quisp/test_utils/Configuration.h
+++ b/quisp/test_utils/Configuration.h
@@ -2,18 +2,19 @@
#include
#include "KeyValue.h"
+#include "omnetpp/cconfiguration.h"
namespace quisp_test {
namespace configuration {
using key_value::TestKeyValue;
-class Configuration : public omnetpp::cConfiguration {
+class Configuration : public omnetpp::cConfigurationEx {
private:
std::vector kvs;
public:
- Configuration() {
+ Configuration() : omnetpp::cConfigurationEx() {
kvs = std::vector();
auto kv = TestKeyValue{};
kvs.push_back(kv);
@@ -23,7 +24,31 @@ class Configuration : public omnetpp::cConfiguration {
virtual const char *getPerObjectConfigValue(const char *objectFullPath, const char *keySuffix) const override { return nullptr; };
virtual const KeyValue &getPerObjectConfigEntry(const char *objectFullPath, const char *keySuffix) const override { return kvs.at(0); };
virtual const char *substituteVariables(const char *value) const override { return nullptr; };
+ virtual void initializeFrom(cConfiguration *bootConfig) override{};
+ virtual const char *getFileName() const override { return "test-file-name"; };
+ virtual void validate(const char *ignorableConfigKeys = nullptr) const override{};
+ virtual std::vector getConfigNames() override { return {}; };
+ virtual void activateConfig(const char *configName, int runNumber = 0) override{};
+ virtual std::string getConfigDescription(const char *configName) const override {}
+ virtual std::vector getBaseConfigs(const char *configName) const override {}
+ virtual std::vector getConfigChain(const char *configName) const override {}
+ virtual int getNumRunsInConfig(const char *configName) const override {}
+ virtual std::vector unrollConfig(const char *configName) const override {}
+ virtual const char *getActiveConfigName() const override {}
+ virtual int getActiveRunNumber() const override {}
+ virtual const char *getVariable(const char *varname) const override {}
+ virtual std::vector getIterationVariableNames() const override {}
+ virtual std::vector getPredefinedVariableNames() const override {}
+ virtual const char *getVariableDescription(const char *varname) const override {}
+ virtual void dump() const override {}
+ virtual std::vector getMatchingConfigKeys(const char *pattern) const override {}
+ virtual const char *getParameterValue(const char *moduleFullPath, const char *paramName, bool hasDefaultValue) const override {}
+ virtual const KeyValue &getParameterEntry(const char *moduleFullPath, const char *paramName, bool hasDefaultValue) const override {}
+ virtual std::vector getKeyValuePairs() const override {}
+ virtual std::vector getParameterKeyValuePairs() const override {}
+ virtual std::vector getMatchingPerObjectConfigKeys(const char *objectFullPath, const char *keySuffixPattern) const override {}
+ virtual std::vector getMatchingPerObjectConfigKeySuffixes(const char *objectFullPath, const char *keySuffixPattern) const override {}
};
} // namespace configuration
-} // namespace quisp_test
\ No newline at end of file
+} // namespace quisp_test
diff --git a/quisp/test_utils/StaticEnv.cc b/quisp/test_utils/StaticEnv.cc
index 67632da6e..2c5289cf1 100644
--- a/quisp/test_utils/StaticEnv.cc
+++ b/quisp/test_utils/StaticEnv.cc
@@ -11,6 +11,7 @@ using configuration::Configuration;
StaticEnv::StaticEnv() {}
cConfiguration *StaticEnv::getConfig() { return new Configuration(); }
+cConfigurationEx *StaticEnv::getConfigEx() { return new Configuration(); }
std::string StaticEnv::gets(const char *prompt, const char *defaultreply) {
unsupported();
return "";
diff --git a/quisp/test_utils/StaticEnv.h b/quisp/test_utils/StaticEnv.h
index d76d94db6..8cce36090 100644
--- a/quisp/test_utils/StaticEnv.h
+++ b/quisp/test_utils/StaticEnv.h
@@ -70,6 +70,7 @@ class StaticEnv : public omnetpp::cEnvir {
void flushXMLParsedContentCache() override {}
unsigned getExtraStackForEnvir() const override { return 0; }
cConfiguration *getConfig() override;
+ cConfigurationEx *getConfigEx() override;
std::string resolveResourcePath(const char *fileName, cComponentType *context) override { return ""; }
bool isGUI() const override { return false; }
bool isExpressMode() const override { return false; }