update examples & add arg 'int64_t count' in __ses_step_va()
authoryu.dongliang <18588496441@163.com>
Sun, 21 Apr 2024 12:03:57 +0000 (20:03 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 21 Apr 2024 12:03:57 +0000 (20:03 +0800)
13 files changed:
examples/add.pack
examples/add2.pack
examples/and.pack
examples/or.pack
examples/oscillator.pack
main.c
scf_eda_pack.h
ses_core.h
ses_step_simplify.c
ses_step_va.c
ses_step_va_bridge.c
ses_step_va_capacitor.c
ses_utils.c

index 9f8930b4211a3189051de6775be79e9181b0d5d9..846a7558456fc4bbbdd32598a62ecc5dd10089bf 100644 (file)
Binary files a/examples/add.pack and b/examples/add.pack differ
index 096cc69afd375d2384b0a7b41e019a3aed70b72d..955d1a54f9e8cd99913bca1e3b00eccdcc7b115a 100644 (file)
Binary files a/examples/add2.pack and b/examples/add2.pack differ
index dc6f0de9942c1b269e6d62c76545ada35288d9b6..2dca83ec802ddbc14944a90ab52d803d72341d43 100644 (file)
Binary files a/examples/and.pack and b/examples/and.pack differ
index 946a87d692b1155ab1e17311d09ba1aeb7b84410..fd4867bba3222e869345abf53ea0ed00af5febf9 100644 (file)
Binary files a/examples/or.pack and b/examples/or.pack differ
index 42bf1f11a03c49879ef3cc633fcd0390b9631c10..6346f89de5327a9bc2e446f9ab2c6dc84b01c98a 100644 (file)
Binary files a/examples/oscillator.pack and b/examples/oscillator.pack differ
diff --git a/main.c b/main.c
index c608d2a58d1d8c028e1c516a94cfb89550c54bf3..db83a15a252cb8cd7161af4d902b3e525c1d5cb9 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, 1);
+               ses_steps_analyse(f, 1000, 4);
        }
 #endif
 
index c5ae79c5d71c4d9728ff95c6245efd37319fa9ab..2cf8303057c0e89cde1d11771e952ad9d2d5b736 100644 (file)
@@ -240,6 +240,7 @@ struct scf_ecomponent_s
        SCF_PACK_DEF_VAR(double, uf);
        SCF_PACK_DEF_VAR(double, uh);
 
+       SCF_PACK_DEF_VAR(int64_t, count);
        SCF_PACK_DEF_VAR(int64_t, color);
        SCF_PACK_DEF_VAR(int, status);
        SCF_PACK_DEF_VAR(int, x);
@@ -266,6 +267,7 @@ SCF_PACK_INFO_VAR(ScfEcomponent, r),
 SCF_PACK_INFO_VAR(ScfEcomponent, uf),
 SCF_PACK_INFO_VAR(ScfEcomponent, uh),
 
+SCF_PACK_INFO_VAR(ScfEcomponent, count),
 SCF_PACK_INFO_VAR(ScfEcomponent, color),
 SCF_PACK_INFO_VAR(ScfEcomponent, status),
 SCF_PACK_INFO_VAR(ScfEcomponent, x),
index d5b35aac6d14cbcc8d6455cad4ebb15cd7e60aeb..e490b4b8e3f5019bc54e487ea64325817c13faf5 100644 (file)
@@ -20,6 +20,12 @@ struct ses_flow_s
        int            pos_pins;
        int            neg_pins;
 
+       int            pos_diodes;
+       int            pos_NPNs;
+
+       int            neg_diodes;
+       int            neg_NPNs;
+
        double         pos_r;
        double         neg_r;
 
@@ -97,6 +103,9 @@ void        ses_path_free (ses_path_t* path);
 void        ses_path_print(ses_path_t* path);
 int         ses_path_add  (ses_path_t* path, ses_path_t* child);
 
+ses_path_t* ses_path_save (ses_path_t* src);
+int         ses_path_load (ses_path_t* dst, ses_path_t* src);
+
 ses_flow_t* ses_flow_alloc();
 void        ses_flow_free (ses_flow_t* flow);
 void        ses_flow_print(ses_flow_t* flow);
@@ -112,7 +121,8 @@ void        ses_ctx_free (ses_ctx_t* ctx);
 int ses_layout_board (ScfEboard*    b);
 int ses_steps_analyse(ScfEfunction* f, int64_t ns, int64_t count);
 
