update the bridge algorithm for capacitor
authoryu.dongliang <18588496441@163.com>
Fri, 26 Apr 2024 08:33:42 +0000 (16:33 +0800)
committeryu.dongliang <18588496441@163.com>
Fri, 26 Apr 2024 08:33:42 +0000 (16:33 +0800)
16 files changed:
Makefile
main.c
ses_core.h
ses_layout.c
ses_step_da.c [deleted file]
ses_step_jr.c
ses_step_simplify.c
ses_step_topo.c
ses_step_va.c
ses_step_va_bridge.c
ses_step_va_capacitor.c
ses_step_va_diode.c
ses_step_va_transistor.c
ses_utils.c
test/bridge_algorithm.c [new file with mode: 0644]
test/main.c

index aaec5b73c7f1ac5b5423aeaf1a8818b7aa6042d5..3c1bf1818919d9649f9dc822eb2684991bf26364 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,6 @@ CFILES += ses_step_va_transistor.c
 CFILES += ses_step_va.c 
 CFILES += ses_step_va_bridge.c
 CFILES += ses_step_va_line.c
-CFILES += ses_step_da.c
 
 CFILES += ses_step_open.c
 CFILES += ses_step_va_capacitor.c
diff --git a/main.c b/main.c
index db83a15a252cb8cd7161af4d902b3e525c1d5cb9..58aeeba5f07fc09d1a0d86be6c686a93ed9fc131 100644 (file)
--- a/main.c
+++ b/main.c
@@ -107,7 +107,7 @@ int main(int argc, char* argv[])
 
                printf("f: %s\n", f->name);
 
-               ses_steps_analyse(f, 1000, 4);
+               ses_steps_analyse(f, 300, 1);
        }
 #endif
 
index b19f64b90d8ee7c2d838c65994fc60340133359d..eb50c7d3ac217da6c4e9ea95ee08df3ad9da8ade 100644 (file)
@@ -79,7 +79,10 @@ struct ses_path_s
 
        int            n_capacitors;
        int            n_diodes;
+       int            n_transistors;
        int            n_layers;
+
+       uint8_t        vflag:1;
 };
 
 struct ses_ctx_s
@@ -107,6 +110,8 @@ int         ses_path_xchg (ses_path_t* path0, int k0, ses_path_t* path1, int k1)
 ses_path_t* ses_path_save (ses_path_t* src);
 int         ses_path_load (ses_path_t* dst, ses_path_t* src);
 
+ses_path_t* ses_path_find_child(ses_path_t* path, int m, int n);
+
 ses_flow_t* ses_flow_alloc();
 void        ses_flow_free (ses_flow_t* flow);
 void        ses_flow_print(ses_flow_t* flow);
@@ -123,23 +128,29 @@ int ses_layout_board (ScfEboard*    b);
 int ses_steps_analyse(ScfEfunction* f, int64_t ns, int64_t count);
 
 int ses_flows_make_path(ses_path_t** ppath, ses_flow_t* pos, ses_flow_t* neg, ses_path_t* bridge, int reverse);
+
 int ses_paths_find_flow(ses_flow_t* flow, scf_vector_t* paths, ScfEpin* vip,  ses_path_t* bridge);
+int ses_flow_find_pos  (ses_flow_t* flow, scf_vector_t* paths, ScfEfunction* f);
+int ses_flow_find_neg  (ses_flow_t* flow, scf_vector_t* paths, ScfEfunction* f);
+
+int  __ses_path_va_diode     (ScfEfunction* f, ses_path_t* path);
+int  __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path);
+int  __ses_path_va_bridge    (ScfEfunction* f, ses_path_t* bridge, int* changed, scf_vector_t* paths, int64_t ns, int64_t count);
+
+void __ses_path_split_i(ScfEfunction* f, ses_path_t* path, int i, int j, double la, double* a);
+int  __ses_status_check(ScfEfunction* f, ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe, int vinit);
+int  __ses_topo_paths  (ScfEfunction* f, scf_vector_t*  paths);
 
-int  __ses_path_va_diode(ScfEfunction* f, ses_path_t* path);
-void __ses_path_split_i (ScfEfunction* f, ses_path_t* path, int i, int j, double la, double* a);
-int  __ses_status_check (ScfEfunction* f, ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe, int vinit);
-int  __ses_topo_paths   (ScfEfunction* f, scf_vector_t*  paths);
+void __ses_status_check_line(ScfEfunction* f, ScfEline* el, int* changed);
 
-void  __ses_status_check_line(ScfEfunction* f, ScfEline* el, int* changed);
-double __ses_path_v_capacitor(ScfEfunction* f, ses_path_t* path);
+int  __ses_path_capacitors(ScfEfunction* f, ses_path_t* path, int m, int n, double* cv);
 
 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);
 void __ses_path_sr (ScfEfunction* f, ses_path_t* path, int i, int j, double* r);
 void __ses_path_jsr(ScfEfunction* f, ses_path_t* path, int i, int j, double* jr);
-int  __ses_path_va (ScfEfunction* f, ses_path_t* path, int *changed, int64_t ns, int64_t count);
-int  __ses_path_da (ScfEfunction* f, ses_path_t* path, int* changed, double da);
+int  __ses_path_va (ScfEfunction* f, ses_path_t* path, int m, int n, int *changed, int64_t ns, int64_t count);
 int  __ses_path_pos(ScfEfunction* f, ScfEline*   el);
 int  __ses_path_neg(ScfEfunction* f, ScfEline*   el);
 void __ses_npn_epr (ScfEfunction* f, ScfEpin*    pe, double* r);
