typedef struct ses_path_s ses_path_t;
typedef struct ses_edge_s ses_edge_t;
typedef struct ses_flow_s ses_flow_t;
+typedef struct ses_node_s ses_node_t;
typedef struct ses_mesh_s ses_mesh_t;
typedef struct ses_info_s ses_info_t;
struct ses_edge_s
{
int refs;
+ int index;
ses_path_t* path;
int vip_m;
int n_diodes;
int n_NPNs;
+ ses_node_t* node0;
+ ses_node_t* node1;
+
double cv;
double r;
double v;
double a;
double a0;
+
+ uint8_t vflag:1;
+};
+
+struct ses_node_s
+{
+ scf_vector_t* edges;
+
+ double v;
+ double a;
+ double a0;
+
+ int index;
+ int vip_i;
};
struct ses_mesh_s
void ses_meshs_print(scf_vector_t* meshs);
void ses_meshs_free (scf_vector_t* meshs);
+ses_node_t* ses_node_alloc();
+void ses_node_free (ses_node_t* node);
+void ses_node_print(ses_node_t* node);
+
+void ses_nodes_free (scf_vector_t* nodes);
+void ses_nodes_print(scf_vector_t* nodes);
+
ses_flow_t* ses_flow_alloc();
void ses_flow_free (ses_flow_t* flow);
void ses_flow_print(ses_flow_t* flow);
int __ses_meshs_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count);
int __ses_meshs_PPN_solve (ScfEfunction* f, ses_flow_t* flow, ses_path_t* bridge, int* changed, int64_t ns, int64_t count);
+int __ses_nodes_path(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t** nodes);
+int __ses_nodes_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count);
+
int __ses_path_jr (ScfEfunction* f, ses_path_t* path);
void __ses_path_pr (ScfEfunction* f, ses_path_t* path, int i, int j, ses_path_t* child, double* r);
void __ses_path_jpr(ScfEfunction* f, ses_path_t* path, int i, int j, ses_path_t* child, double* jr);
--- /dev/null
+#include"ses_core.h"
+#include <gsl/gsl_linalg.h>
+
+int ses_node_ref_edge(ses_node_t* node, ses_edge_t* edge)
+{
+ int ret = scf_vector_add(node->edges, edge);
+ if (ret < 0)
+ return ret;
+
+ edge->refs++;
+ return 0;
+}
+
+int ses_node_add_edge(ses_node_t* node, ses_path_t* path, int m, int n, ses_edge_t** pp)
+{
+ ses_edge_t* edge = ses_edge_alloc(path, m, n);
+ if (!edge)
+ return -ENOMEM;
+
+ int ret = scf_vector_add(node->edges, edge);
+ if (ret < 0) {
+ ses_edge_free(edge);
+ return ret;
+ }
+
+ if (pp)
+ *pp = edge;
+ return 0;
+}
+
+ses_edge_t* ses_nodes_find_edge(scf_vector_t* nodes, ses_path_t* path, int vip_m, int vip_n)
+{
+ ses_node_t* node;
+ ses_edge_t* edge;
+
+ int i;
+ int j;
+
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ for (j = 0; j < node->edges->size; j++) {
+ edge = node->edges->data[j];
+
+ if (edge->path == path
+ && edge->vip_m == vip_m
+ && edge->vip_n == vip_n)
+ return edge;
+ }
+ }
+
+ return NULL;
+}
+
+int __ses_nodes_path(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t** nodes)
+{
+ scf_vector_t* vec;
+ ses_path_t* child;
+ ses_path_t* bridge;
+
+ ses_edge_t* edge = NULL;
+ ses_node_t* prev = NULL;
+ ses_node_t* node = NULL;
+
+ int ret = -1;
+
+ vec = scf_vector_alloc();
+ if (!vec)
+ return -ENOMEM;
+
+ int n_nodes = 0;
+ int n_edges = 0;
+
+ int i;
+ int j = vip_n;
+ int k;
+
+ for (i = vip_n - 1; i > vip_m; i -= 2) {
+
+ ScfEpin* p = path->pins->data[i];
+
+ if (!path->childs)
+ continue;
+
+ node = ses_node_alloc();
+ if (!node) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ret = ses_node_add_edge(node, path, i, j, &edge);
+ if (ret < 0) {
+ ses_node_free(node);
+ goto error;
+ }
+ edge->index = n_edges++;
+ edge->node1 = node;
+
+ if (prev) {
+ ret = ses_node_ref_edge(prev, edge);
+ if (ret < 0) {
+ ses_node_free(node);
+ goto error;
+ }
+ edge->node0 = prev;
+ }
+
+ for (k = 0; k < path->childs->size; k++) {
+ child = path->childs->data[k];
+
+ if (child->parent_p0 == i) {
+#define CHILD_EDGE_ADD_UNIQUE() \
+ edge = ses_nodes_find_edge(vec, child, 0, child->pins->size - 1); \
+ if (edge) { \
+ ret = ses_node_ref_edge(node, edge); \
+ if (ret < 0) { \
+ ses_node_free(node); \
+ goto error; \
+ } \
+ } else { \
+ ret = ses_node_add_edge(node, child, 0, child->pins->size - 1, &edge); \
+ if (ret < 0) { \
+ ses_node_free(node); \
+ goto error; \
+ } \
+ edge->index = n_edges++; \
+ } \
+
+ CHILD_EDGE_ADD_UNIQUE();
+ edge->node1 = node;
+
+ } else if (child->parent_p1 == i - 1) {
+
+ CHILD_EDGE_ADD_UNIQUE();
+ edge->node0 = node;
+ }
+ }
+
+ if (path->bridges) {
+ for (k = 0; k < path->bridges->size; k++) {
+ bridge = path->bridges->data[k];
+
+ if (bridge->parent_p0 == i) {
+#define BRIDGE_EDGE_ADD_UNIQUE() \
+ edge = ses_nodes_find_edge(vec, bridge, 0, bridge->pins->size - 1); \
+ if (edge) { \
+ ret = ses_node_ref_edge(node, edge); \
+ if (ret < 0) { \
+ ses_node_free(node); \
+ goto error; \
+ } \
+ } else { \
+ ret = ses_node_add_edge(node, bridge, 0, bridge->pins->size - 1, &edge); \
+ if (ret < 0) { \
+ ses_node_free(node); \
+ goto error; \
+ } \
+ edge->index = n_edges++; \
+ if (prev) { \
+ ret = ses_node_ref_edge(node, edge); \
+ if (ret < 0) { \
+ ses_node_free(node); \
+ goto error; \
+ } \
+ } \
+ }
+
+ BRIDGE_EDGE_ADD_UNIQUE();
+ edge->node1 = node;
+
+ } else if (bridge->parent_p1 == i - 1) {
+
+ BRIDGE_EDGE_ADD_UNIQUE();
+ edge->node0 = node;
+ }
+ }
+ }
+
+ ret = scf_vector_add(vec, node);
+ if (ret < 0) {
+ ses_node_free(node);
+ goto error;
+ }
+ node->index = n_nodes++;
+ node->vip_i = i;
+
+ prev = node;
+
+ j = i - 1;
+ }
+
+ if (j > vip_m) {
+ if (!node) {
+ node = ses_node_alloc();
+ if (!node) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ret = scf_vector_add(vec, node);
+ if (ret < 0) {
+ ses_node_free(node);
+ goto error;
+ }
+ node->index = n_nodes++;
+ node->vip_i = j;
+ }
+
+ ret = ses_node_add_edge(node, path, vip_m, j, &edge);
+ if (ret < 0)
+ goto error;
+ edge->index = n_edges++;
+ edge->node0 = node;
+ }
+
+ *nodes = vec;
+ return 0;
+
+error:
+ scf_vector_clear(vec, (void (*)(void*) )ses_node_free);
+ scf_vector_free(vec);
+ return ret;
+}
+
+/*
+ v[0]
+ v[1]
+ ...
+ v[n - 1]
+
+ i[0]
+ i[1]
+ ...
+ i[m - 1]
+ -------------
+ a[0][0] + a[0][1] + ... + a[0][m] = 0
+...
+ a[n - 1][0] + a[n - 1][1] + ... + a[n - 1][m] = 0
+
+ v[0][0] - v[0][1] - a[0] * R[0] = C[0]
+ ...
+ v[m - 1][0] - v[m - 1][1] - a[m - 1] * R[m - 1] = C[m - 1]
+ */
+static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t* nodes, int* changed, int64_t ns, int64_t count)
+{
+ ses_node_t* node;
+ ses_edge_t* edge;
+
+ ScfEline* el;
+ ScfEpin* pm = path->pins->data[vip_m];
+ ScfEpin* pn = path->pins->data[vip_n];
+ ScfEpin* p0;
+ ScfEpin* p1;
+
+ int ret = 0;
+ int i;
+ int j;
+
+ int m = 0;
+ int n = nodes->size;
+
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ for (j = 0; j < node->edges->size; j++) {
+ edge = node->edges->data[j];
+
+ if (!edge->vflag) {
+ m++;
+ edge->vflag = 1;
+ }
+ }
+ }
+
+ int N = n + m;
+
+ scf_logi("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, n_nodes: %d, n_edges: %d, N: %d\n", pm->cid, pm->id, pm->v, pn->cid, pn->id, pn->v, n, m, N);
+
+ double* A = calloc(N * N + N + N, sizeof(double));
+ if (!A)
+ return -ENOMEM;
+
+ double* b = A + N * N;
+ double* X = b + N;
+ double cv;
+ double r;
+
+ __ses_path_jr(f, path);
+
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ b[i] = 0;
+
+ for (j = 0; j < node->edges->size; j++) {
+ edge = node->edges->data[j];
+
+ if (edge->path == path) {
+ if (edge->vip_m < node->vip_i)
+ A[i * N + n + edge->index] = 1;
+ else
+ A[i * N + n + edge->index] = -1;
+ } else {
+ if (edge->path->parent_p0 < node->vip_i)
+ A[i * N + n + edge->index] = 1;
+ else
+ A[i * N + n + edge->index] = -1;
+ }
+ }
+ }
+
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ scf_logd("node->index: %d\n", node->index);
+
+ for (j = 0; j < node->edges->size; j++) {
+ edge = node->edges->data[j];
+
+ if (!edge->vflag)
+ continue;
+ edge->vflag = 0;
+
+ __ses_path_capacitors(f, edge->path, edge->vip_m, edge->vip_n, &cv);
+
+ if (0 == edge->vip_m && edge->vip_n == edge->path->pins->size - 1)
+ r = edge->path->pr;
+ else
+ __ses_path_sr(f, edge->path, edge->vip_m, edge->vip_n, &r);
+
+ edge->r = r;
+
+ p0 = edge->path->pins->data[edge->vip_m];
+ p1 = edge->path->pins->data[edge->vip_n];
+
+ scf_logd("c%ldp%ld-c%ldp%ld, r: %lg, cv: %lg, edge->index: %d\n", p0->cid, p0->id, p1->cid, p1->id, r, cv, edge->index);
+
+ b[n + edge->index] = cv;
+ A[(n + edge->index) * N + n + edge->index] = -r;
+
+ if (edge->path == path) {
+
+ if (edge->node0)
+ A[(n + edge->index) * N + edge->node0->index] = -1;
+
+ else if (edge->vip_n == vip_n)
+ b[n + edge->index] += pn->v;
+
+
+ if (edge->node1)
+ A[(n + edge->index) * N + edge->node1->index] = 1;
+
+ else if (edge->vip_m == vip_m)
+ b[n + edge->index] -= pm->v;
+
+ } else {
+ if (edge->node0)
+ A[(n + edge->index) * N + edge->node0->index] = -1;
+
+ else if (edge->path->parent_p1 == vip_n)
+ b[n + edge->index] -= pn->v;
+
+
+ if (edge->node1)
+ A[(n + edge->index) * N + edge->node1->index] = 1;
+
+ else if (edge->path->parent_p0 == vip_m)
+ b[n + edge->index] -= pm->v;
+ }
+ }
+ }
+
+ gsl_matrix_view _A = gsl_matrix_view_array(A, N, N);
+ gsl_vector_view _b = gsl_vector_view_array(b, N);
+ gsl_vector_view _X = gsl_vector_view_array(X, N);
+
+ int s;
+ gsl_permutation* _P = gsl_permutation_alloc(N);
+ if (!_P) {
+ ret = -ENOMEM;
+ goto P_failed;
+ }
+
+ gsl_linalg_LU_decomp(&_A.matrix, _P, &s);
+ gsl_linalg_LU_solve (&_A.matrix, _P, &_b.vector, &_X.vector);
+
+#if 0
+ for (i = 0; i < N; i++) {
+ for (j = 0; j < N; j++)
+ printf("%5lg ", A[i * N + j]);
+ printf("\n");
+ }
+ scf_logi("b:\n");
+ gsl_vector_fprintf(stdout, &_b.vector, "%lg");
+#endif
+
+ scf_logi("X:\n");
+ gsl_vector_fprintf(stdout, &_X.vector, "%lg");
+
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ p0 = path->pins->data[node->vip_i];
+
+ el = f->elines[p0->lid];
+ el->v = X[i];
+ }
+
+#if 1
+ for (i = 0; i < nodes->size; i++) {
+ node = nodes->data[i];
+
+ for (j = 0; j < node->edges->size; j++) {
+ edge = node->edges->data[j];
+
+ p0 = edge->path->pins->data[edge->vip_m];
+ p1 = edge->path->pins->data[edge->vip_n];
+
+ scf_logi("c%ldp%ld--c%ldp%ld, edge->vflag: %d\n", p0->cid, p0->id, p1->cid, p1->id, edge->vflag);
+
+ if (edge->vflag)
+ continue;
+ edge->vflag = 1;
+
+ p0->v = f->elines[p0->lid]->v;
+ p1->v = f->elines[p1->lid]->v;
+
+ ret = __ses_path_va_branch(f, edge->path, edge->vip_m, edge->vip_n, edge->r, changed, ns, count);
+ if (ret < 0)
+ goto error;
+ }
+ }
+#endif
+error:
+ gsl_permutation_free(_P);
+P_failed:
+ free(A);
+ return ret;
+}
+
+int __ses_nodes_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count)
+{
+ scf_vector_t* nodes = NULL;
+ ses_node_t* node;
+ ses_edge_t* edge;
+
+ ScfEline* el;
+ ScfEpin* pm = path->pins->data[vip_m];
+ ScfEpin* pn = path->pins->data[vip_n];
+ ScfEpin* p0;
+ ScfEpin* p1;
+
+ int ret = __ses_nodes_path(f, path, vip_m, vip_n, &nodes);
+ if (ret < 0)
+ return ret;
+
+ ses_nodes_print(nodes);
+
+ ret = __ses_nodes_path_solve2(f, path, vip_m, vip_n, nodes, changed, ns, count);
+
+ scf_vector_clear(nodes, (void (*)(void*) )ses_node_free);
+ scf_vector_free(nodes);
+
+ return ret;
+}