-int ses_paths_find_flow(ses_flow_t* flow, scf_vector_t* paths, ScfEpin* vip, ses_path_t* bridge);
+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_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);
@@ -127,7 +137,7 @@ void __ses_path_pr (ScfEfunction* f, ses_path_t* path, int i, int j, ses_path_t*
 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);
+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_pos(ScfEfunction* f, ScfEline*   el);
 int  __ses_path_neg(ScfEfunction* f, ScfEline*   el);
index dfa7da68b9c8c7261a201efdb72d659eb607377c..92448bf0366cdc1380c11d20fbf4365639a4476f 100644 (file)
@@ -264,10 +264,6 @@ static int _simplify_draw(ScfEfunction* f, uint32_t bx, uint32_t by, uint32_t bw
        ScfEcomponent*   B;
        ScfEcomponent*   c;
        ScfEline*        el;
-       ScfEpin*         p;
-       ScfEpin*         pb;
-       ScfEpin*         pc;
-       ScfEpin*         pe;
        ScfLine*         l;
 
        cairo_surface_t* surface;
@@ -282,9 +278,9 @@ static int _simplify_draw(ScfEfunction* f, uint32_t bx, uint32_t by, uint32_t bw
        cairo_fill(cr);
        cairo_stroke(cr);
 
-       size_t i;
-       size_t j;
-       size_t k;
+       long i;
+       long j;
+       long k;
 
        B = f->components[0];
 
@@ -351,7 +347,23 @@ static int _simplify_draw(ScfEfunction* f, uint32_t bx, uint32_t by, uint32_t bw
 
                                cairo_set_font_size(cr, 20);
 
-                               cairo_move_to  (cr, l->x0 + 12, l->y0 + 24);
+                               int cx = INT_MAX;
+                               int cy = l->y0;
+
+                               for (i = 0; i < el->n_pins; i += 2) {
+                                       c = f->components[el->pins[i]];
+
+                                       if (c->x > l->x0 && c->x < cx) {
+                                               cx = c->x;
+                                               cy = c->y;
+                                       }
+                               }
+
+                               if (cy > l->y0)
+                                       cairo_move_to(cr, l->x0 + 12, l->y0 - 8);
+                               else
+                                       cairo_move_to(cr, l->x0 + 12, l->y0 + 24);
+
                                cairo_show_text(cr, text);
                                cairo_stroke(cr);
                        }
index e90a53224e12789088998fcae32cd008880547ba..cf08c85c0adf9bb8bdf76f9320aff3f64547ed2d 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)
+static int __ses_path_split_a(ScfEfunction* f, ses_path_t* path, int i, double* a, int* changed, int64_t ns, int64_t count)
 {
        ses_path_t*    child;
 
@@ -83,7 +83,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);
+               int ret = __ses_path_va(f, child, changed, ns, count);
                if (ret < 0)
                        return ret;
 
@@ -157,7 +157,7 @@ double __ses_path_v_capacitor(ScfEfunction* f, ses_path_t* path)
        return v;
 }
 
-int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns)
+int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns, int64_t count)
 {
        if (!path)
                return -EINVAL;
@@ -216,7 +216,7 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns)
                __ses_path_split_v(f, path, i0, i, a);
 
                if (!(i & 0x1) && path->childs) {
-                       int ret = __ses_path_split_a(f, path, i, &a, changed, ns);
+                       int ret = __ses_path_split_a(f, path, i, &a, changed, ns, count);
                        if (ret < 0)
                                return ret;
 
@@ -255,8 +255,11 @@ int __ses_path_va(ScfEfunction* f, ses_path_t* path, int* changed, int64_t ns)
                                else
                                        p->v  = p2->v - c->v * sign;
 
-                               scf_logi("c%ld->v: %lg, p->v: %lg, p2->v: %lg, dv: %lg, ja: %lg, ns: %ld, uf: %lg, c->jdr: %lg\n",
-                                               c->id, c->v, p->v, p2->v, dv, p->a, ns, c->uf, c->jdr);
+                               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);
+
+                               c->a     = p->a * sign;
+                               c->count = count;
 
                                el    = f->elines[p->lid];
                                el->v = p->v;
@@ -356,7 +359,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);
+               int ret = __ses_path_va(f, path, &changed, ns, count);
                if (ret < 0)
                        return ret;
        }