index e1d3504c2c7c57d2e4210a473d3a93f49f24690c..6906dc4e26ecc96b6779e6daa08fb70de3735337 100644 (file)
@@ -595,6 +595,8 @@ static void __ses_layout_path(ScfEfunction* f, ses_path_t* path, ses_path_t* bas
 
        __ses_layout_path2(f, path, base);
 
+       scf_logd("path: %d, base: %d, ------------------------\n", path->index, base->index);
+
        base = path;
 
        if (base->childs) {
@@ -607,13 +609,11 @@ static void __ses_layout_path(ScfEfunction* f, ses_path_t* path, ses_path_t* bas
 
        if (base->bridges) {
                for (i = 0; i < base->bridges->size; i++) {
-                       path      = base->childs->data[i];
+                       path      = base->bridges->data[i];
 
                        __ses_layout_path(f, path, base);
                }
        }
-
-       scf_logd("path: %d, ------------------------\n\n", base->index);
 }
 
 static int __ses_layout_lines4(ScfEfunction* f)
diff --git a/ses_step_da.c b/ses_step_da.c
deleted file mode 100644 (file)
index c1993f2..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#include"ses_core.h"
-
-static int __ses_path_split_da(ScfEfunction* f, ses_path_t* path, int i, double* da, int* changed)
-{
-       ses_path_t*    child;
-
-       ScfEcomponent* c;
-       ScfEline*      el;
-       ScfEpin*       p;
-       ScfEpin*       p2;
-       ScfEpin*       cp0;
-       ScfEpin*       cp1;
-
-       int j;
-       int k;
-       int n = 0;
-
-       p = path->pins->data[i];
-
-       for (j    = 0; j < path->childs->size; j++) {
-               child =        path->childs->data[j];
-
-               cp0 = child->pins->data[0];
-               cp1 = child->pins->data[child->pins->size - 1];
-
-               if (p->lid != cp0->lid)
-                       continue;
-
-               for (k = i + 1; k < path->pins->size; k++) {
-                       p2 =            path->pins->data[k];
-
-                       if (p2->lid == cp1->lid)
-                               break;
-               }
-
-               if (k >= path->pins->size) {
-                       scf_loge("\n");
-                       return -EINVAL;
-               }
-
-               double _r  = p2->pr - p->pr;
-               double _dv = 0;
-               double _da = 0;
-
-               __ses_path_pr(f, path, i, k, child, &_r);
-
-               ses_ir_u(&_dv, NULL, *da, 0, _r, 0);
-
-               scf_logw("child: %d, c%ldp%ld-c%ldp%ld (c%ldp%ld-c%ldp%ld), _dv: %lg, da: %lg, _r: %lg, p->pr: %lg, p->dr: %lg, p2->pr: %lg\n",
-                               child->index, p->cid, p->id, p2->cid, p2->id, cp0->cid, cp0->id, cp1->cid, cp1->id, _dv, *da, _r, p->pr, p->dr, p2->pr);
-
-               ses_ur_i(&_da, NULL, _dv, 0, child->pr, 0);
-
-               *da   -= _da;
-
-               el     = f->elines[p2->lid];
-               el->v -= _dv;
-
-               scf_loge("child: %d, c%ldp%ld, c%ldp%ld, p->v: %lg, el->v: %lg, _dv: %lg\n",
-                               child->index, p->cid, p->id, p2->cid, p2->id, p->v, el->v, _dv);
-
-               int ret = __ses_path_da(f, child, changed, _da);
-               if (ret < 0)
-                       return ret;
-
-               n++;
-       }
-
-       scf_logw("*****************\n");
-       return n;
-}
-
-static void __ses_path_split_dv(ScfEfunction* f, ses_path_t* path, int i0, int i, double da)
-{
-       ScfEcomponent* B  = f->components[0];
-       ScfEpin*       Bp = B->pins[SCF_EDA_Battery_POS];
-       ScfEpin*       Bn = B->pins[SCF_EDA_Battery_NEG];
-       ScfEpin*       p0 = path->pins->data[i0];
-       ScfEpin*       p  = path->pins->data[i];
-
-       double   dv;
-       double   r;
-
-       __ses_path_sr(f, path, i0, i, &r);
-
-       ses_ir_u(&dv, NULL, da, 0, r, 0);
-
-       if (p->lid != Bp->lid && p->lid != Bn->lid)
-               p->v  -= dv;
-
-       scf_logd("c%ldp%ld, c%ldp%ld, da: %lg, r: %lg, dv: %lg\n", p0->cid, p0->id, p->cid, p->id, da, r, dv);
-}
-
-void __ses_pn_dr(ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe)
-{
-       double v = pb->v - pe->v;
-       double r;
-
-       if (v >= SCF_EDA_V_Diode_ON) {
-
-               ses_ui_r(&r, NULL, v, 0, pb->a, 0);
-               pe->dr = r - pe->r;
-
-       } else if (v > SCF_EDA_V_Diode_OFF)
-               pe->dr = pb->r * (SCF_EDA_V_Diode_ON - SCF_EDA_V_Diode_OFF) / (v - SCF_EDA_V_Diode_OFF + 0.001);
-}
-
-void __ses_npn_dr(ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe)
-{
-       double v = pb->v - pe->v;
-       double r;
-
-       if (v >= SCF_EDA_V_NPN_ON) {
-
-               ses_ui_r(&r, NULL, v, 0, pb->a, 0);
-               pb->dr = r - pb->r;
-
-       } else if (v > SCF_EDA_V_NPN_OFF)
-               pb->dr = pb->r * (SCF_EDA_V_NPN_ON - SCF_EDA_V_NPN_OFF) / (v - SCF_EDA_V_NPN_OFF + 0.001);
-}
-
-int __ses_path_da(ScfEfunction* f, ses_path_t* path, int* changed, double da)
-{
-       if (!path)
-               return -EINVAL;
-
-       if (path->pins->size < 2) {
-               scf_loge("\n");
-               return -EINVAL;
-       }
-
-       ses_path_t*    child;
-       ScfEcomponent* c;
-       ScfEline*      el;
-       ScfEpin*       p;
-       ScfEpin*       p0;
-       ScfEpin*       p1;
-       ScfEpin*       p2;
-       ScfEpin*       cp0;
-       ScfEpin*       cp1;
-
-       int i;
-       int j;
-
-       double r  = 0;
-       double dv = 0;
-
-       path->da = da;
-
-       int i0 = 0;
-
-       for (i = 0; i < path->pins->size; i++) {
-               p  =        path->pins->data[i];
-
-               if (!(i & 0x1) && path->childs) {
-
-                       __ses_path_split_dv(f, path, i0, i, da);
-
-                       int ret = __ses_path_split_da(f, path, i, &da, changed);
-                       if (ret < 0)
-                               return ret;
-
-                       if (ret > 0) {
-                               p0 = p;
-                               i0 = i;
-                               scf_logd("i: %d, p0: c%ldp%ld\n", i, p0->cid, p0->id);
-                       }
-               } else
-                       __ses_path_split_dv(f, path, i0, i, da);
-
-               el     = f->elines[p->lid];
-               el->v  = p->v;
-               r     += p->r + p->dr;
-
-               if (i & 0x1) {
-                       c    = f->components[p->cid];
-                       r   += c->r;
-                       dv  -= p->v;
-
-                       p->a += da;
-
-                       p2     = path->pins->data[i - 1];
-                       p2->a += da;
-
-                       if (path->childs) {
-                               for (j    = 0; j < path->childs->size; j++) {
-                                       child =        path->childs->data[j];
-
-                                       cp0 = child->pins->data[0];
-                                       cp1 = child->pins->data[child->pins->size - 1];
-
-                                       if (p->lid == cp1->lid) {
-                                               da  += child->da;
-
-                                               scf_logd("path: %d, i: %d, c%ldp%ld, child->da: %lg\n", child->index, i, cp1->cid, cp1->id, child->da);
-                                       }
-                               }
-                       }
-
-                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, r: %lg, p->a: %lg, da: %lg, p->pr: %lg\n\n", path->index, i, p->cid, p->id,
-                                       p->v, dv, r, p->a, da, p->pr);
-
-                       if (SCF_EDA_Diode == c->type) {
-
-                               if (SCF_EDA_Diode_NEG == p->id) {
-                                       p2 = path->pins->data[i - 1];
-
-                                       *changed += __ses_status_check(f, c, p2, p, 1);
-
-                                       __ses_pn_dr(c, p2, p);
-                               }
-
-                       } else if (SCF_EDA_NPN == c->type) {
-
-                               if (SCF_EDA_NPN_E == p->id) {
-                                       p2 = path->pins->data[i - 1];
-
-                                       if (SCF_EDA_NPN_B == p2->id) {
-                                               *changed += __ses_status_check(f, c, p2, p, 1);
-
-                                               __ses_npn_dr(c, p2, p);
-                                       }
-                               }
-                       }
-
-                       r  = 0;
-               } else {
-                       dv = p->v;
-
-                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, p->a: %lg, da: %lg, p->pr: %lg\n", path->index, i, p->cid, p->id, p->v, dv, p->a, da, p->pr);
-               }
-       }
-       printf("\n");
-
-       return 0;
-}
index 0dc3c637d7652545b3a31dd8ce93530ce95deb89..ea709a979e82c230680741ec3229ac0a1da1b6ea 100644 (file)
@@ -213,6 +213,24 @@ int __ses_path_jr(ScfEfunction* f, ses_path_t* path)
                }
        }
 
+       if (path->bridges) {
+               for (i    = path->bridges->size - 1; i >= 0; i--) {
+                       child = path->bridges->data[i];
+
+                       cp1 = child->pins->data[child->pins->size - 1];
+
+                       for (j = 0; j < path->pins->size; j++) {
+                               p         = path->pins->data[j];
+
+                               if (p->lid == cp1->lid) {
+                                       child->parent_pr  = p->pr;
+                                       child->parent_jpr = p->jpr;
+                                       break;
+                               }
+                       }
+               }
+       }
+
        p         = path->pins->data[path->pins->size - 1];
        path->pr  = p->pr;
        path->sr  = p->sr;
index b4df409b11763a358f3002e742513d81a3a4ca7b..a9be82dc74ffc486dde7ab5e25bee93edfb72222 100644 (file)
@@ -350,7 +350,7 @@ static int _simplify_draw(ScfEfunction* f, uint32_t bx, uint32_t by, uint32_t bw
                                cairo_stroke(cr);
 
                                if (el->v < SCF_EDA_V_MIN)
-                                       snprintf(text, sizeof(text) - 1, "%lgv", B->pins[SCF_EDA_Battery_NEG]->v);
+                                       snprintf(text, sizeof(text) - 1, "0v");
                                else if (el->v > SCF_EDA_V_MAX)
                                        snprintf(text, sizeof(text) - 1, "%lgv", B->pins[SCF_EDA_Battery_POS]->v);
 
index 77ae8b428f2018586d7dc1b0d2b46b5f2bcc74ed..ca44eabe8cedd3233eb9ed5f504602ffebf0fd80 100644 (file)
@@ -298,11 +298,68 @@ static int _topo_path_bridges(ScfEfunction* f, ses_path_t* path)
        return __topo_path_bridges(f, path);
 }
 
