return 0;
}
+static void ses_AbX_print(double* A, double* b, double* X, int N)
+{
+ int i;
+ int j;
+
+ printf("A:\n");
+ for (i = 0; i < N; i++) {
+ for (j = 0; j < N; j++)
+ printf("%3lg ", A[i * N + j]);
+ printf("\n");
+ }
+
+ printf("\nb:\n");
+ for (j = 0; j < N; j++)
+ printf("%lg\n", b[j]);
+
+ printf("\nX:\n");
+ for (j = 0; j < N; j++)
+ printf("%lg\n", X[j]);
+}
+
/*
v[0]
v[1]
...
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, scf_vector_t* edges, int* changed, int64_t ns, int64_t count)
+
+static void __ses_nodes_set_Ab(ScfEfunction* f, scf_vector_t* nodes, scf_vector_t* edges, int64_t ns, double* A, double* b, int N)
{
ses_node_t* node;
ses_edge_t* edge;
- ScfEcomponent* c;
ScfEcomponent* B = f->components[0];
ScfEpin* Bp = B->pins[SCF_EDA_Battery_POS];
ScfEpin* Bn = B->pins[SCF_EDA_Battery_NEG];
-
- ScfEpin* pm = path->pins->data[vip_m];
- ScfEpin* pn = path->pins->data[vip_n];
ScfEpin* p0;
ScfEpin* p1;
- ScfEline* el;
-
- int ret = 0;
- int i;
- int j;
- int m = edges->size;
- int n = nodes->size;
-
- if (pm->lid == Bp->lid)
- n = nodes->size - 1;
-
- int N = n + m;
-
- pm->v = f->elines[pm->lid]->v;
- pn->v = f->elines[pn->lid]->v;
-
- scf_logi("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, n: %d, m: %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 + (N + N + N * N + N * N), sizeof(double));
- if (!A)
- return -ENOMEM;
-
- double* b = A + N * N;
- double* X = b + N;
- double* W = X + N;
- double* S = W + N;
- double* V = S + N;
- double* U = V + N * N;
double cv;
double lv;
double uf;
double la;
double r;
- __ses_path_jr(f, path);
+ int n = N - edges->size;
+ int i;
+ int j;
for (i = 0; i < n; i++) {
node = nodes->data[i];
else
b[n + edge->index] -= Bp->v;
}
+}
- scf_logi("-----check transistor ON / OFF\n");
-
- gsl_matrix_view _A = gsl_matrix_view_array(U, N, N);
- gsl_vector_view _b = gsl_vector_view_array(b, N);
- gsl_vector_view _X = gsl_vector_view_array(X, N);
+static int __ses_edges_update_Ab(ScfEfunction* f, scf_vector_t* edges, double* A, double* b, double* X, int N, int* n_offs)
+{
+ ses_edge_t* edge;
- gsl_vector_view _W = gsl_vector_view_array(W, N);
- gsl_vector_view _S = gsl_vector_view_array(S, N);
- gsl_matrix_view _V = gsl_matrix_view_array(V, N, N);
+ ScfEcomponent* c;
+ ScfEcomponent* B = f->components[0];
+ ScfEpin* Bp = B->pins[SCF_EDA_Battery_POS];
+ ScfEpin* Bn = B->pins[SCF_EDA_Battery_NEG];
+ ScfEpin* p0;
+ ScfEpin* p1;
- int __changed = 0;
- int __need = 0;
+ int n = N - edges->size;
+ int k = 0;
+ int i;
+ int j;
- do {
- __changed = 0;
- __need = 0;
+ for (j = 0; j < edges->size; j++) {
+ edge = edges->data[j];
- memcpy(U, A, sizeof(double) * N * N);
-#if 1
- for (i = 0; i < N; i++) {
- for (j = 0; j < N; j++)
- printf("%lg ", A[i * N + j]);
- printf("\n");
- }
- printf("\n");
+ p0 = edge->path->pins->data[edge->vip_m];
+ p1 = edge->path->pins->data[edge->vip_n];
+ c = f->components[p0->cid];
- for (j = 0; j < N; j++)
- printf("%lg\n", b[j]);
-#endif
+ if (edge->bflag) {
+ double Vb;
+ double Ve;
- gsl_linalg_SV_decomp(&_A.matrix, &_V.matrix, &_S.vector, &_W.vector);
- gsl_linalg_SV_solve (&_A.matrix, &_V.matrix, &_S.vector, &_b.vector, &_X.vector);
+ if (edge->node1 && edge->node1->lid != Bp->lid)
+ Vb = X[edge->node1->index];
+ else
+ Vb = Bp->v;
- scf_logi("X:\n");
- for (i = 0; i < N; i++)
- scf_logi("%lg\n", X[i]);
+ if (edge->node0 && edge->node0->lid != Bn->lid)
+ Ve = X[edge->node0->index];
+ else
+ Ve = Bn->v;
- for (j = 0; j < edges->size; j++) {
- edge = edges->data[j];
+ double dV = Vb - Ve;
+ double Ib = X[n + edge->index];
+ double Rb = SCF_EDA_V_NPN_ON / Ib;
- p0 = edge->path->pins->data[edge->vip_m];
- p1 = edge->path->pins->data[edge->vip_n];
- c = f->components[p0->cid];
+ if (-1e8 < Rb && Rb < 1e8) {
+ if (dV < SCF_EDA_V_NPN_ON * 0.995 || dV > SCF_EDA_V_NPN_ON * 1.005) {
- if (edge->bflag) {
- double Vb;
- double Ve;
+ scf_logd("edge: [%d] c%ldp%ld-c%ldp%ld, Vb: %lg, Ve: %lg, dV: %lg, Ib: %lg, Rb: %lg\n",
+ edge->index, p0->cid, p0->id, p1->cid, p1->id, Vb, Ve, dV, Ib, Rb);
- if (edge->node1 && edge->node1->lid != Bp->lid)
- Vb = X[edge->node1->index];
- else
- Vb = Bp->v;
+ A[(n + edge->index) * N + n + edge->index] = -Rb;
+ k++;
+ }
+ } else {
+ c->status = SCF_EDA_Status_OFF;
+ c->lock = 1;
+ (*n_offs)++;
- if (edge->node0 && edge->node0->lid != Bn->lid)
- Ve = X[edge->node0->index];
- else
- Ve = Bn->v;
+ scf_loge("\033[34mc%ld, status: %d, dV: %lg, Ib: %lg, Rb: %lg, edge->index: %d\033[0m\n", c->id, c->status, dV, Ib, Rb, edge->index);
+ }
- double dV = Vb - Ve;
+ } else if (edge->edge_b) {
+ double Ic = X[n + edge->index];
+ double Ib = X[n + edge->edge_b->index];
- if (dV > 0.07) {
- if (dV < SCF_EDA_V_NPN_ON * 0.99) {
+ double dI = Ib * edge->hfe - Ic;
- scf_logi("edge: [%d] c%ldp%ld-c%ldp%ld, Vb: %lg, Ve: %lg, dV: %lg\n",
- edge->index, p0->cid, p0->id, p1->cid, p1->id, Vb, Ve, dV);
+ if (dI < -1e-10) {
+ scf_logd("edge: [%d] c%ldp%ld-c%ldp%ld [b%d], Ic: %lg, Ib: %lg, dI: %lg\n",
+ edge->index, p0->cid, p0->id, p1->cid, p1->id, edge->edge_b->index, Ic, Ib, dI);
- double Ib = X[n + edge->index];
+ for (i = 0; i < N; i++)
+ A[(n + edge->index) * N + i] = 0;
- A[(n + edge->index) * N + n + edge->index] = -SCF_EDA_V_NPN_ON / Ib;
- __need++;
- }
- } else {
- c->status = SCF_EDA_Status_OFF;
- c->lock = 1;
- __changed++;
+ A[(n + edge->index) * N + n + edge->index] = -1;
+ A[(n + edge->index) * N + n + edge->edge_b->index] = edge->hfe;
+ b[ n + edge->index] = 0;
- scf_loge("\033[34mc%ld, status: %d, dV: %lg, edge->index: %d\033[0m\n", c->id, c->status, dV, edge->index);
- }
+ k++;
}
}
- } while (__need > 0);
-
- scf_logi("-----check transistor on amplified / saturate\n");
-
- memcpy(U, A, sizeof(double) * N * N);
-#if 1
- for (i = 0; i < N; i++) {
- for (j = 0; j < N; j++)
- printf("%lg ", A[i * N + j]);
- printf("\n");
- }
- printf("\n");
-
- for (j = 0; j < N; j++)
- printf("%lg\n", b[j]);
-#endif
- gsl_linalg_SV_decomp(&_A.matrix, &_V.matrix, &_S.vector, &_W.vector);
- gsl_linalg_SV_solve (&_A.matrix, &_V.matrix, &_S.vector, &_b.vector, &_X.vector);
-
- scf_logi("X:\n");
- for (i = 0; i < N; i++)
- scf_logi("%lg\n", X[i]);
-
- for (i = 0; i < n; i++) {
- node = nodes->data[i];
-
- el = f->elines[node->lid];
- el->v = X[i];
}
- if (__changed > 0) {
- *changed += __changed;
- return 0;
- }
+ return k;
+}
- for (j = 0; j < edges->size; j++) {
- edge = edges->data[j];
+static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t* nodes, scf_vector_t* edges, int* changed, int64_t ns, int64_t count)
+{
+ ses_node_t* node;
+ ses_edge_t* edge;
- if (edge->edge_b) {
- double Ic = X[n + edge->index];
- double Ib = X[n + edge->edge_b->index];
+ ScfEcomponent* c;
+ ScfEcomponent* B = f->components[0];
+ ScfEpin* Bp = B->pins[SCF_EDA_Battery_POS];
+ ScfEpin* Bn = B->pins[SCF_EDA_Battery_NEG];
- double dI = Ib * edge->hfe - Ic;
+ ScfEpin* pm = path->pins->data[vip_m];
+ ScfEpin* pn = path->pins->data[vip_n];
+ ScfEpin* p0;
+ ScfEpin* p1;
+ ScfEline* el;
- if (Ib > 0 && dI < -1e-10) {
- p0 = edge->path->pins->data[edge->vip_m];
- p1 = edge->path->pins->data[edge->vip_n];
+ int ret = 0;
+ int i;
+ int j;
- scf_logi("edge: [%d] c%ldp%ld-c%ldp%ld [b%d], Ic: %lg, Ib: %lg, dI: %lg\n",
- edge->index, p0->cid, p0->id, p1->cid, p1->id, edge->edge_b->index, Ic, Ib, dI);
+ int m = edges->size;
+ int n = nodes->size;
- int k;
- for (k = 0; k < N; k++)
- A[(n + edge->index) * N + k] = 0;
+ if (pm->lid == Bp->lid)
+ n = nodes->size - 1;
- A[(n + edge->index) * N + n + edge->index] = -1;
- A[(n + edge->index) * N + n + edge->edge_b->index] = edge->hfe;
- b[ n + edge->index] = 0;
- }
- }
- }
+ int N = n + m;
- scf_logi("-----final result\n");
+ pm->v = f->elines[pm->lid]->v;
+ pn->v = f->elines[pn->lid]->v;
- memcpy(U, A, sizeof(double) * N * N);
-#if 1
- for (i = 0; i < N; i++) {
- for (j = 0; j < N; j++)
- printf("%lg ", A[i * N + j]);
- printf("\n");
- }
- printf("\n");
+ scf_logi("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, n: %d, m: %d, N: %d\n", pm->cid, pm->id, pm->v, pn->cid, pn->id, pn->v, n, m, N);
- for (j = 0; j < N; j++)
- printf("%lg\n", b[j]);
-#endif
- gsl_linalg_SV_decomp(&_A.matrix, &_V.matrix, &_S.vector, &_W.vector);
- gsl_linalg_SV_solve (&_A.matrix, &_V.matrix, &_S.vector, &_b.vector, &_X.vector);
+ double* A = calloc(N * N + N + N + (N + N + N * N + N * N), sizeof(double));
+ if (!A)
+ return -ENOMEM;
- scf_logi("result X:\n");
- for (i = 0; i < N; i++)
- scf_logi("%lg\n", X[i]);
+ double* b = A + N * N;
+ double* X = b + N;
+ double* W = X + N;
+ double* S = W + N;
+ double* V = S + N;
+ double* U = V + N * N;
- for (i = 0; i < n; i++) {
- node = nodes->data[i];
+ __ses_path_jr(f, path);
- el = f->elines[node->lid];
- el->v = X[i];
- }
+ __ses_nodes_set_Ab(f, nodes, edges, ns, A, b, N);
- __changed = 0;
+ gsl_matrix_view _A = gsl_matrix_view_array(U, N, N);
+ gsl_vector_view _b = gsl_vector_view_array(b, N);
+ gsl_vector_view _X = gsl_vector_view_array(X, N);
- for (j = 0; j < edges->size; j++) {
- edge = edges->data[j];
+ gsl_vector_view _W = gsl_vector_view_array(W, N);
+ gsl_vector_view _S = gsl_vector_view_array(S, N);
+ gsl_matrix_view _V = gsl_matrix_view_array(V, N, N);
- p0 = edge->path->pins->data[edge->vip_m];
- p1 = edge->path->pins->data[edge->vip_n];
+ int n_offs = 0;
- c = f->components[p0->cid];
+ int try = 0;
+ do {
+ n_offs = 0;
- edge->a = X[n + edge->index];
+ memcpy(U, A, sizeof(double) * N * N);
- scf_logd("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, a: %lg, edge->index: %d\n", p0->cid, p0->id, p0->v, p1->cid, p1->id, p1->v, edge->a, edge->index);
+ gsl_linalg_SV_decomp(&_A.matrix, &_V.matrix, &_S.vector, &_W.vector);
+ gsl_linalg_SV_solve (&_A.matrix, &_V.matrix, &_S.vector, &_b.vector, &_X.vector);
- if (SCF_EDA_NPN == c->type) {
- p0->a = edge->a;
- p1->a = c->pins[SCF_EDA_NPN_B]->a + c->pins[SCF_EDA_NPN_C]->a;
+// ses_AbX_print(A, b, X, N);
- if (SCF_EDA_NPN_B == p0->id && edge->a < 0) {
- c->status = SCF_EDA_Status_OFF;
- c->lock = 1;
- __changed++;
+ ret = __ses_edges_update_Ab(f, edges, A, b, X, N, &n_offs);
+ try++;
- scf_loge("\033[34mc%ld, status: %d, a: %lg, edge->index: %d\033[0m\n", c->id, c->status, edge->a, edge->index);
- }
+ } while (ret > 0 && try < 100);
- } else if (SCF_EDA_PNP == c->type) {
- p1->a = edge->a;
- p0->a = c->pins[SCF_EDA_PNP_B]->a + c->pins[SCF_EDA_PNP_C]->a;
+ scf_logi("ret: %d, try: %d\n\n", ret, try);
- if (SCF_EDA_PNP_B == p1->id && edge->a < 0) {
- c->status = SCF_EDA_Status_OFF;
- c->lock = 1;
- __changed++;
+ for (i = 0; i < n; i++) {
+ node = nodes->data[i];
- scf_loge("\033[34mc%ld, status: %d, a: %lg, edge->index: %d\033[0m\n", c->id, c->status, edge->a, edge->index);
- }
- }
+ el = f->elines[node->lid];
+ el->v = X[i];
}
- if (__changed > 0) {
- *changed += __changed;
+ if (n_offs > 0) {
+ *changed += n_offs;
+ free(A);
return 0;
}
scf_logd("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, a: %lg, edge->index: %d\n", p0->cid, p0->id, p0->v, p1->cid, p1->id, p1->v, edge->a, edge->index);
+ edge->a = X[n + edge->index];
+
if (SCF_EDA_NPN == c->type) {
ses_ui_r(&edge->r, 0, p0->v - p1->v, 0, edge->a, 0);
p0->dr = edge->r - p0->r;
p0->a = edge->a;
p1->a = c->pins[SCF_EDA_NPN_B]->a + c->pins[SCF_EDA_NPN_C]->a;
-
- if (SCF_EDA_NPN_B == p0->id && p0->a < 0) {
- c->status = SCF_EDA_Status_OFF;
-
- scf_loge("\033[34mc%ld, status: %d, a: %lg, edge->index: %d\033[0m\n", c->id, c->status, edge->a, edge->index);
- }
continue;
} else if (SCF_EDA_PNP == c->type) {
p1->dr = edge->r - p1->r;
p1->a = edge->a;
p0->a = c->pins[SCF_EDA_PNP_B]->a + c->pins[SCF_EDA_PNP_C]->a;
-
- if (SCF_EDA_PNP_B == p1->id && p1->a < 0) {
- c->status = SCF_EDA_Status_OFF;
-
- scf_loge("\033[34mc%ld, status: %d, a: %lg, edge->index: %d\033[0m\n", c->id, c->status, edge->a, edge->index);
- }
continue;
} else if (SCF_EDA_Inductor == c->type) {