index d60f34ac9cca7f2dc5d015691e79d77405a1c608..10111f494d152b97f08c1e85897a0dd538f2eb15 100644 (file)
@@ -164,7 +164,7 @@ int __ses_flow_v_neg(ScfEfunction* f, ses_flow_t* flow, double dv_vip, int* chan
        return 0;
 }
 
-static int __ses_bridge_v(ScfEfunction* f, ses_path_t* bridge, double vmin, ses_flow_t* flow, int64_t ns)
+static int __ses_bridge_v(ScfEfunction* f, ses_path_t* bridge, double vmin, ses_flow_t* flow, int64_t ns, int64_t count)
 {
        ScfEline* el;
        ScfEpin*  p0 = bridge->pins->data[0];
@@ -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);
+               int ret = __ses_path_va(f, bridge, &__changed, ns, count);
                if (ret < 0)
                        return ret;
 
@@ -244,7 +244,7 @@ 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)
+static 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;
@@ -319,7 +319,7 @@ static int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* change
 
        int __changed = 0;
 
-       ret = __ses_path_va(f, bridge, &__changed, ns);
+       ret = __ses_path_va(f, bridge, &__changed, ns, count);
        if (ret < 0)
                return ret;
 #if 0
@@ -347,7 +347,7 @@ static int __ses_path_va_bridge(ScfEfunction* f, ses_path_t* bridge, int* change
        return 0;
 }
 
-static int ses_path_va_bridge(ScfEfunction* f, ses_path_t* path, int* changed, scf_vector_t* paths, int64_t ns)
+static int ses_path_va_bridge(ScfEfunction* f, ses_path_t* path, int* changed, scf_vector_t* paths, int64_t ns, int64_t count)
 {
        ses_path_t* child;
 
@@ -359,7 +359,7 @@ static int ses_path_va_bridge(ScfEfunction* f, ses_path_t* path, int* changed, s
 
        if (0 == path->n_capacitors) {
 
-               ret = __ses_path_va_bridge(f, path, changed, paths, ns);
+               ret = __ses_path_va_bridge(f, path, changed, paths, ns, count);
                if (ret < 0)
                        return ret;
        }
@@ -378,7 +378,7 @@ static int ses_path_va_bridge(ScfEfunction* f, ses_path_t* path, int* changed, s
                for (j = 0; j < path->bridges->size; j++) {
                        child     = path->bridges->data[j];
 
-                       ret = ses_path_va_bridge(f, child, changed, vec, ns);
+                       ret = ses_path_va_bridge(f, child, changed, vec, ns, count);
                        if (ret < 0) {
                                scf_vector_free(vec);
                                return ret;
@@ -402,7 +402,7 @@ static int _va_bridge_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ct
        for (i = 0; i < ctx->paths->size; i++) {
                path      = ctx->paths->data[i];
 
-               int ret = ses_path_va_bridge(f, path, &changed, ctx->paths, ns);
+               int ret = ses_path_va_bridge(f, path, &changed, ctx->paths, ns, count);
                if (ret < 0)
                        return ret;
        }
index 2855a43a3a0ec439715c01d227f722620c58b2e4..48e8fb8bbdbb0c0d9dc3c03d44e265fb083c82ea 100644 (file)
@@ -31,7 +31,7 @@ void __ses_status_check_line(ScfEfunction* f, ScfEline* el, int* changed)
        }
 }
 
-static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_t* bridge, int* changed, int64_t ns)
+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;
        ses_flow_t*    flow1;
@@ -131,7 +131,7 @@ 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);
+       ret = __ses_path_va(f, bridge, changed, ns, count);
        if (ret < 0) {
                scf_loge("\n");
                return ret;
@@ -142,7 +142,7 @@ static int __ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_pat
        return 0;
 }
 
-static int ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_t* bridge, int* changed, int64_t ns)
+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_path_t* child;
 
@@ -156,26 +156,16 @@ static int ses_path_va_capacitor(ScfEfunction* f, scf_vector_t* paths, ses_path_
 
                __ses_path_jr(f, bridge);
 
-               ret = __ses_path_va_capacitor(f, paths, bridge, changed, ns);
+               ret = __ses_path_va_capacitor(f, paths, bridge, changed, ns, count);
                if (ret < 0)
                        return ret;
        }