+static int ses_pin_to_npn(const ScfEfunction* f, const ScfEpin* vip, int pid)
+{
+       const ScfEcomponent* c;
+       const ScfEline*      el = f->elines[vip->lid];
+       const ScfEpin*       p;
+
+       int i;
+       for (i = 0; i < el->n_pins; i += 2) {
+
+               c  = f->components[el->pins[i]];
+               p  = c->pins      [el->pins[i + 1]];
+
+               if (p != vip && SCF_EDA_NPN == c->type && pid == p->id)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int ses_path_to_npn(const ScfEfunction* f, const ses_path_t* path, int pid)
+{
+       const ScfEpin* p0 = path->pins->data[0];
+       const ScfEpin* p1 = path->pins->data[path->pins->size - 1];
+
+       return ses_pin_to_npn(f, p0, pid) || ses_pin_to_npn(f, p1, pid);
+}
+
+static int _ses_connect_cmp(const void* v0, const void* v1, void* arg)
+{
+       const ScfEfunction* f  = arg;
+
+       const ses_path_t*   p0 = *(const ses_path_t**)v0;
+       const ses_path_t*   p1 = *(const ses_path_t**)v1;
+
+       if (0 == p0->n_capacitors)
+               return -1;
+       if (0 == p1->n_capacitors)
+               return 1;
+
+       if (ses_path_to_npn(f, p0, SCF_EDA_NPN_C))
+               return -1;
+       if (ses_path_to_npn(f, p1, SCF_EDA_NPN_C))
+               return 1;
+
+       if (ses_path_to_npn(f, p0, SCF_EDA_NPN_B))
+               return -1;
+       if (ses_path_to_npn(f, p1, SCF_EDA_NPN_B))
+               return 1;
+
+       if (p0->n_capacitors < p1->n_capacitors)
+               return -1;
+       if (p0->n_capacitors > p1->n_capacitors)
+               return 1;
+       return 0;
+}
+
 static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
 {
        if (!f || !paths)
                return -EINVAL;
 
+       scf_vector_t*    vec;
        ses_path_t*      path0;
        ses_path_t*      path1;
 
@@ -320,9 +377,18 @@ static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
        int i;
        int j;
        int k;
+       int m;
 
-       for (i    = 0; i < paths->size; ) {
-               path0 = paths->data[i];
+       vec = scf_vector_clone(paths);
+       if (!vec)
+               return -ENOMEM;
+
+       // qsort in 'vec' and keep the origin order in 'paths'
+       qsort_r(vec->data, vec->size, sizeof(void*), _ses_connect_cmp, f);
+
+       i = 0;
+       while (i  < vec->size) {
+               path0 = vec->data[i];
 
                p0 = path0->pins->data[0];
                p1 = path0->pins->data[path0->pins->size - 1];
@@ -332,8 +398,8 @@ static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
                        continue;
                }
 
-               for (j    = 0; j < paths->size; j++) {
-                       path1 = paths->data[j];
+               for (j    = 0; j < vec->size; j++) {
+                       path1 =        vec->data[j];
 
                        if (path1 == path0)
                                continue;
@@ -346,16 +412,20 @@ static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
                                        p  =        path0->pins->data[k];
 
                                        if (scf_vector_add(path1->pins, p) < 0)
-                                               return -ENOMEM;
+                                               goto error;
                                }
                                goto connected;
 
                        } else if (p3->lid == p1->lid) {
+
+                               if (path0->n_diodes > 0 || path0->n_transistors > 0)
+                                       continue;
+
                                for (k = path0->pins->size - 1; k >= 0; k--) {
                                        p  = path0->pins->data[k];
 
                                        if (scf_vector_add(path1->pins, p) < 0)
-                                               return -ENOMEM;
+                                               goto error;
                                }
                                goto connected;
 
@@ -364,7 +434,30 @@ static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
                                        p  =        path1->pins->data[k];
 
                                        if (scf_vector_add(path0->pins, p) < 0)
-                                               return -ENOMEM;
+                                               goto error;
+                               }
+
+                               SCF_XCHG(path0->pins, path1->pins);
+                               goto connected;
+
+                       } else if (p2->lid == p0->lid) {
+
+                               if (path0->n_diodes > 0 || path0->n_transistors > 0)
+                                       continue;
+
+                               m = path0->pins->size - 1;
+                               k = 0;
+                               while (k < m) {
+                                       SCF_XCHG(path0->pins->data[k], path0->pins->data[m]);
+                                       k++;
+                                       m--;
+                               }
+
+                               for (k = 0; k < path1->pins->size; k++) {
+                                       p  =        path1->pins->data[k];
+
+                                       if (scf_vector_add(path0->pins, p) < 0)
+                                               goto error;
                                }
 
                                SCF_XCHG(path0->pins, path1->pins);
@@ -376,13 +469,20 @@ static int _topo_path_connect(ScfEfunction* f, scf_vector_t* paths)
                continue;
 
 connected:
-               if (scf_vector_del(paths, path0) < 0)
-                       return -1;
+               assert(0 == scf_vector_del(vec, path0));
+               assert(0 == scf_vector_del(paths, path0));
+
                ses_path_free(path0);
                path0 = NULL;
+               i = 0;
        }
 
+       scf_vector_free(vec);
        return 0;
+
+error:
+       scf_vector_free(vec);
+       return -ENOMEM;
 }
 
 static int _topo_path_completes(ScfEfunction* f, scf_vector_t* paths)
@@ -782,6 +882,9 @@ static void _topo_key_components(ScfEfunction* f, ses_path_t* path)
                        if (SCF_EDA_NPN_B == p->id)
                                path->n_diodes++;
 
+                       else if (SCF_EDA_NPN_C == p->id)
+                               path->n_transistors++;
+
                } else if (SCF_EDA_Capacitor == c->type) {
 
                        if (0 == p->id)
index cf08c85c0adf9bb8bdf76f9320aff3f64547ed2d..29d5518c048d3f4b9345bc2895c18ae7fb45b4b8 100644 (file)
@@ -1,6 +1,6 @@
 #include"ses_core.h"
 
-static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double* a, int* changed, int64_t ns, int64_t count)
+static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, int n, double* a, int* changed, int64_t ns, int64_t count)
 {
        ses_path_t*    child;
 
@@ -13,7 +13,7 @@ static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double*
 
        int j;
        int k;
-       int n = 0;
+       int n_childs = 0;
 
        p0 = path->pins->data[i];
 
@@ -26,17 +26,15 @@ static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double*
                if (p0->lid != cp0->lid)
                        continue;
 
-               for (k = i + 1; k < path->pins->size; k++) {
-                       p1 =            path->pins->data[k];
+               for (k = i + 1; k <= n; k++) {
+                       p1 = path->pins->data[k];
 
                        if (p1->lid == cp1->lid)
                                break;
                }
 
-               if (k >= path->pins->size) {
-                       scf_loge("\n");
-                       return -EINVAL;
-               }
+               if (k > n)
+                       continue;
 
                double r;
                double v;
@@ -83,7 +81,7 @@ static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double*
                        __ses_path_jr      (f, child);
                }
 
-               int ret = __ses_path_va(f, child, changed, ns, count);
+               int ret = __ses_path_va(f, child, 0, child->pins->size - 1, changed, ns, count);
                if (ret < 0)
                        return ret;
 
@@ -100,11 +98,11 @@ static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double*
                scf_loge("child: %d, c%ldp%ld-c%ldp%ld (c%ldp%ld-c%ldp%ld, n_diodes: %d), p->v: %lg, v: %lg, child->a0: %lg, child->a: %lg\n\n",
                                child->index, p0->cid, p0->id, p1->cid, p1->id, cp0->cid, cp0->id, cp1->cid, cp1->id, child->n_diodes, p0->v, v, child->a0, child->a);
 
-               n++;
+               n_childs++;
        }
 
        scf_logw("*****************\n");
-       return n;
+       return n_childs;
 }
 
 static void __ses_path_split_v(ScfEfunction* f, ses_path_t* path, int i0, int i, double a)
@@ -134,16 +132,17 @@ static void __ses_path_split_v(ScfEfunction* f, ses_path_t* path, int i0, int i,
        scf_logd("c%ldp%ld, c%ldp%ld, a: %lg, r: %lg, v: %lg, p0->v: %lg, p->v: %lg\n", p0->cid, p0->id, p->cid, p->id, a, r, v, p0->v, p->v);
 }
 
-double __ses_path_v_capacitor(ScfEfunction* f, ses_path_t* path)
+int __ses_path_capacitors(ScfEfunction* f, ses_path_t* path, int m, int n, double* cv)
 {
        ScfEcomponent* c;
        ScfEpin*       p;
 
        double v = 0;
+       int    k = 0;
        int    i;
 
-       for (i = 0; i < path->pins->size; i += 2) {
-               p  =        path->pins->data[i];
+       for (i = m; i <= n; i += 2) {
+               p  = path->pins->data[i];
 
                c  = f->components[p->cid];
 
@@ -151,24 +150,28 @@ double __ses_path_v_capacitor(ScfEfunction* f, ses_path_t* path)
                        int sign = p->id - !p->id;
 
                        v += c->v * sign;
+                       k++;
                }
        }
 
-       return v;
+       *cv = v;
+       return k;
 }
 
