From: yu.dongliang <18588496441@163.com> Date: Fri, 26 Apr 2024 08:33:42 +0000 (+0800) Subject: update the bridge algorithm for capacitor X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=ca6e0eebd86bee1f1a3862f7c8dc62e625a81bd7;p=ses.git update the bridge algorithm for capacitor --- diff --git a/Makefile b/Makefile index aaec5b7..3c1bf18 100644 --- 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 db83a15..58aeeba 100644 --- 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 diff --git a/ses_core.h b/ses_core.h index b19f64b..eb50c7d 100644 --- a/ses_core.h +++ b/ses_core.h @@ -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); diff --git a/ses_layout.c b/ses_layout.c index e1d3504..6906dc4 100644 --- a/ses_layout.c +++ b/ses_layout.c @@ -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 index c1993f2..0000000 --- a/ses_step_da.c +++ /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; -} diff --git a/ses_step_jr.c b/ses_step_jr.c index 0dc3c63..ea709a9 100644 --- a/ses_step_jr.c +++ b/ses_step_jr.c @@ -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; diff --git a/ses_step_simplify.c b/ses_step_simplify.c index b4df409..a9be82d 100644 --- a/ses_step_simplify.c +++ b/ses_step_simplify.c @@ -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); diff --git a/ses_step_topo.c b/ses_step_topo.c index 77ae8b4..ca44eab 100644 --- a/ses_step_topo.c +++ b/ses_step_topo.c @@ -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) diff --git a/ses_step_va.c b/ses_step_va.c index cf08c85..29d5518 100644 --- a/ses_step_va.c +++ b/ses_step_va.c @@ -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; } diff --git a/ses_step_va_bridge.c b/ses_step_va_bridge.c index 10111f4..908ffb3 100644 --- a/ses_step_va_bridge.c +++ b/ses_step_va_bridge.c @@ -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 diff --git a/ses_step_va_capacitor.c b/ses_step_va_capacitor.c index 6998d67..6c76221 100644 --- a/ses_step_va_capacitor.c +++ b/ses_step_va_capacitor.c @@ -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) diff --git a/ses_step_va_diode.c b/ses_step_va_diode.c index 3c56ba4..400747f 100644 --- a/ses_step_va_diode.c +++ b/ses_step_va_diode.c @@ -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); diff --git a/ses_step_va_transistor.c b/ses_step_va_transistor.c index 2ed48dc..3c0a08c 100644 --- a/ses_step_va_transistor.c +++ b/ses_step_va_transistor.c @@ -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; diff --git a/ses_utils.c b/ses_utils.c index c993ab6..85b828d 100644 --- a/ses_utils.c +++ b/ses_utils.c @@ -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 index 0000000..c8532e4 --- /dev/null +++ b/test/bridge_algorithm.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +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; +} diff --git a/test/main.c b/test/main.c index 5361aef..1afc2b5 100644 --- a/test/main.c +++ b/test/main.c @@ -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;