-#if 0
-       if (bridge->childs) {
-               for (j = 0; j < bridge->childs->size; j++) {
-                       child     = bridge->childs->data[j];
 
-                       ret = ses_path_va_capacitor(f, paths, child, changed, ns);
-                       if (ret < 0)
-                               return ret;
-               }
-       }
-#endif
        if (bridge->bridges) {
                for (j = 0; j < bridge->childs->size; j++) {
                        child     = bridge->childs->data[j];
 
-                       ret = ses_path_va_capacitor(f, paths, child, changed, ns);
+                       ret = ses_path_va_capacitor(f, paths, child, changed, ns, count);
                        if (ret < 0)
                                return ret;
                }
@@ -197,7 +187,7 @@ static int _va_capacitor_handler(ScfEfunction* f, int64_t ns, int64_t count, ses
 
                int changed = 0;
 
-               int ret = ses_path_va_capacitor(f, ctx->paths, path, &changed, ns);
+               int ret = ses_path_va_capacitor(f, ctx->paths, path, &changed, ns, count);
                if (ret < 0)
                        return ret;
 
index a64b5f8e0f037115bbd865815cae196290d7fbc4..18df7e463425fd79293aee83ca0ba73d93405325 100644 (file)
@@ -73,6 +73,114 @@ int ses_paths_find_flow(ses_flow_t* flow, scf_vector_t* paths, ScfEpin* vip, ses
        return 0;
 }
 
+int ses_flows_make_path(ses_path_t** ppath, ses_flow_t* pos, ses_flow_t* neg, ses_path_t* bridge, int reverse)
+{
+       if (!pos || !neg || !bridge)
+               return -EINVAL;
+
+       if (!pos->paths || !pos->vip || !neg->paths || !neg->vip_n)
+               return -EINVAL;
+
+       *ppath = ses_path_alloc();
+       if (!*ppath)
+               return -ENOMEM;
+
+       ses_path_t*    path;
+       ScfEcomponent* c;
+       ScfEpin*       p;
+       ScfEpin*       p0;
+       ScfEpin*       vip = pos->vip;
+
+       int i;
+       int j;
+
+       for (i   = 0; i < pos->paths->size; i++) {
+               path =        pos->paths->data[i];
+
+               for (j = 0; j < path->pins->size; j++) {
+                       p  =        path->pins->data[j];
+
+                       if (p->lid == vip->lid) {
+                               vip = path->pins->data[0];
+                               break;
+                       }
+               }
+
+               assert(j < path->pins->size);
+
+               for ( ; j >= 0; j--) {
+                       p = path->pins->data[j];
+
+                       if (scf_vector_add((*ppath)->pins, p) < 0) {
+                               ses_path_free(*ppath);
+                               *ppath = NULL;
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       // positive branch is reversed, make it normal
+       i = 0;
+       j = (*ppath)->pins->size - 1;
+
+       while (i < j) {
+               SCF_XCHG((*ppath)->pins->data[i], (*ppath)->pins->data[j]);
+               i++;
+               j--;
+       }
+
+       // add the bridge by the reverse flag
+       if (!reverse) {
+               for (j = 0; j < bridge->pins->size; j++) {
+                       p  =        bridge->pins->data[j];
+
+                       if (scf_vector_add((*ppath)->pins, p) < 0) {
+                               ses_path_free(*ppath);
+                               *ppath = NULL;
+                               return -ENOMEM;
+                       }
+               }
+       } else {
+               for (j = bridge->pins->size - 1; j >= 0; j--) {
+                       p  = bridge->pins->data[j];
+
+                       if (scf_vector_add((*ppath)->pins, p) < 0) {
+                               ses_path_free(*ppath);
+                               *ppath = NULL;
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       // negative branch is normal
+       vip = neg->vip;
+
+       for (i   = 0; i < neg->paths->size; i++) {
+               path =        neg->paths->data[i];
+
+               for (j = 0; j < path->pins->size; j++) {
+                       p  =        path->pins->data[j];
+
+                       if (p->lid == vip->lid)
+                               break;
+               }
+
+               for (++j; j < path->pins->size; j++) {
+                       p       = path->pins->data[j];
+
+                       if (scf_vector_add((*ppath)->pins, p) < 0) {
+                               ses_path_free(*ppath);
+                               *ppath = NULL;
+                               return -ENOMEM;
+                       }
+               }
+
+               vip = path->pins->data[j - 1];
+       }
+
+       return 0;
+}
+
 void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
 {
        if (!flow)
@@ -104,10 +212,15 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
 
                        ++flow->pos_pins;
 
-                       if (p->lid == vip->lid) {
+                       c = f->components[p->cid];
+
+                       if (SCF_EDA_NPN == c->type && SCF_EDA_NPN_B == p->id)
+                               flow->pos_NPNs++;
+                       else if (SCF_EDA_Diode == c->type && SCF_EDA_Diode_POS == p->id)
+                               flow->pos_diodes++;
 
+                       if (p->lid == vip->lid) {
                                vip = path->pins->data[0];
-                               c   = f->components[p->cid];
 
                                double pr = p->pr;
 
@@ -142,6 +255,11 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
 
                        c = f->components[p->cid];
 
+                       if (SCF_EDA_NPN == c->type && SCF_EDA_NPN_B == p->id)
+                               flow->neg_NPNs++;
+                       else if (SCF_EDA_Diode == c->type && SCF_EDA_Diode_POS == p->id)
+                               flow->neg_diodes++;
+
                        if (SCF_EDA_NPN == c->type && SCF_EDA_NPN_E == p->id) {
                                p = path->pins->data[j - 1];
 
@@ -150,7 +268,7 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
                                else
                                        flow->neg_r += p->pr - p0->pr;
 
-                               scf_loge("flow->neg_r: %lg, c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
+                               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)
@@ -162,7 +280,7 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
 
                                flow->neg_r += p->sr - p0->pr;
 
-                               scf_logw("flow->neg_r: %lg, c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
+                               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);
                                p0 = p;
                        }
@@ -174,16 +292,16 @@ void ses_flow_jr(ses_flow_t* flow, ScfEfunction* f)
 
                if (vip != p0) {
                        flow->neg_r += vip->sr - p0->pr;
-                       scf_loge("flow->neg_r: %lg, vip c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
+                       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_logi("flow->neg_r: %lg, vip c%ldp%ld->sr: %lg, p0 c%ldp%ld->pr: %lg\n",
+               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_loge("flow pos_pins: %d, neg_pins: %d, pos_r: %lg, neg_r: %lg, vip: c%ldp%ld\n",
-                       flow->pos_pins, flow->neg_pins, flow->pos_r, flow->neg_r, flow->vip->cid, flow->vip->id);
+       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",
+                       flow->pos_r, flow->neg_r, flow->vip->cid, flow->vip->id, flow->pos_diodes, flow->pos_NPNs, flow->neg_diodes, flow->neg_NPNs);
 }
 
 void ses_flow_print(ses_flow_t* flow)
@@ -396,6 +514,61 @@ int ses_path_add(ses_path_t* parent, ses_path_t* child)
        return 0;
 }
 
+ses_path_t* ses_path_save(ses_path_t* src)
+{
+       ses_path_t* dst = ses_path_alloc();
+       if (!dst)
+               return NULL;
+
+       ScfEpin* p;
+       ScfEpin* p2;
+
+       int i;
+       for (i = 0; i < src->pins->size; i++) {
+               p  =        src->pins->data[i];
+
+               p2 = malloc(sizeof(ScfEpin));
+               if (!p2) {
+                       scf_vector_clear(dst->pins, (void (*)(void*) )free);
+                       ses_path_free(dst);
+                       return NULL;
+               }
+
+               if (scf_vector_add(dst->pins, p2) < 0) {
+                       scf_vector_clear(dst->pins, (void (*)(void*) )free);
+                       ses_path_free(dst);
+                       free(p2);
+                       return NULL;
+               }
+
+               memcpy(p2, p, sizeof(ScfEpin));
+       }
+
+       return dst;
+}
+
+int ses_path_load(ses_path_t* dst, ses_path_t* src)
+{
+       if (!dst || !src || dst->pins->size != src->pins->size)
+               return -EINVAL;
+
+       ScfEpin* p;
+       ScfEpin* p2;
+
+       int i;
+       for (i = 0; i < src->pins->size; i++) {
+               p  =        src->pins->data[i];
+               p2 =        dst->pins->data[i];
+
+               if (p2->cid != p->cid || p2->id != p->id)
+                       return -EINVAL;
+
+               memcpy(p, p2, sizeof(ScfEpin));
+       }
+
+       return 0;
+}
+
 ses_ctx_t* ses_ctx_alloc()
 {
        ses_ctx_t* ctx = calloc(1, sizeof(ses_ctx_t));