-int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, int64_t count)
+int __ses_path_va(ScfEfunction* f, ses_path_t* path, int m, int n, int* changed, int64_t ns, int64_t count)
 {
        if (!path)
                return -EINVAL;
 
-       if (path->pins->size < 2) {
+       if (path->pins->size < 2 || n - m < 1) {
                scf_loge("\n");
                return -EINVAL;
        }
 
        ses_path_t*    child;
        ScfEcomponent* c;
+       ScfEcomponent* B  = f->components[0];
+       ScfEpin*       Bn = B->pins[SCF_EDA_Battery_NEG];
        ScfEline*      el;
        ScfEpin*       p;
        ScfEpin*       p0;
@@ -180,8 +183,8 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
        int i;
        int j;
 
-       p0 = path->pins->data[0];
-       p1 = path->pins->data[path->pins->size - 1];
+       p0 = path->pins->data[m];
+       p1 = path->pins->data[n];
 
        el     = f->elines[p0->lid];
        p0->v  = el->v;
@@ -189,46 +192,64 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
        el     = f->elines[p1->lid];
        p1->v  = el->v;
 
+       double pr = 0;
        double cv = 0;
+       double a  = 0;
        double v  = p0->v - p1->v;
 
+       child = ses_path_find_child(path, m, n);
+
        if (path->n_capacitors > 0) {
-               cv = __ses_path_v_capacitor(f, path);
+               __ses_path_capacitors(f, path, m, n, &cv);
                v -= cv;
-               ses_ur_i(&path->a, NULL, v, 0, path->jpr, 0);
-       } else
-               ses_ur_i(&path->a, NULL, v, 0, path->pr, 0);
+               __ses_path_jpr(f, path, m, n, child, &pr);
+       } else {
+               __ses_path_pr(f, path, m, n, child, &pr);
+       }
+
+       ses_ur_i(&a, NULL, v, 0, pr, 0);
+
+       if (0 == m && path->pins->size - 1 == n)
+               path->a = a;
 
-       scf_logw("path: %d, c%ldp%ld-c%ldp%ld, p0->v: %lg, p1->v: %lg, v: %lg, cv: %lg, r: %lg, jr: %lg, a: %lg\n\n",
-                       path->index, p0->cid, p0->id, p1->cid, p1->id, p0->v, p1->v, v, cv, path->pr, path->jpr, path->a);
+       scf_logw("path: %d, c%ldp%ld-c%ldp%ld, p0->v: %lg, p1->v: %lg, v: %lg, cv: %lg, pr: %lg, path->pr: %lg, path->jpr: %lg, a: %lg\n\n",
+                       path->index, p0->cid, p0->id, p1->cid, p1->id, p0->v, p1->v, v, cv, pr, path->pr, path->jpr, a);
 
-       double a  = path->a;
-       double r  = 0;
-       double dv = 0;
+       double r   = 0;
+       double dv  = 0;
+       double dv0 = 0;
+       double dv1 = 0;
+       double dvc = 0;
 
-       int i0 = 0;
+       int i0 = m;
 
-       for (i = 0; i < path->pins->size; i++) {
-               p  =        path->pins->data[i];
+       for (i = m; i <= n; i++) {
+               p  = path->pins->data[i];
 
                scf_logd("c%ldp%ld, p->r: %lg, dr: %lg, sr: %lg, pr: %lg\n", p->cid, p->id, p->r, p->dr, p->sr, p->pr);
 
                __ses_path_split_v(f, path, i0, i, a);
 
+               p->v -= dv0 + dvc + dv1;
+               dv1   = 0;
+
+               double tmp = p->v;
+
                if (!(i & 0x1) && path->childs) {
-                       int ret = __ses_path_split_a(f, path, i, &a, changed, ns, count);
+                       int ret = __ses_path_split_a(f, path, i, n, &a, changed, ns, count);
                        if (ret < 0)
                                return ret;
 
                        if (ret > 0) {
                                p0 = p;
                                i0 = i;
+                               dv0 = p->v - tmp;
                                scf_logd("i: %d, p0: c%ldp%ld\n", i, p0->cid, p0->id);
                        }
                }
 
-               el     = f->elines[p->lid];
-               el->v  = p->v;
+               el    = f->elines[p->lid];
+               el->v = p->v;
 
                r += p->r + p->dr + p->jdr;
 
@@ -243,17 +264,26 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
                        if (SCF_EDA_Capacitor == c->type) {
                                int sign = !p->id - p->id;
 
-                               dv -= c->v * sign;
+                               cv  = c->v * sign;
+                               dv -= cv;
                                r  -= c->jdr;
                                ses_ur_i(&p->a, NULL, dv, 0, r, 0);
 
                                c->v   += p->a * ns / 1e3 / c->uf * sign;
                                c->jdr  = c->v / p->a * sign - c->r;
 
-                               if (p->a > 0)
+                               if (p->a > 0 || p->lid == Bn->lid) {
+                                       tmp   = p2->v;
                                        p2->v = p->v + c->v * sign;
-                               else
-                                       p->v  = p2->v - c->v * sign;
+
+                                       if (p0 == p2)
+                                               dv0 = p2->v - tmp;
+                               } else {
+                                       tmp  = p->v;
+                                       p->v = p2->v - c->v * sign;
+                                       dv1  = tmp - p->v;
+                               }
+                               dvc += cv;
 
                                scf_logi("c%ld->v: %lg, p->v: %lg, p2->v: %lg, dv: %lg, ja: %lg, ja0: %lg, ns: %ld, uf: %lg, c->jdr: %lg\n",
                                                c->id, c->v, p->v, p2->v, dv, p->a, c->a, ns, c->uf, c->jdr);
@@ -268,7 +298,20 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
                                el    = f->elines[p2->lid];
                                el->v = p2->v;
                                __ses_status_check_line(f, el, changed);
+
+                       } else if (p->a > a) {
+                               p->a = a;
+
+                               if (SCF_EDA_NPN == c->type) {
+                                       ses_ui_r(&p2->dr, NULL, dv, 0, a, 0);
+                                       p2->dr -= p2->r;
+
+                               } else if (SCF_EDA_Diode == c->type) {
+                                       ses_ui_r(&p->dr, NULL, dv, 0, a, 0);
+                                       p->dr -= p->r;
+                               }
                        }
+                       scf_logd("c%ld->v: %lg, p->v: %lg, dv: %lg, ja: %lg, r: %lg\n", c->id, c->v, p->v, dv, p->a, r);
 
                        p2->a = p->a;
 
@@ -279,13 +322,23 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
                                        cp0 = child->pins->data[0];
                                        cp1 = child->pins->data[child->pins->size - 1];
 
-                                       if (p->lid == cp1->lid)
-                                               a += child->a0;
+                                       if (p->lid != cp1->lid)
+                                               continue;
+
+                                       int k;
+                                       for (k = m; k <= n; k++) {
+                                               p2 = path->pins->data[k];
+
+                                               if (p2->lid == cp0->lid) {
+                                                       a += child->a0;
+                                                       break;
+                                               }
+                                       }
                                }
                        }
 
-                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, r: %lg, p->a: %lg, a: %lg, p->pr: %lg\n\n", path->index, i, p->cid, p->id,
-                                       p->v, dv, r, p->a, a, p->pr);
+                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, r: %lg, p->a: %lg, a: %lg, p->pr: %lg\n\n",
+                                       path->index, i, p->cid, p->id, p->v, dv, r, p->a, a, p->pr);
 
                        if (SCF_EDA_Diode == c->type) {
 
@@ -315,11 +368,13 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, i
                        r  = 0;
                } else {
                        dv = p->v;
-                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, a: %lg, p->pr: %lg\n", path->index, i, p->cid, p->id, p->v, dv, a, p->pr);
+                       scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, a: %lg, p->pr: %lg, dv0: %lg, dvc: %lg\n",
+                                       path->index, i, p->cid, p->id, p->v, dv, a, p->pr, dv0, dvc);
                }
        }
        printf("\n");
 
+       path->vflag = 1;
        return 0;
 }
 
@@ -359,7 +414,7 @@ static int _va_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ct
 
                __ses_path_jr(f, path);
 
-               int ret = __ses_path_va(f, path, &changed, ns, count);
+               int ret = __ses_path_va(f, path, 0, path->pins->size - 1, &changed, ns, count);
                if (ret < 0)
                        return ret;
        }
