Commit db94a579 authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

core: merge model and dynamics

irt::model and irt::dynamics are too closed. We merge these structure
into irt::model.
parent 95e171e6
This diff is collapsed.
......@@ -187,14 +187,75 @@ struct top_cluster
}
};
inline int
make_input_node_id(const irt::model_id mdl, const int port) noexcept
{
irt_assert(port >= 0 && port < 8);
irt::u32 index = irt::get_index(mdl);
irt_assert(index < 268435456u);
irt::u32 port_index = static_cast<irt::u32>(port) << 28u;
index |= port_index;
return static_cast<int>(index);
}
inline int
make_output_node_id(const irt::model_id mdl, const int port) noexcept
{
irt_assert(port >= 0 && port < 8);
irt::u32 index = irt::get_index(mdl);
irt_assert(index < 268435456u);
irt::u32 port_index = static_cast<irt::u32>(8u + port) << 28u;
index |= port_index;
return static_cast<int>(index);
}
inline std::pair<irt::u32, irt::u32>
get_model_input_port(const int node_id) noexcept
{
const irt::u32 real_node_id = static_cast<irt::u32>(node_id);
irt::u32 port = real_node_id >> 28u;
irt_assert(port < 8u);
constexpr irt::u32 mask = ~(15u << 28u);
irt::u32 index = real_node_id & mask;
return std::make_pair(index, port);
}
inline std::pair<irt::u32, irt::u32>
get_model_output_port(const int node_id) noexcept
{
const irt::u32 real_node_id = static_cast<irt::u32>(node_id);
irt::u32 port = real_node_id >> 28u;
irt_assert(port >= 8u && port < 16u);
port -= 8u;
irt_assert(port < 8u);
constexpr irt::u32 mask = ~(15u << 28u);
irt::u32 index = real_node_id & mask;
return std::make_pair(index, port);
}
struct cluster
{
cluster() = default;
small_string<16> name;
std::vector<child_id> children;
std::vector<input_port_id> input_ports;
std::vector<output_port_id> output_ports;
std::vector<int> input_ports;
std::vector<int> output_ports;
int get(const child_id id) const noexcept
{
......@@ -311,7 +372,7 @@ struct sources
irt::source::text_file* new_text_file() noexcept;
void show(bool* is_show);
void show_menu(const char *title, external_source& src);
void show_menu(const char* title, external_source& src);
};
struct editor
......@@ -473,36 +534,33 @@ struct editor
models_mapper[get_index(child)] = parent;
}
static int get_in(input_port_id id) noexcept
struct gport
{
return static_cast<int>(get_index(id));
}
gport() noexcept = default;
input_port_id get_in(int index) const noexcept
{
auto* port = sim.input_ports.try_to_get(static_cast<u32>(index));
gport(irt::model* model_, const int port_index_) noexcept
: model(model_)
, port_index(port_index_)
{}
return port ? sim.input_ports.get_id(port) : undefined<input_port_id>();
}
irt::model* model = nullptr;
int port_index = 0;
};
static int get_out(output_port_id id) noexcept
gport get_in(const int index) noexcept
{
constexpr u32 is_output = 1 << 31;
u32 index = get_index(id);
index |= is_output;
const auto model_index_port = get_model_input_port(index);
auto* mdl = sim.models.try_to_get(model_index_port.first);
return static_cast<int>(index);
return { mdl, static_cast<int>(model_index_port.second) };
}
output_port_id get_out(int index) const noexcept
gport get_out(const int index) noexcept
{
constexpr u32 mask = ~(1 << 31); /* remove the first bit */
index &= mask;
auto* port = sim.output_ports.try_to_get(static_cast<u32>(index));
const auto model_index_port = get_model_output_port(index);
auto* mdl = sim.models.try_to_get(model_index_port.first);
return port ? sim.output_ports.get_id(port)
: undefined<output_port_id>();
return { mdl, static_cast<int>(model_index_port.second) };
}
status add_lotka_volterra() noexcept;
......
......@@ -127,7 +127,7 @@ endfunction()
irritator_add_test(test-api test/public-api.cpp)
irritator_add_test(simulations test/simulations.cpp)
irritator_add_test(auditory test/auditory.cpp)
# irritator_add_test(auditory test/auditory.cpp)
# irritator_add_benchmark(benchmark_exactitude_aqss benchmark/benchmark_exactitude_aqss.cpp)
# irritator_add_benchmark(benchmark_exactitude_qss1 benchmark/benchmark_exactitude_qss1.cpp)
......
This diff is collapsed.
......@@ -50,20 +50,20 @@ example_qss_lotka_volterra(simulation& sim, F f) noexcept
sum_b.default_input_coeffs[0] = -1.0;
sum_b.default_input_coeffs[1] = 0.1;
sim.connect(sum_a.y[0], integrator_a.x[0]);
sim.connect(sum_b.y[0], integrator_b.x[0]);
sim.connect(integrator_a.y[0], sum_a.x[0]);
sim.connect(integrator_b.y[0], sum_b.x[0]);
sim.connect(integrator_a.y[0], product.x[0]);
sim.connect(integrator_b.y[0], product.x[1]);
sim.connect(product.y[0], sum_a.x[1]);
sim.connect(product.y[0], sum_b.x[1]);
f(sum_a.id);
f(sum_b.id);
f(product.id);
f(integrator_a.id);
f(integrator_b.id);
sim.connect(sum_a, 0, integrator_a, 0);
sim.connect(sum_b, 0, integrator_b, 0);
sim.connect(integrator_a, 0, sum_a, 0);
sim.connect(integrator_b, 0, sum_b, 0);
sim.connect(integrator_a, 0, product, 0);
sim.connect(integrator_b, 0, product, 1);
sim.connect(product, 0, sum_a, 1);
sim.connect(product, 0, sum_b, 1);
f(sim.get_id(sum_a));
f(sim.get_id(sum_b));
f(sim.get_id(product));
f(sim.get_id(integrator_a));
f(sim.get_id(integrator_b));
return status::success;
}
......@@ -103,19 +103,19 @@ example_qss_lif(simulation& sim, F f) noexcept
auto& cross = sim.alloc<abstract_cross<QssLevel>>();
cross.default_threshold = Vt;
sim.connect(cross.y[0], integrator.x[1]);
sim.connect(cross.y[1], sum.x[0]);
sim.connect(integrator.y[0], cross.x[0]);
sim.connect(integrator.y[0], cross.x[2]);
sim.connect(cst_cross.y[0], cross.x[1]);
sim.connect(cst.y[0], sum.x[1]);
sim.connect(sum.y[0], integrator.x[0]);
sim.connect(cross, 0, integrator, 1);
sim.connect(cross, 1, sum, 0);
sim.connect(integrator, 0, cross, 0);
sim.connect(integrator, 0, cross, 2);
sim.connect(cst_cross, 0, cross, 1);
sim.connect(cst, 0, sum, 1);
sim.connect(sum, 0, integrator, 0);
f(sum.id);
f(cst.id);
f(cst_cross.id);
f(integrator.id);
f(cross.id);
f(sim.get_id(sum));
f(sim.get_id(cst));
f(sim.get_id(cst_cross));
f(sim.get_id(integrator));
f(sim.get_id(cross));
return status::success;
}
......@@ -178,46 +178,46 @@ example_qss_izhikevich(simulation& sim, F f) noexcept
sum_d.default_input_coeffs[0] = 1.0;
sum_d.default_input_coeffs[1] = d;
sim.connect(integrator_a.y[0], cross.x[0]);
sim.connect(cst2.y[0], cross.x[1]);
sim.connect(integrator_a.y[0], cross.x[2]);
sim.connect(cross.y[1], product.x[0]);
sim.connect(cross.y[1], product.x[1]);
sim.connect(product.y[0], sum_c.x[0]);
sim.connect(cross.y[1], sum_c.x[1]);
sim.connect(cross.y[1], sum_b.x[1]);
sim.connect(cst.y[0], sum_c.x[2]);
sim.connect(cst3.y[0], sum_c.x[3]);
sim.connect(sum_c.y[0], sum_a.x[0]);
sim.connect(cross2.y[1], sum_a.x[1]);
sim.connect(sum_a.y[0], integrator_a.x[0]);
sim.connect(cross.y[0], integrator_a.x[1]);
sim.connect(cross2.y[1], sum_b.x[0]);
sim.connect(sum_b.y[0], integrator_b.x[0]);
sim.connect(cross2.y[0], integrator_b.x[1]);
sim.connect(integrator_a.y[0], cross2.x[0]);
sim.connect(integrator_b.y[0], cross2.x[2]);
sim.connect(sum_d.y[0], cross2.x[1]);
sim.connect(integrator_b.y[0], sum_d.x[0]);
sim.connect(cst.y[0], sum_d.x[1]);
f(cst.id);
f(cst2.id);
f(cst3.id);
f(sum_a.id);
f(sum_b.id);
f(sum_c.id);
f(sum_d.id);
f(product.id);
f(integrator_a.id);
f(integrator_b.id);
f(cross.id);
f(cross2.id);
sim.connect(integrator_a, 0, cross, 0);
sim.connect(cst2, 0, cross, 1);
sim.connect(integrator_a, 0, cross, 2);
sim.connect(cross, 1, product, 0);
sim.connect(cross, 1, product, 1);
sim.connect(product, 0, sum_c, 0);
sim.connect(cross, 1, sum_c, 1);
sim.connect(cross, 1, sum_b, 1);
sim.connect(cst, 0, sum_c, 2);
sim.connect(cst3, 0, sum_c, 3);
sim.connect(sum_c, 0, sum_a, 0);
sim.connect(cross2, 1, sum_a, 1);
sim.connect(sum_a, 0, integrator_a, 0);
sim.connect(cross, 0, integrator_a, 1);
sim.connect(cross2, 1, sum_b, 0);
sim.connect(sum_b, 0, integrator_b, 0);
sim.connect(cross2, 0, integrator_b, 1);
sim.connect(integrator_a, 0, cross2, 0);
sim.connect(integrator_b, 0, cross2, 2);
sim.connect(sum_d, 0, cross2, 1);
sim.connect(integrator_b, 0, sum_d, 0);
sim.connect(cst, 0, sum_d, 1);
f(sim.get_id(cst));
f(sim.get_id(cst2));
f(sim.get_id(cst3));
f(sim.get_id(sum_a));
f(sim.get_id(sum_b));
f(sim.get_id(sum_c));
f(sim.get_id(sum_d));
f(sim.get_id(product));
f(sim.get_id(integrator_a));
f(sim.get_id(integrator_b));
f(sim.get_id(cross));
f(sim.get_id(cross2));
return status::success;
}
......@@ -250,21 +250,21 @@ example_qss_van_der_pol(simulation& sim, F f) noexcept
sum.default_input_coeffs[1] = -mu;
sum.default_input_coeffs[2] = -1.0;
sim.connect(integrator_b.y[0], integrator_a.x[0]);
sim.connect(sum.y[0], integrator_b.x[0]);
sim.connect(integrator_b.y[0], sum.x[0]);
sim.connect(product2.y[0], sum.x[1]);
sim.connect(integrator_a.y[0], sum.x[2]);
sim.connect(integrator_b.y[0], product1.x[0]);
sim.connect(integrator_a.y[0], product1.x[1]);
sim.connect(product1.y[0], product2.x[0]);
sim.connect(integrator_a.y[0], product2.x[1]);
f(sum.id);
f(product1.id);
f(product2.id);
f(integrator_a.id);
f(integrator_b.id);
sim.connect(integrator_b, 0, integrator_a, 0);
sim.connect(sum, 0, integrator_b, 0);
sim.connect(integrator_b, 0, sum, 0);
sim.connect(product2, 0, sum, 1);
sim.connect(integrator_a, 0, sum, 2);
sim.connect(integrator_b, 0, product1, 0);
sim.connect(integrator_a, 0, product1, 1);
sim.connect(product1, 0, product2, 0);
sim.connect(integrator_a, 0, product2, 1);
f(sim.get_id(sum));
f(sim.get_id(product1));
f(sim.get_id(product2));
f(sim.get_id(integrator_a));
f(sim.get_id(integrator_b));
return status::success;
}
......@@ -303,19 +303,19 @@ example_qss_negative_lif(simulation& sim, F f) noexcept
cross.default_threshold = Vt;
cross.default_detect_up = false;
sim.connect(cross.y[0], integrator.x[1]);
sim.connect(cross.y[1], sum.x[0]);
sim.connect(integrator.y[0], cross.x[0]);
sim.connect(integrator.y[0], cross.x[2]);
sim.connect(cst_cross.y[0], cross.x[1]);
sim.connect(cst.y[0], sum.x[1]);
sim.connect(sum.y[0], integrator.x[0]);
f(sum.id);
f(integrator.id);
f(cross.id);
f(cst.id);
f(cst_cross.id);
sim.connect(cross, 0, integrator, 1);
sim.connect(cross, 1, sum, 0);
sim.connect(integrator, 0, cross, 0);
sim.connect(integrator, 0, cross, 2);
sim.connect(cst_cross, 0, cross, 1);
sim.connect(cst, 0, sum, 1);
sim.connect(sum, 0, integrator, 0);
f(sim.get_id(sum));
f(sim.get_id(integrator));
f(sim.get_id(cross));
f(sim.get_id(cst));
f(sim.get_id(cst_cross));
return status::success;
}
......
......@@ -188,7 +188,7 @@ struct random_source
return false;
}
bool operator()(external_source& src)
bool operator()(external_source& /*src*/)
{
if (!use_rewind)
return false;
......
......@@ -211,6 +211,7 @@ get_input_port_names(const dynamics_type type) noexcept
case dynamics_type::quantifier:
case dynamics_type::counter:
case dynamics_type::buffer:
case dynamics_type::qss1_power:
case dynamics_type::qss2_power:
case dynamics_type::qss3_power:
......@@ -290,6 +291,7 @@ get_output_port_names() noexcept
std::is_same_v<Dynamics, mult_4> ||
std::is_same_v<Dynamics, counter> ||
std::is_same_v<Dynamics, buffer> ||
std::is_same_v<Dynamics, buffer> ||
std::is_same_v<Dynamics, generator> ||
std::is_same_v<Dynamics, constant> ||
std::is_same_v<Dynamics, time_func> ||
......@@ -588,15 +590,17 @@ private:
auto* mdl_dst = sim.models.try_to_get(map[mdl_dst_id]);
irt_return_if_fail(mdl_dst, status::io_file_format_model_unknown);
output_port_id output_port;
input_port_id input_port;
port* output_port = nullptr;
port* input_port = nullptr;
irt_return_if_bad(
sim.get_output_port_id(*mdl_src, port_src_index, &output_port));
sim.get_output_port(*mdl_src, port_src_index, output_port));
irt_return_if_bad(
sim.get_input_port(*mdl_dst, port_dst_index, input_port));
irt_return_if_bad(
sim.get_input_port_id(*mdl_dst, port_dst_index, &input_port));
sim.connect(*mdl_src, port_src_index, *mdl_dst, port_dst_index));
irt_return_if_bad(sim.connect(output_port, input_port));
++connection_error;
}
......@@ -698,26 +702,20 @@ private:
irt_return_if_fail(convert(dynamics_name, &type),
status::io_file_format_dynamics_unknown);
model_id mdl_id = static_cast<model_id>(0);
auto ret = sim.dispatch(type, [this, &sim, &mdl_id](auto& dyn_models) {
irt_return_if_fail(dyn_models.can_alloc(1),
status::io_file_format_dynamics_limit_reach);
auto& dyn = dyn_models.alloc();
auto dyn_id = dyn_models.get_id(dyn);
sim.alloc(dyn, dyn_id);
mdl_id = dyn.id;
auto& mdl = sim.alloc(type);
update_error_report();
update_error_report();
irt_return_if_fail(read(dyn),
status::io_file_format_dynamics_init_error);
auto ret =
sim.dispatch(mdl, [this]<typename Dynamics>(Dynamics& dyn) -> status {
irt_return_if_fail(this->read(dyn),
status::io_file_format_dynamics_init_error);
return status::success;
});
return status::success;
});
irt_return_if_bad(ret);
map[id] = mdl_id;
map[id] = sim.models.get_id(mdl);
return status::success;
}
......@@ -1086,43 +1084,40 @@ struct writer
os << id << ' ';
map[id] = mdl_id;
sim.dispatch(mdl->type, [this, mdl](auto& dyn_models) {
write(dyn_models.get(mdl->id));
sim.dispatch(*mdl, [this, mdl](auto& dyn) -> void {
this->write(dyn);
});
++id;
}
irt::output_port* out = nullptr;
while (sim.output_ports.next(out)) {
for (auto dst : out->connections) {
if (auto* in = sim.input_ports.try_to_get(dst); in) {
auto* mdl_src = sim.models.try_to_get(out->model);
auto* mdl_dst = sim.models.try_to_get(in->model);
if (!(mdl_src && mdl_dst))
continue;
int src_index = -1;
int dst_index = -1;
irt_return_if_bad(
sim.get_input_port_index(*mdl_dst, dst, &dst_index));
irt_return_if_bad(sim.get_output_port_index(
*mdl_src, sim.output_ports.get_id(out), &src_index));
auto it_out = std::find(map.begin(), map.end(), out->model);
auto it_in = std::find(map.begin(), map.end(), in->model);
assert(it_out != map.end());
assert(it_in != map.end());
os << std::distance(map.begin(), it_out) << ' ' << src_index
<< ' ' << std::distance(map.begin(), it_in) << ' '
<< dst_index << '\n';
mdl = nullptr;
while (sim.models.next(mdl)) {
sim.dispatch(*mdl, [this, &sim, &mdl]<typename Dynamics>(Dynamics& dyn) {
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
for (size_t i = 0, e = std::size(dyn.y); i != e; ++i) {
for (const auto& elem : dyn.y[i].connections) {
auto* dst = sim.models.try_to_get(elem.model);
if (dst) {
auto it_out = std::find(map.begin(), map.end(), sim.models.get_id(*mdl));
auto it_in = std::find(map.begin(), map.end(), elem.model);
irt_assert(it_out != map.end());
irt_assert(it_in != map.end());
os << std::distance(map.begin(), it_out)
<< ' '
<< i
<< ' '
<< std::distance(map.begin(), it_in)
<< ' '
<< elem.port_index
<< '\n';
}
}
}
}
}
});
}
return status::success;
......@@ -1351,8 +1346,7 @@ private:
void write(const generator& dyn) noexcept
{
os << "generator " << ' ' << dyn.default_offset
<< '\n';
os << "generator " << ' ' << dyn.default_offset << '\n';
}
void write(const constant& dyn) noexcept
......@@ -1418,7 +1412,7 @@ private:
void write(const time_func& dyn) noexcept
{
os << "time_func "
<< (dyn.default_f == &time_function ? "time\n" : "square\n");
<< (dyn.default_f == &time_function ? "time\n" : "square\n");
}
void write(const flow& dyn) noexcept
......@@ -1434,36 +1428,37 @@ private:
public:
dot_writer(std::ostream& os_)
: os(os_)
: os(os_)
{}
void operator()(const simulation& sim) noexcept
{
os << "digraph graphname {\n";