index 10111f494d152b97f08c1e85897a0dd538f2eb15..908ffb32e7ade4727857a3c79e4ce891d5dc0bee 100644 (file)
@@ -197,7 +197,7 @@ static int __ses_bridge_v(ScfEfunction* f, ses_path_t* bridge, double vmin, ses_
 
                __changed = 0;
 
-               int ret = __ses_path_va(f, bridge, &__changed, ns, count);
+               int ret = __ses_path_va(f, bridge, 0, bridge->pins->size - 1, &__changed, ns, count);
                if (ret < 0)
                        return ret;
 
@@ -244,17 +244,10 @@ static int __ses_bridge_r(ScfEfunction* f, ses_path_t* bridge, int vmin, ses_flo
        return 0;
 }
 
-static int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* changed, scf_vector_t* paths, int64_t ns, int64_t count)
+int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* changed, scf_vector_t* paths, int64_t ns, int64_t count)
 {
-       if (!bridge)
-               return -EINVAL;
-
-       if (bridge->pins->size < 2) {
-               scf_loge("\n");
-               return -EINVAL;
-       }
-
-       ses_flow_t*    flow;
+       ses_flow_t*    flow0;
+       ses_flow_t*    flow1;
        ses_path_t*    fpath;
        ses_info_t*    info;
 
@@ -277,23 +270,36 @@ static int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* change
 
        __ses_path_jr(f, bridge);
 
-       flow = ses_flow_alloc();
-       if (!flow)
+       flow0 = ses_flow_alloc();
+       if (!flow0)
                return -ENOMEM;
 
-       int ret = ses_paths_find_flow(flow, paths, p0, bridge);
+       int ret = ses_paths_find_flow(flow0, paths, p0, bridge);
        if (ret < 0) {
-               ses_flow_free(flow);
+               ses_flow_free(flow0);
                return ret;
        }
 
-       ses_flow_print(flow);
-       ses_flow_jr(flow, f);
+       flow1 = ses_flow_alloc();
+       if (!flow1) {
+               ses_flow_free(flow0);
+               return -ENOMEM;
+       }
+
+       ret = ses_paths_find_flow(flow1, paths, p1, bridge);
+       if (ret < 0) {
+               ses_flow_free(flow0);
+               ses_flow_free(flow1);
+               return ret;
+       }
 
-       fpath = flow->paths->data[flow->paths->size - 1];
+       ses_flow_print(flow0);
+       ses_flow_jr(flow0, f);
+       printf("\n");
 
-       scf_logw("flow vip: c%ldp%ld->a: %lg, v:%lg, vip_n: c%ldp%ld->a: %lg, v: %lg\n\n",
-                       flow->vip->cid, flow->vip->id, flow->vip->a, flow->vip->v, flow->vip_n->cid, flow->vip_n->id, flow->vip_n->a, flow->vip_n->v);
+       ses_flow_print(flow1);
+       ses_flow_jr(flow1, f);
+       printf("\n");
 
        double v;
        double jv;
@@ -317,9 +323,12 @@ static int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* change
                __ses_path_jr      (f, bridge);
        }
 
+       __ses_path_va_transistor(f, bridge);
+       __ses_path_jr           (f, bridge);
+
        int __changed = 0;
 
-       ret = __ses_path_va(f, bridge, &__changed, ns, count);
+       ret = __ses_path_va(f, bridge, 0, bridge->pins->size - 1, &__changed, ns, count);
        if (ret < 0)
                return ret;
 #if 0
index 6998d6742027df9232e107b0a899ecc6ac3c1631..6c76221a8ae30c9d3c0c041083bd1fbc97841401 100644 (file)
@@ -31,6 +31,55 @@ void __ses_status_check_line(ScfEfunction* f, ScfEline* el, int* changed)
        }
 }
 
+static void ses_va_bridge(
+               double  U0,  double  U1,  double  U2,  double  U3,  double  Vbc,
+               double  R0,  double  R1,  double  R2,  double  R3,  double  Rb,
+               double* pi0, double* pi1, double* pi2, double* pi3, double* pib,
+               double* pVb0, double* pVb1)
+{
+       scf_logw("R0: %lg, R1: %lg, R2: %lg, R3: %lg, Vbc: %lg, U0: %lg, U1: %lg, U2: %lg, U3: %lg\n", R0, R1, R2, R3, Vbc, U0, U1, U2, U3);
+
+       double i1 = (R0 * R3 * (U2 - U1 + Vbc) - R0 * R2 * (U1 - U3 - Vbc) + (R2 * R3 + R3 * Rb + R2 * Rb) * (U0 - U1))
+                     / ((R2 + R3) * (R0 * R1 + Rb * (R0 + R1)) + R2 * R3 * (R0 + R1));
+
+       double ib = (U0 - U1 - i1 * (R0 + R1)) / R0;
+       double i0 = i1 + ib;
+       double i3 = (R0 * (U1 - U3 - Vbc) - Rb * (U0 - U1) + i1 * (R0 * R1 + Rb * (R0 + R1))) / R0 / R3;
+       double i2 = i3 - ib;
+
+       double V0 = i0 * R0;
+       double V1 = i1 * R1;
+       double V2 = i2 * R2;
+       double V3 = i3 * R3;
+       double Vb = ib * Rb;
+
+       scf_logi("i0: %lg, i1: %lg, i2: %lg, i3: %lg, ib: %lg\n", i0, i1, i2, i3, ib);
+
+       double Vb0 = U1 + V1;
+       double Vb1 = U3 + V3;
+
+       if (pi0)
+               *pi0 = i0;
+
+       if (pi1)
+               *pi1 = i1;
+
+       if (pi2)
+               *pi2 = i2;
+
+       if (pi3)
+               *pi3 = i3;
+
+       if (pib)
+               *pib = ib;
+
+       if (pVb0)
+               *pVb0 = Vb0;
+
+       if (pVb1)
+               *pVb1 = Vb1;
+}
+
 static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_t* bridge, int* changed, int64_t ns, int64_t count)
 {
        ses_flow_t*    flow0;
@@ -38,15 +87,16 @@ static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_pat
        ses_path_t*    fpath;
 
        ScfEcomponent* B;
-       ScfEcomponent* c;
        ScfEline*      el;
        ScfEpin*       p0;
        ScfEpin*       p1;
+       ScfEpin*       fp0;
+       ScfEpin*       fp1;
        ScfEpin*       Bp;
        ScfEpin*       Bn;
 
-       int i;
-       int j;
+       if (bridge->vflag)
+               return 0;
 
        B  = f->components[0];
        Bp = B->pins[SCF_EDA_Battery_POS];
@@ -58,7 +108,7 @@ static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_pat
        if (p0->lid == Bp->lid && p1->lid == Bn->lid)
                return 0;
 
-       __ses_path_jr(f, bridge);
+       scf_loge("c%ldp%ld-c%ldp%ld-------------------------\n", p0->cid, p0->id, p1->cid, p1->id);
 
        flow0 = ses_flow_alloc();
        if (!flow0)
@@ -77,57 +127,177 @@ static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_pat
        }
 
        ret = ses_paths_find_flow(flow1, paths, p1, bridge);
-       if (ret < 0) {
-               ses_flow_free(flow0);
-               ses_flow_free(flow1);
-               return ret;
+       if (ret < 0)
+               goto error;
+
+       if (flow0->paths->size > 0) {
+               fpath = flow0->paths->data[flow0->paths->size - 1];
+
+               if (!fpath->vflag) {
+                       ret = __ses_path_va_capacitor(f, paths, fpath, changed, ns, count);
+                       if (ret < 0)
+                               goto error;
+               }
        }
 
-       ses_flow_print(flow0);
-       ses_flow_jr(flow0, f);
-       printf("\n");
+       if (flow1->paths->size > 0) {
+               fpath = flow1->paths->data[flow1->paths->size - 1];
 
-       ses_flow_print(flow1);
-       ses_flow_jr(flow1, f);
-       printf("\n");
+               if (!fpath->vflag) {
+                       ret = __ses_path_va_capacitor(f, paths, fpath, changed, ns, count);
+                       if (ret < 0)
+                               goto error;
+               }
+       }
 
-       double jr;
-       double jv;
+       double R;
        double cv;
        double ja;
 
+       __ses_path_jr(f, bridge);
+
        el    = f->elines[p0->lid];
        p0->v = el->v;
 
        el    = f->elines[p1->lid];
        p1->v = el->v;
 
-       cv = __ses_path_v_capacitor(f, bridge);
+       __ses_path_capacitors(f, bridge, 0, bridge->pins->size - 1, &cv);
 
        scf_logw("c%ldp%ld-c%ldp%ld, cv: %lg, p0->v: %lg, p1->v: %lg\n", p0->cid, p0->id, p1->cid, p1->id, cv, p0->v, p1->v);
 
        if (p0->v - p1->v > cv) {
 
-               jv = Bp->v - cv;
-               jr = flow0->pos_r + flow1->neg_r + bridge->jpr;
-               ja = jv / jr;
+               if (p0->lid == Bp->lid) {
+
+                       ret = ses_flow_find_pos(flow1, paths, f);
+                       if (ret < 0)
+                               goto error;
+
+                       ret = ses_flow_find_neg(flow1, paths, f);
+                       if (ret < 0)
+                               goto error;
+
+                       ses_flow_print(flow0);
+                       ses_flow_jr(flow0, f);
+                       printf("\n");
+
+                       ses_flow_print(flow1);
+                       ses_flow_jr(flow1, f);
+                       printf("\n");
+
+                       R     = bridge->jpr * flow1->pos_r / (bridge->jpr + flow1->pos_r);
+
+                       ja    = Bp->v / (R + flow1->neg_r);
+                       p0->v = Bp->v;
+                       p1->v = Bp->v - ja * R;
+
+               } else if (p1->lid == Bn->lid) {
+
+                       ret = ses_flow_find_pos(flow0, paths, f);
+                       if (ret < 0)
+                               goto error;
+
+                       ret = ses_flow_find_neg(flow0, paths, f);
+                       if (ret < 0)
+                               goto error;
+
+                       ses_flow_print(flow0);
+                       ses_flow_jr(flow0, f);
+                       printf("\n");
+
+                       ses_flow_print(flow1);
+                       ses_flow_jr(flow1, f);
+                       printf("\n");
+
+                       R     = bridge->jpr * flow0->neg_r / (bridge->jpr + flow0->neg_r);
+
+                       ja    = Bp->v / (R + flow0->pos_r);
+                       p0->v = Bp->v - ja * flow0->pos_r;
+                       p1->v = Bn->v;
+
+                       scf_logi("R: %lg, flow0->pos_r: %lg, flow0->neg_r: %lg\n", R, flow0->pos_r, flow0->neg_r);
+               } else {
+                       ses_flow_print(flow0);
+                       ses_flow_jr(flow0, f);
+                       printf("\n");
+
+                       ses_flow_print(flow1);
+                       ses_flow_jr(flow1, f);
+                       printf("\n");
+
+                       fpath = flow0->paths->data[flow0->paths->size - 1];
+                       fp0   = fpath->pins->data[0];
+                       fp1   = fpath->pins->data[fpath->pins->size - 1];
+
+                       double U0 = fp0->v;
+                       double U1 = fp1->v;
 
-               p0->v = Bp->v - ja * flow0->pos_r;
-               p1->v = Bn->v + ja * flow1->neg_r;
+                       fpath = flow1->paths->data[flow1->paths->size - 1];
+                       fp0   = fpath->pins->data[0];
+                       fp1   = fpath->pins->data[fpath->pins->size - 1];
 
-               scf_logi("c%ldp%ld-c%ldp%ld, cv: %lg, p0->v: %lg, p1->v: %lg, jr: %lg, jv: %lg, ja: %lg\n\n",
-                               p0->cid, p0->id, p1->cid, p1->id, cv, p0->v, p1->v, jr, jv, ja);
+                       double U2 = fp0->v;
+                       double U3 = fp1->v;
 
+                       ses_va_bridge(U0, U1, U2, U3, cv,
+                                       flow0->pos_r, flow0->neg_r, flow1->pos_r, flow1->neg_r, bridge->jpr,
+                                       NULL, NULL, NULL, NULL, &ja, &p0->v, &p1->v);
+               }
+
+               scf_logi("c%ldp%ld-c%ldp%ld, cv: %lg, p0->v: %lg, p1->v: %lg, ja: %lg\n\n",
+                               p0->cid, p0->id, p1->cid, p1->id, cv, p0->v, p1->v, ja);
        } else {
-               jv = Bp->v + cv;
-               jr = flow1->pos_r + flow0->neg_r + bridge->jpr;
-               ja = jv / jr;
+               assert(p0->lid != Bp->lid);
+
+               if (p1->lid == Bn->lid) {
+
+                       ret = ses_flow_find_neg(flow1, paths, f);
+                       if (ret < 0)
+                               goto error;
+
+                       ses_flow_print(flow0);
+                       ses_flow_jr(flow0, f);
+                       printf("\n");
+
+                       ses_flow_print(flow1);
+                       ses_flow_jr(flow1, f);
+                       printf("\n");
+
+                       R     = bridge->jpr + flow0->neg_r;
+                       ja    = (cv - p0->v) / R;
+                       p1->v = Bn->v;
+
+               } else {
+                       ses_flow_print(flow0);
+                       ses_flow_jr(flow0, f);
+                       printf("\n");
 
-               p1->v = Bp->v - ja * flow1->pos_r;
-               p0->v = Bn->v + ja * flow0->neg_r;
+                       ses_flow_print(flow1);
+                       ses_flow_jr(flow1, f);
+                       printf("\n");
 
-               scf_logi("c%ldp%ld-c%ldp%ld, cv: %lg, p0->v: %lg, p1->v: %lg, jr: %lg, jv: %lg, ja: %lg\n\n",
-                               p0->cid, p0->id, p1->cid, p1->id, cv, p0->v, p1->v, jr, jv, ja);
+                       fpath = flow1->paths->data[flow1->paths->size - 1];
+                       fp0   = fpath->pins->data[0];
+                       fp1   = fpath->pins->data[fpath->pins->size - 1];
+
+                       double U0 = fp0->v;
+                       double U1 = fp1->v;
+
+                       fpath = flow0->paths->data[flow0->paths->size - 1];
+                       fp0   = fpath->pins->data[0];
+                       fp1   = fpath->pins->data[fpath->pins->size - 1];
+
+                       double U2 = fp0->v;
+                       double U3 = fp1->v;
+
+                       ses_va_bridge(U0, U1, U2, U3, -cv,
+                                       flow1->pos_r, flow1->neg_r, flow0->pos_r, flow0->neg_r, bridge->jpr,
+                                       NULL, NULL, NULL, NULL, &ja, &p1->v, &p0->v);
+               }
+
+               scf_logi("c%ldp%ld-c%ldp%ld, cv: %lg, p0->v: %lg, p1->v: %lg, ja: %lg\n\n",
+                               p0->cid, p0->id, p1->cid, p1->id, cv, p0->v, p1->v, ja);
        }
 
        el    = f->elines[p0->lid];
@@ -136,15 +306,19 @@ static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_pat
        el    = f->elines[p1->lid];
        el->v = p1->v;
 
-       ret = __ses_path_va(f, bridge, changed, ns, count);
+       ret = __ses_path_va(f, bridge, 0, bridge->pins->size - 1, changed, ns, count);
        if (ret < 0) {
                scf_loge("\n");
-               return ret;
+               goto error;
        }
 
        __ses_status_check_line(f, f->elines[p0->lid], changed);
        __ses_status_check_line(f, f->elines[p1->lid], changed);
-       return 0;
+       ret = 0;
+error:
+       ses_flow_free(flow0);
+       ses_flow_free(flow1);
+       return ret;
 }
 
 static int ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_t* bridge, int* changed, int64_t ns, int64_t count)
@@ -165,8 +339,8 @@ static int ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_
        }
 
        if (bridge->bridges) {
-               for (j = 0; j < bridge->childs->size; j++) {
-                       child     = bridge->childs->data[j];
+               for (j = 0; j < bridge->bridges->size; j++) {
+                       child     = bridge->bridges->data[j];
 
                        ret = ses_path_va_capacitor(f, paths, child, changed, ns, count);
                        if (ret < 0)
index 3c56ba414a52e8a121cf8db1dc0af8dd1a60732b..400747f41898774286e2b8384f2bfcf69fa6f892 100644 (file)
@@ -171,9 +171,43 @@ void __ses_path_dr_reverse(ScfEfunction* f, ses_path_t* path, int i, int j, doub
        }
 }
 
+ses_path_t* ses_path_find_child(ses_path_t* path, int m, int n)
+{
+       ses_path_t* child;
+       ScfEpin*    cp0;
+       ScfEpin*    cp1;
+
+       if (path->childs) {
+               ScfEpin* p0;
+               ScfEpin* p1 = path->pins->data[n];
+
+               int i;
+               int j;
+
+               for (i    = 0; i < path->childs->size; i++) {
+                       child =        path->childs->data[i];
+
+                       cp0 = child->pins->data[0];
+                       cp1 = child->pins->data[child->pins->size - 1];
+
+                       if (cp1->lid != p1->lid)
+                               continue;
+
+                       for (j = m; j <= n; j++) {
+                               p0 = path->pins->data[j];
+
+                               if (cp0->lid == p0->lid)
+                                       return child;
+                       }
+               }
+       }
+       return NULL;
+}
+
 static void __ses_path_a_diode(ScfEfunction* f, ses_path_t* path, int k, double* a)
 {
        ses_info_t* info;
+       ses_path_t* child;
 
        ScfEpin*    p0 = path->pins->data[0];
        ScfEpin*    p1 = path->pins->data[path->pins->size - 1];
@@ -196,7 +230,9 @@ static void __ses_path_a_diode(ScfEfunction* f, ses_path_t* path, int k, double*
                v -= info->n_diodes * SCF_EDA_V_Diode_ON;
                v -= info->n_NPNs   * SCF_EDA_V_NPN_ON;
 
-               __ses_path_pr(f, path, i, info->i, NULL, &_r);
+               child = ses_path_find_child(path, i, info->i);
+
+               __ses_path_pr(f, path, i, info->i, child, &_r);
 
                r += _r;
 
@@ -205,14 +241,18 @@ static void __ses_path_a_diode(ScfEfunction* f, ses_path_t* path, int k, double*
                i = info->j;
        }
 
-       scf_logd("c%ldp%ld--c%ldp%ld, r: %lg, v: %lg\n", p0->cid, p0->id, p1->cid, p1->id, r, v);
+       j = path->pins->size - 1;
 
-       if (i  < path->pins->size - 1) {
+       if (i  < j) {
                pi = path->pins->data[i];
+               pj = path->pins->data[j];
 
-               __ses_path_pr(f, path, i, path->pins->size - 1, NULL, &_r);
+               child = ses_path_find_child(path, i, j);
+
+               __ses_path_pr(f, path, i, j, child, &_r);
 
                r += _r;
+               scf_logd("c%ldp%ld--c%ldp%ld, r: %lg, v: %lg, _r: %lg\n", pi->cid, pi->id, pj->cid, pj->id, r, v, _r);
        }
 
        ses_ur_i(a, NULL, v, 0, r, 0);
index 2ed48dc1788e68e5c200d9ffc64adbfae5d7fd80..3c0a08c7a2bbe65e0da6eca00be5e694c259ede6 100644 (file)
@@ -102,7 +102,7 @@ _changed:
        return 1;
 }
 
-static int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path)
+int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path)
 {
        ses_path_t*    parent = path->parent;
        ses_path_t*    child;
@@ -114,6 +114,7 @@ static int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path)
 
        ScfEpin*       p;
        ScfEpin*       pc;
+       ScfEpin*       pb;
 
        int i;
        int j = path->pins->size - 1;
@@ -166,7 +167,8 @@ static int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path)
                if (!pc->aconst)
                        break;
 
-               pc->a = pc->hfe * c->pins[SCF_EDA_NPN_B]->a;
+               pb    = c->pins[SCF_EDA_NPN_B];
+               pc->a = pc->hfe * pb->a;
 
                __ses_path_pr(f, path, 0, i, NULL, &pr);
 
@@ -174,6 +176,9 @@ static int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path)
 
                pc->v = p0->v - v;
 
+               scf_logi("i: %d, c%ldp%ld--c%ldp%ld, v: %lg, pc->v: %lg, pc->a: %lg, pr: %lg, pc->pr: %lg, pb c%ldp%ld->a: %lg\n",
+                               i, p0->cid, p0->id, pc->cid, pc->id, v, pc->v, pc->a, pr, pc->pr, pb->cid, pb->id, pb->a);
+
                if (pc->v < pj->v) {
                        v     = p0->v - pj->v;
 
index c993ab6b0c63c58083889a3a07b792f9aa135f67..85b828d46597efd2c9c497ce09bc09c1128c837d 100644 (file)
@@ -56,20 +56,85 @@ int ses_paths_find_flow(ses_flow_t* flow, scf_vector_t* paths, ScfEpin* vip, ses
                        }
                }
 
-               if (!path->childs)
-                       continue;
+               if (path->childs) {
+                       int ret = ses_paths_find_flow(flow, path->childs, vip, bridge);
+                       if (ret < 0)
+                               return ret;
+
+                       if (1 == ret) {
+                               if (scf_vector_add(flow->paths, path) < 0)
+                                       return -ENOMEM;
+                               return 1;
+                       }
+               }
+
+               if (path->bridges) {
+                       int ret = ses_paths_find_flow(flow, path->bridges, vip, bridge);
+                       if (ret < 0)
+                               return ret;
+
+                       if (1 == ret) {
+                               if (scf_vector_add(flow->paths, path) < 0)
+                                       return -ENOMEM;
+                               return 1;
+                       }
+               }
+       }
 
-               int ret = ses_paths_find_flow(flow, path->childs, vip, bridge);
+       return 0;
+}
+
+int ses_flow_find_neg(ses_flow_t* flow, scf_vector_t* paths, ScfEfunction* f)
+{
+       if (flow->paths->size <= 0)
+               return 0;
+
+       ses_path_t*    path = flow->paths->data[flow->paths->size - 1];
+       ScfEpin*       vp   = flow->vip;
+       ScfEpin*       vn   = flow->vip_n;
+       ScfEpin*       p    = path->pins->data[path->pins->size - 1];
+
+       ScfEcomponent* B    = f->components[0];
+       ScfEpin*       Bn   = B->pins[SCF_EDA_Battery_NEG];
+
+       while (p->lid != Bn->lid) {
+               int ret = ses_paths_find_flow(flow, paths, p, path);
                if (ret < 0)
                        return ret;
 
-               if (1 == ret) {
-                       if (scf_vector_add(flow->paths, path) < 0)
-                               return -1;
-                       return 1;
-               }
+               path = flow->paths->data[flow->paths->size - 1];
+               p    = path->pins ->data[path->pins->size - 1];
        }
 
+       flow->vip   = vp;
+       flow->vip_n = vn;
+       return 0;
+}
+
+int ses_flow_find_pos(ses_flow_t* flow, scf_vector_t* paths, ScfEfunction* f)
+{
+       if (flow->paths->size <= 0)
+               return 0;
+
+       ses_path_t*    path = flow->paths->data[flow->paths->size - 1];
+       ScfEpin*       vp   = flow->vip;
+       ScfEpin*       vn   = flow->vip_n;
+       ScfEpin*       p    = path->pins->data[0];
+
+       ScfEcomponent* B    = f->components[0];
+       ScfEpin*       Bp   = B->pins[SCF_EDA_Battery_POS];
+
+       while (p->lid != Bp->lid) {
+               int ret = ses_paths_find_flow(flow, paths, p, path);
+               if (ret < 0)
+                       return ret;
+
+               path = flow->paths->data[flow->paths->size - 1];
+               p    = path->pins ->data[0];
+       }
+
+       flow->vip   = vp;
+       flow->vip_n = vn;
        return 0;
 }
 
@@ -196,6 +261,7 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
                return;
 
        ses_path_t*    path;
+       ses_path_t*    child;
        ScfEcomponent* c;
        ScfEpin*       p;
        ScfEpin*       p0;
@@ -241,13 +307,17 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
        for (i   = 0; i < flow->paths->size; i++) {
                path =        flow->paths->data[i];
 
+               int j0;
+
                p0 = NULL;
                for (j = 0; j < path->pins->size; j++) {
                        p  =        path->pins->data[j];
 
                        if (!p0) {
-                               if (p->lid == vip->lid)
+                               if (p->lid == vip->lid) {
                                        p0 = p;
+                                       j0 = j;
+                               }
                                continue;
                        }
 
@@ -271,33 +341,51 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
                                scf_logd("flow->neg_r: %lg, c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
                                                flow->neg_r, p->cid, p->id, p->sr, p0->cid, p0->id, p0->pr);
 
-                               if (j + 1 < path->pins->size)
+                               if (j + 1 < path->pins->size) {
                                        p0    = path->pins->data[j + 1];
-                               else
+                                       j0    = j + 1;
+                               } else {
                                        p0    = path->pins->data[j];
+                                       j0    = j;
+                               }
 
                        } else if (p->sr != p->pr) {
 
-                               flow->neg_r += p->sr - p0->pr;
+                               child = ses_path_find_child(path, j0, j);
+                               if (child)
+                                       flow->neg_r += child->parent_pr - p0->pr;
+                               else
+                                       flow->neg_r += p->sr - p0->pr;
 
-                               scf_logd("flow->neg_r: %lg, c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
-                                               flow->neg_r, p->cid, p->id, p->sr, p0->cid, p0->id, p0->pr);
+                               scf_logd("flow->neg_r: %lg, c%ldp%ld->sr: %lg, p->pr: %lg, p0 c%ldp%ld->pr: %lg\n",
+                                               flow->neg_r, p->cid, p->id, p->sr, p->pr, p0->cid, p0->id, p0->pr);
                                p0 = p;
+                               j0 = j;
                        }
                }
 
-               assert(p0);
+               if (p0) {
+                       vip = path->pins->data[j - 1];
+                       c   = f->components[vip->cid];
 
-               vip = path->pins->data[j - 1];
+                       if (vip != p0) {
+                               child = ses_path_find_child(path, j0, j - 1);
+                               if (child)
+                                       flow->neg_r += child->parent_pr - p0->pr;
+                               else
+                                       flow->neg_r += vip->sr - p0->pr;
+                       }
 
-               if (vip != p0) {
-                       flow->neg_r += vip->sr - p0->pr;
                        scf_logd("flow->neg_r: %lg, vip c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
                                        flow->neg_r, vip->cid, vip->id, vip->sr, p0->cid, p0->id, p0->pr);
+
+                       if (SCF_EDA_NPN == c->type && SCF_EDA_NPN_E == vip->id) {
+                               vip->pr  = path->parent_pr;
+                               vip->jpr = path->parent_jpr;
+                       }
                }
 
-               scf_logd("flow->neg_r: %lg, vip c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
-                               flow->neg_r, vip->cid, vip->id, vip->sr, p0->cid, p0->id, p0->pr);
+               scf_logd("flow->neg_r: %lg, vip c%ldp%ld->sr: %lg\n", flow->neg_r, vip->cid, vip->id, vip->sr);
        }
 
        scf_loge("flow pos_r: %lg, neg_r: %lg, vip: c%ldp%ld, pos_diodes: %d, pos_NPNs: %d, neg_diodes: %d, neg_NPNs: %d\n",
@@ -316,20 +404,27 @@ void ses_flow_print(ses_flow_t* flow)
        int i;
        int j;
 
-       for (i   = 0; i < flow->paths->size; i++) {
-               path =        flow->paths->data[i];
+       for (i = flow->paths->size - 1; i >= 0; i--) {
+
+               if (i > 0) {
+                       path = flow->paths->data[i - 1];
+                       vip  = path->pins->data[0];
+               } else
+                       vip  = flow->vip;
+
+               path = flow->paths->data[i];
 
                for (j = 0; j < path->pins->size; j++) {
                        p  =        path->pins->data[j];
 
                        printf("c%ldp%ld ", p->cid, p->id);
 
-                       if (p->lid == vip->lid) {
-                               vip = path->pins->data[0];
+                       if (p->lid == vip->lid)
                                break;
-                       }
                }
-               printf(", ");
+
+               if (i > 0)
+                       printf(", ");
        }
 
        printf(";\n");
@@ -353,7 +448,8 @@ void ses_flow_print(ses_flow_t* flow)
                        printf("c%ldp%ld ", p->cid, p->id);
                }
 
-               printf(", ");
+               if (flag)
+                       printf(", ");
 
                vip = path->pins->data[j - 1];
        }
@@ -671,3 +767,31 @@ void ses_ctx_free(ses_ctx_t* ctx)
                free(ctx);
        }
 }
+
+void __ses_pn_dr(ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe)
+{
+       double v = pb->v - pe->v;
+       double r;
+
+       if (v >= SCF_EDA_V_Diode_ON) {
+
+               ses_ui_r(&r, NULL, v, 0, pb->a, 0);
+               pe->dr = r - pe->r;
+
+       } else if (v > SCF_EDA_V_Diode_OFF)
+               pe->dr = pb->r * (SCF_EDA_V_Diode_ON - SCF_EDA_V_Diode_OFF) / (v - SCF_EDA_V_Diode_OFF + 0.001);
+}
+
+void __ses_npn_dr(ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe)
+{
+       double v = pb->v - pe->v;
+       double r;
+
+       if (v >= SCF_EDA_V_NPN_ON) {
+
+               ses_ui_r(&r, NULL, v, 0, pb->a, 0);
+               pb->dr = r - pb->r;
+
+       } else if (v > SCF_EDA_V_NPN_OFF)
+               pb->dr = pb->r * (SCF_EDA_V_NPN_ON - SCF_EDA_V_NPN_OFF) / (v - SCF_EDA_V_NPN_OFF + 0.001);
+}
diff --git a/test/bridge_algorithm.c b/test/bridge_algorithm.c
new file mode 100644 (file)
index 0000000..c8532e4
--- /dev/null
@@ -0,0 +1,92 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<math.h>
+#include<complex.h>
+
+double V   = 6;
+double R0  = 7000;
+double R1  = 3000;
+double R2  = 9000;
+double R3  = 1000;
+
+double Rb  = 100;
+double Vbc = 0.05;
+
+void bridge()
+{
+       double i1  = (V  * (R2 * (R3 + Rb) + R3 * (R0 + Rb)) + Vbc * R0 * (R2 + R3))
+                      /  (R0 * R1 * (R2 + R3) + (R0 + R1) * (R2 * Rb + R2 * R3 + R3 * Rb));
+
+       double ib = (V - i1 * (R0 + R1)) / R0;
+       double i0 = i1 + ib;
+       double i3 = (i1 * (R0 * R1 + Rb * (R0 + R1)) - Vbc * R0 - V * Rb) / R0 / R3;
+       double i2 = i3 - ib;
+       double i3_ = (V + ib * R2) / (R2 + R3);
+
+       double V0 = i0 * R0;
+       double V1 = i1 * R1;
+       double V2 = i2 * R2;
+       double V3 = i3 * R3;
+       double Vb = ib * Rb;
+
+       printf("R0: %lg, i0: %lg, V0: %lg\n", R0, i0, V0);
+       printf("R1: %lg, i1: %lg, V1: %lg\n", R1, i1, V1);
+       printf("R2: %lg, i2: %lg, V2: %lg\n", R2, i2, V2);
+       printf("R3: %lg, i3: %lg, V3: %lg, i3_: %lg\n", R3, i3, V3, i3_);
+       printf("Rb: %lg, ib: %lg, Vb: %lg, Vbc: %lg\n", Rb, ib, Vb, Vbc);
+
+       printf("V0 + V1: %lg\n", V0 + V1);
+       printf("V2 + V3: %lg\n", V2 + V3);
+       printf("i1 + ib: %lg, i0: %lg\n", i1 + ib, i0);
+       printf("i2 + ib: %lg, i3: %lg\n", i2 + ib, i3);
+
+       printf("Vbc + Vb + V3: %lg, V1: %lg\n", Vbc + Vb + V3, V1);
+       printf("Vbc + Vb + V0: %lg, V2: %lg\n", Vbc + Vb + V0, V2);
+}
+
+double U0 = 6;
+double U1 = 0;
+double U2 = 6;
+double U3 = 0;
+
+void bridge2()
+{
+       double i1 = (R0 * R3 * (U2 - U1 + Vbc) - R0 * R2 * (U1 - U3 - Vbc) + (R2 * R3 + R3 * Rb + R2 * Rb) * (U0 - U1))
+                     / ((R2 + R3) * (R0 * R1 + Rb * (R0 + R1)) + R2 * R3 * (R0 + R1));
+
+       double ib = (U0 - U1 - i1 * (R0 + R1)) / R0;
+       double i0 = i1 + ib;
+       double i3 = (R0 * (U1 - U3 - Vbc) - Rb * (U0 - U1) + i1 * (R0 * R1 + Rb * (R0 + R1))) / R0 / R3;
+       double i2 = i3 - ib;
+       double i3_ = (U2 - U3 - i2 * R2) / R3;
+
+       double V0 = i0 * R0;
+       double V1 = i1 * R1;
+       double V2 = i2 * R2;
+       double V3 = i3 * R3;
+       double Vb = ib * Rb;
+
+       printf("R0: %lg, i0: %lg, V0: %lg\n", R0, i0, V0);
+       printf("R1: %lg, i1: %lg, V1: %lg\n", R1, i1, V1);
+       printf("R2: %lg, i2: %lg, V2: %lg\n", R2, i2, V2);
+       printf("R3: %lg, i3: %lg, V3: %lg, i3_: %lg\n", R3, i3, V3, i3_);
+       printf("Rb: %lg, ib: %lg, Vb: %lg, Vbc: %lg\n", Rb, ib, Vb, Vbc);
+
+       printf("V0 + V1: %lg, U0 - U1: %lg\n", V0 + V1, U0 - U1);
+       printf("V2 + V3: %lg, U2 - U3: %lg\n", V2 + V3, U2 - U3);
+
+       printf("i1 + ib: %lg, i0: %lg\n", i1 + ib, i0);
+       printf("i2 + ib: %lg, i3: %lg\n", i2 + ib, i3);
+
+       printf("Vbc + Vb + V3: %lg, V1: %lg\n", Vbc + Vb + V3, V1);
+       printf("Vbc + Vb + V0: %lg, V2: %lg\n", Vbc + Vb + V0, V2);
+}
+
+int main()
+{
+       bridge();
+       printf("---------------\n\n");
+
+       bridge2();
+       return 0;
+}
index 5361aeffdd915195e73158e068af85dfae2aee6a..1afc2b5b14e80c57abfad581dd86bc5f57a7ffa5 100644 (file)
@@ -70,12 +70,13 @@ int main(int argc, char* argv[])
        EDA_PIN_ADD_PIN(R2, 0,                    B,  SCF_EDA_Battery_NEG);
 
        T0->pins[SCF_EDA_NPN_C]->flags |= SCF_EDA_PIN_OUT;
+       T0->pins[SCF_EDA_NPN_C]->hfe    = 50;
 
-       R4->r  = 1000 * 47;
-       R5->r  = 1000 * 27;
-       R3->r  = 1000 * 10;
-       R2->r  = 1000 * 10;
        R1->r  = 1000 * 10;
+       R2->r  = 1000 * 10;
+       R3->r  = 1000 * 10;
+       R4->r  = 1000 * 10;
+       R5->r  = 1000;
        R0->r  = 1000;
        C0->uf = 10;
        C1->uf = 0.01;