From: yu.dongliang <18588496441@163.com> Date: Sun, 26 May 2024 06:13:57 +0000 (+0800) Subject: support PNP transistor, add pnp_oscillator.cpk X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=ed48444c0a7cff6ea5386c973efb47a314265fe7;p=ses.git support PNP transistor, add pnp_oscillator.cpk --- diff --git a/Makefile b/Makefile index 9b4794d..9619bf1 100644 --- a/Makefile +++ b/Makefile @@ -16,13 +16,13 @@ CFILES += ses_steps.c CFILES += ses_step_battery.c CFILES += ses_step_dc_input.c CFILES += ses_step_dc_diode.c -CFILES += ses_step_dc_transistor.c +CFILES += ses_step_dc_npn.c +CFILES += ses_step_dc_pnp.c CFILES += ses_step_topo.c CFILES += ses_step_jr.c CFILES += ses_step_va_diode.c -CFILES += ses_step_va_transistor.c CFILES += ses_step_va.c CFILES += ses_step_status.c diff --git a/examples/pnp_oscillator.cpk b/examples/pnp_oscillator.cpk new file mode 100644 index 0000000..62dc959 Binary files /dev/null and b/examples/pnp_oscillator.cpk differ diff --git a/main.c b/main.c index 1d0596d..c608d2a 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, 60 * 1000 + 10501); + ses_steps_analyse(f, 1000, 1); } #endif diff --git a/scf_eda_pack.h b/scf_eda_pack.h index 1f48b4c..b955ef5 100644 --- a/scf_eda_pack.h +++ b/scf_eda_pack.h @@ -36,6 +36,9 @@ enum { #define SCF_EDA_V_NPN_ON 0.70 #define SCF_EDA_V_NPN_OFF 0.61 +#define SCF_EDA_V_PNP_ON SCF_EDA_V_NPN_ON +#define SCF_EDA_V_PNP_OFF SCF_EDA_V_NPN_OFF + enum { SCF_EDA_Battery_NEG, SCF_EDA_Battery_POS, @@ -63,10 +66,10 @@ enum { }; enum { - SCF_EDA_PNP_B, - SCF_EDA_PNP_E, - SCF_EDA_PNP_C, - SCF_EDA_PNP_NB, + SCF_EDA_PNP_B = SCF_EDA_NPN_B, + SCF_EDA_PNP_E = SCF_EDA_NPN_E, + SCF_EDA_PNP_C = SCF_EDA_NPN_C, + SCF_EDA_PNP_NB = SCF_EDA_NPN_NB, }; typedef struct { @@ -301,7 +304,7 @@ SCF_PACK_INFO_OBJS(ScfEboard, functions, ScfEfunction), SCF_PACK_END(ScfEboard) -ScfEconn* scf_econn__alloc(); +ScfEconn* scf_econn__alloc(); int scf_econn__add_cid(ScfEconn* ec, uint64_t cid); int scf_econn__del_cid(ScfEconn* ec, uint64_t cid); diff --git a/ses_core.h b/ses_core.h index 1eda99c..abdbf99 100644 --- a/ses_core.h +++ b/ses_core.h @@ -54,6 +54,7 @@ struct ses_info_s int j; int n_diodes; int n_NPNs; + int n_PNPs; int n_capacitors; }; @@ -114,6 +115,7 @@ struct ses_path_s int n_capacitors; int n_diodes; int n_NPNs; + int n_PNPs; int n_transistors; int n_layers; @@ -129,15 +131,11 @@ struct ses_edge_s int vip_m; int vip_n; - int n_diodes; - int n_NPNs; - ses_node_t* node0; ses_node_t* node1; - ses_edge_t* npn_b; - int npn_index; - double npn_hfe; + ses_edge_t* edge_b; + double hfe; double cv; double r; @@ -147,6 +145,7 @@ struct ses_edge_s double a0; uint8_t vflag:1; + uint8_t bflag:1; }; struct ses_node_s diff --git a/ses_layout.c b/ses_layout.c index 0d4212e..b4aaeb7 100644 --- a/ses_layout.c +++ b/ses_layout.c @@ -668,7 +668,7 @@ static int __ses_layout_lines4(ScfEfunction* f) p = base->pins->data[j - 1]; n = __ses_find_eline_index(f, p->lid); - SCF_XCHG(f->elines[n], f->elines[j / 2 + 1]); + SCF_XCHG(f->elines[n], f->elines[j / 2]); for (i = 0; i < f->n_elines; i++) f->elines[i]->vflag = 0; @@ -1540,13 +1540,17 @@ static void __ses_xchg_ce(ScfEfunction* f, int d) ScfEpin* pe; ScfEpin* pc; - size_t i; - size_t j; + int64_t i; + int64_t j; + + assert(SCF_EDA_NPN_B == SCF_EDA_PNP_B); + assert(SCF_EDA_NPN_C == SCF_EDA_PNP_C); + assert(SCF_EDA_NPN_E == SCF_EDA_PNP_E); for (i = 0; i < f->n_components; i++) { c = f->components[i]; - if (SCF_EDA_NPN != c->type) + if (SCF_EDA_NPN != c->type && SCF_EDA_PNP != c->type) continue; j = 0; diff --git a/ses_node_analysis.c b/ses_node_analysis.c index 8324cef..0da595c 100644 --- a/ses_node_analysis.c +++ b/ses_node_analysis.c @@ -77,16 +77,16 @@ ses_edge_t* ses_nodes_find_edge_by_pin(scf_vector_t* nodes, ScfEpin* vip) return NULL; } -int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t* nodes, int* n_edges, int* n_NPNs) +int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t* nodes, int* n_edges) { ses_path_t* child; ses_path_t* bridge; ses_path_t* conn; - ses_edge_t* edge = NULL; - ses_edge_t* npn_c = NULL; - ses_node_t* prev = NULL; - ses_node_t* node = NULL; + ses_edge_t* edge = NULL; + ses_edge_t* edge_c = NULL; + ses_node_t* prev = NULL; + ses_node_t* node = NULL; ScfEcomponent* c; ScfEpin* p; @@ -107,7 +107,7 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s if (conn->vflag) continue; - ret = __ses_nodes_path2(f, conn, 0, conn->pins->size - 1, nodes, n_edges, n_NPNs); + ret = __ses_nodes_path2(f, conn, 0, conn->pins->size - 1, nodes, n_edges); if (ret < 0) return ret; } @@ -120,7 +120,7 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s if (child->vflag) continue; - ret = __ses_nodes_path2(f, child, 0, child->pins->size - 1, nodes, n_edges, n_NPNs); + ret = __ses_nodes_path2(f, child, 0, child->pins->size - 1, nodes, n_edges); if (ret < 0) return ret; } @@ -133,7 +133,7 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s if (bridge->vflag) continue; - ret = __ses_nodes_path2(f, bridge, 0, bridge->pins->size - 1, nodes, n_edges, n_NPNs); + ret = __ses_nodes_path2(f, bridge, 0, bridge->pins->size - 1, nodes, n_edges); if (ret < 0) return ret; } @@ -141,31 +141,38 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s scf_logd("path: %d, vflag: %d, vip_m: %d, vip_n: %d\n", path->index, path->vflag, vip_m, vip_n); - int n = 0; + int bflag = 0; for (i = vip_n - 1; i > vip_m; i -= 2) { p = path->pins->data[i]; c = f->components[p->cid]; - if (SCF_EDA_NPN == c->type) { + switch (c->type) { - if (SCF_EDA_NPN_B == p->id) { - npn_c = ses_nodes_find_edge_by_pin(nodes, c->pins[SCF_EDA_NPN_C]); - if (!npn_c) { - scf_loge("\n"); - return -EINVAL; - } + case SCF_EDA_PNP: + p = path->pins->data[i + 1]; + case SCF_EDA_NPN: - n++; - npn_c->npn_hfe = c->pins[SCF_EDA_NPN_C]->hfe; - } + if (SCF_EDA_NPN_B == p->id) { + edge_c = ses_nodes_find_edge_by_pin(nodes, c->pins[SCF_EDA_NPN_C]); + if (!edge_c) { + scf_loge("\n"); + return -EINVAL; + } - if (!node) { - node = ses_node_alloc(); - if (!node) - return -ENOMEM; - } - } + bflag = 1; + edge_c->hfe = c->pins[SCF_EDA_NPN_C]->hfe; + } + + if (!node) { + node = ses_node_alloc(); + if (!node) + return -ENOMEM; + } + break; + default: + break; + }; if (path->childs) { for (k = 0; k < path->childs->size; k++) { @@ -248,8 +255,8 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s } edge->index = (*n_edges)++; edge->node1 = node; - edge->n_NPNs= n; - n = 0; + edge->bflag = bflag; + bflag = 0; if (prev) { ret = ses_node_ref_edge(prev, edge); @@ -260,10 +267,9 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s edge->node0 = prev; } - if (npn_c) { - npn_c->npn_b = edge; - npn_c->npn_index = (*n_NPNs)++; - npn_c = NULL; + if (edge_c) { + edge_c->edge_b = edge; + edge_c = NULL; } ret = scf_vector_add(nodes, node); @@ -300,13 +306,12 @@ int __ses_nodes_path2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, s return ret; edge->index = (*n_edges)++; edge->node0 = prev; - edge->n_NPNs= n; - n = 0; + edge->bflag = bflag; + bflag = 0; - if (npn_c) { - npn_c->npn_b = edge; - npn_c->npn_index = (*n_NPNs)++; - npn_c = NULL; + if (edge_c) { + edge_c->edge_b = edge; + edge_c = NULL; } } @@ -319,21 +324,20 @@ int __ses_nodes_path(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, sc if (!vec) return -ENOMEM; + ses_node_t* node; + ses_edge_t* edge; + int n_edges = 0; - int n_NPNs = 0; + int i; + int j; - int ret = __ses_nodes_path2(f, path, vip_m, vip_n, vec, &n_edges, &n_NPNs); + int ret = __ses_nodes_path2(f, path, vip_m, vip_n, vec, &n_edges); if (ret < 0) { scf_vector_clear(vec, (void (*)(void*) )ses_node_free); scf_vector_free(vec); return ret; } - ses_node_t* node; - ses_edge_t* edge; - int i; - int j; - for (i = 0; i < vec->size; ) { node = vec->data[i]; @@ -410,7 +414,7 @@ static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, m++; edge->vflag = 1; - if (edge->npn_b) + if (edge->edge_b) t++; } } @@ -497,16 +501,9 @@ static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, scf_logd("c%ldp%ld-c%ldp%ld, r: %lg, cv: %lg, edge->index: %d\n", p0->cid, p0->id, p1->cid, p1->id, r, cv, edge->index); - if (edge->n_NPNs > 0) { - b[n + edge->index] = cv + edge->n_NPNs * SCF_EDA_V_NPN_ON; -#if 0 - } else if (edge->npn_b) { - A[(n + edge->index) * N + n + edge->index] = 1; - A[(n + edge->index) * N + n + edge->npn_b->index] = -edge->npn_hfe; - b[n + edge->index] = 0; - continue; -#endif - } else { + if (edge->bflag) + b[n + edge->index] = cv + SCF_EDA_V_NPN_ON; + else { b[n + edge->index] = cv; A[(n + edge->index) * N + n + edge->index] = -r; } @@ -581,11 +578,11 @@ static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, for (j = 0; j < node->edges->size; j++) { edge = node->edges->data[j]; - if (edge->npn_b) { + if (edge->edge_b) { double Ic = X[n + edge->index]; - double Ib = X[n + edge->npn_b->index]; + double Ib = X[n + edge->edge_b->index]; - double dI = Ib * edge->npn_hfe - Ic; + double dI = Ib * edge->hfe - Ic; if (dI < -1e-10) { scf_logi("Ic: %lg, Ib: %lg, dI: %lg\n", Ic, Ib, dI); @@ -594,9 +591,9 @@ static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, for (k = 0; k < N; k++) A[(n + edge->index) * N + k] = 0; - A[(n + edge->index) * N + n + edge->index] = -1; - A[(n + edge->index) * N + n + edge->npn_b->index] = edge->npn_hfe; - b[n + edge->index] = 0; + A[(n + edge->index) * N + n + edge->index] = -1; + A[(n + edge->index) * N + n + edge->edge_b->index] = edge->hfe; + b[ n + edge->index] = 0; n_amplifiers++; } @@ -649,6 +646,14 @@ static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, p0->a = edge->a; p1->a = c->pins[SCF_EDA_NPN_B]->a + c->pins[SCF_EDA_NPN_C]->a; continue; + + } else if (SCF_EDA_PNP == c->type) { + ses_ui_r(&edge->r, 0, p0->v - p1->v, 0, edge->a, 0); + + p1->dr = edge->r - p1->r; + p1->a = edge->a; + p0->a = c->pins[SCF_EDA_PNP_B]->a + c->pins[SCF_EDA_PNP_C]->a; + continue; } ret = __ses_path_va_branch(f, edge->path, edge->vip_m, edge->vip_n, edge->r, changed, ns, count); diff --git a/ses_path.c b/ses_path.c index f2628e6..b52dbf3 100644 --- a/ses_path.c +++ b/ses_path.c @@ -112,15 +112,15 @@ void ses_path_print(ses_path_t* path) if (!path) return; - ses_path_t* path2; + ses_path_t* child; ScfEpin* p; int i; int j; if (!path->parent) - printf("\033[31mpath : %d, n_diodes: %d, n_NPNs: %d, n_capacitors: %d, infos->size: %d, \033[0m", - path->index, path->n_diodes, path->n_NPNs, path->n_capacitors, path->infos->size); + printf("\033[31mpath : %d, n_diodes: %d, n_NPNs: %d, n_PNPs: %d, n_capacitors: %d, \033[0m", + path->index, path->n_diodes, path->n_NPNs, path->n_PNPs, path->n_capacitors); for (i = 0; i < path->pins->size; i++) { p = path->pins->data[i]; @@ -131,37 +131,37 @@ void ses_path_print(ses_path_t* path) if (path->connections) { for (i = 0; i < path->connections->size; i++) { - path2 = path->connections->data[i]; + child = path->connections->data[i]; - if (path2->parent == path) { - printf("\033[34mconnection: %d, n_diodes: %d, n_NPNs: %d, n_capacitors: %d, infos->size: %d, parent: %d, \033[0m", - path2->index, path2->n_diodes, path2->n_NPNs, path2->n_capacitors, path2->infos->size, path->index); + if (child->parent == path) { + printf("\033[34mconnection: %d, n_diodes: %d, n_NPNs: %d, n_PNPs: %d, n_capacitors: %d, parent: %d, \033[0m", + child->index, child->n_diodes, child->n_NPNs, child->n_PNPs, child->n_capacitors, path->index); - ses_path_print(path2); + ses_path_print(child); } else - printf("connection: %d\n", path2->index); + printf("\033[34mconnection: %d\033[0m\n", child->index); } } if (path->childs) { for (i = 0; i < path->childs->size; i++) { - path2 = path->childs->data[i]; + child = path->childs->data[i]; - printf("\033[32mchild : %d, n_diodes: %d, n_NPNs: %d, n_capacitors: %d, infos->size: %d, parent: %d, \033[0m", - path2->index, path2->n_diodes, path2->n_NPNs, path2->n_capacitors, path2->infos->size, path->index); + printf("\033[32mchild : %d, n_diodes: %d, n_NPNs: %d, n_PNPs: %d, n_capacitors: %d, parent: %d, \033[0m", + child->index, child->n_diodes, child->n_NPNs, child->n_PNPs, child->n_capacitors, path->index); - ses_path_print(path2); + ses_path_print(child); } } if (path->bridges) { for (i = 0; i < path->bridges->size; i++) { - path2 = path->bridges->data[i]; + child = path->bridges->data[i]; - printf("\033[33mbridge: %d, n_diodes: %d, n_NPNs: %d, n_capacitors: %d, infos->size: %d, parent: %d, \033[0m", - path2->index, path2->n_diodes, path2->n_NPNs, path2->n_capacitors, path2->infos->size, path->index); + printf("\033[33mbridge: %d, n_diodes: %d, n_NPNs: %d, n_PNPs: %d, n_capacitors: %d, parent: %d, \033[0m", + child->index, child->n_diodes, child->n_NPNs, child->n_PNPs, child->n_capacitors, path->index); - ses_path_print(path2); + ses_path_print(child); } } } diff --git a/ses_step_dc_transistor.c b/ses_step_dc_npn.c similarity index 92% rename from ses_step_dc_transistor.c rename to ses_step_dc_npn.c index e13c1d0..147bf2e 100644 --- a/ses_step_dc_transistor.c +++ b/ses_step_dc_npn.c @@ -1,6 +1,6 @@ #include"ses_core.h" -static int _dc_transistor_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ctx) +static int _dc_npn_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ctx) { ScfEcomponent* c; ScfEcomponent* B; @@ -111,9 +111,9 @@ static int _dc_transistor_handler(ScfEfunction* f, int64_t ns, int64_t count, se return 0; } -ses_step_t ses_step_dc_transistor = +ses_step_t ses_step_dc_npn = { - .name = "dc_transistor", + .name = "dc_npn", - .handler = _dc_transistor_handler, + .handler = _dc_npn_handler, }; diff --git a/ses_step_dc_pnp.c b/ses_step_dc_pnp.c new file mode 100644 index 0000000..bbc7ef8 --- /dev/null +++ b/ses_step_dc_pnp.c @@ -0,0 +1,119 @@ +#include"ses_core.h" + +static int _dc_pnp_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ctx) +{ + ScfEcomponent* c; + ScfEcomponent* B; + ScfEline* lb; + ScfEline* le; + ScfEpin* pb; + ScfEpin* pc; + ScfEpin* pe; + ScfEpin* Bp; + ScfEpin* Bn; + + size_t i; + size_t j; + size_t k; + + B = f->components[0]; + Bp = B->pins[SCF_EDA_Battery_POS]; + Bn = B->pins[SCF_EDA_Battery_NEG]; + + for (i = 0; i < f->n_components; i++) { + c = f->components[i]; + + if (SCF_EDA_PNP != c->type) + continue; + + pb = c->pins[SCF_EDA_PNP_B]; + pc = c->pins[SCF_EDA_PNP_C]; + pe = c->pins[SCF_EDA_PNP_E]; + + lb = f->elines[pb->lid]; + le = f->elines[pe->lid]; + + if (pe->lid == Bp->lid && pb->lid == Bn->lid) { + scf_loge("PNP c%ld, short connected\n", c->id); + return -EINVAL; + } + + if (__ses_path_pos(f, lb) && !__ses_path_neg(f, lb)) { + c->status = SCF_EDA_Status_OFF; + + scf_loge("PNP c%ld, status: %d\n", c->id, c->status); + continue; + } + + scf_logd("c%ld, status: %d, lock: %d, pb->v: %lg, pe->v: %lg, diff: %lg, off: %lg\n", + c->id, c->status, c->lock, pb->v, pe->v, pb->v - pe->v, SCF_EDA_V_PNP_OFF); + + if (lb->v < SCF_EDA_V_MIN) { + + if (le->v < SCF_EDA_V_MIN) + continue; + + pe->v = le->v; + pb->v = le->v - SCF_EDA_V_PNP_ON; + lb->v = pb->v; + + if (le->v == Bp->v) + lb->vconst = 1; + + if (pb->v < Bn->v) { + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } else + c->status = SCF_EDA_Status_ON; + + } else if (le->v < SCF_EDA_V_MIN) { + + pb->v = lb->v; + pe->v = lb->v + SCF_EDA_V_PNP_ON; + le->v = pe->v; + + if (lb->v == Bn->v) + le->vconst = 1; + + if (pe->v > Bp->v) { + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } else + c->status = SCF_EDA_Status_ON; + + } else if (lb->v <= le->v - SCF_EDA_V_PNP_OFF) { + + if (le->v == Bp->v) + lb->vconst = 1; + else if (lb->v == Bn->v) + le->vconst = 1; + + lb->v = le->v - SCF_EDA_V_PNP_ON; + pb->v = lb->v; + pe->v = le->v; + + if (pb->v < Bn->v) { + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } else + c->status = SCF_EDA_Status_ON; + } else { + pb->v = lb->v; + pe->v = le->v; + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } + + scf_loge("\033[34mc%ld, status: %d, lock: %d, pb->v: %lg, pe->v: %lg, diff: %lg, off: %lg\033[0m\n", + c->id, c->status, c->lock, pb->v, pe->v, pb->v - pe->v, SCF_EDA_V_PNP_OFF); + } + + return 0; +} + +ses_step_t ses_step_dc_pnp = +{ + .name = "dc_pnp", + + .handler = _dc_pnp_handler, +}; diff --git a/ses_step_output.c b/ses_step_output.c index cd13d0d..f5bb247 100644 --- a/ses_step_output.c +++ b/ses_step_output.c @@ -14,7 +14,7 @@ static int _output_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t for (i = 0; i < f->n_elines; i++) { el = f->elines[i]; - printf("e%ld->vconst: %d\n", el->id, el->vconst); + scf_logd("e%ld->vconst: %d\n", el->id, el->vconst); if (SCF_EDA_PIN_OUT & el->flags) scf_logw("out el: %ld, V: %lg\n", el->id, el->v); diff --git a/ses_step_simplify.c b/ses_step_simplify.c index 2b1bdd4..471ed97 100644 --- a/ses_step_simplify.c +++ b/ses_step_simplify.c @@ -1,7 +1,7 @@ #include #include"ses_core.h" -#define SHOW_BITS 1000000.0 +#define SHOW_BITS 10000.0 static void ses_text_a(cairo_t* cr, int x, int y, double a) { @@ -330,6 +330,67 @@ void __ses_function_draw(ScfEfunction* f, cairo_t* cr) cairo_stroke(cr); } + cairo_select_font_face(cr, "Georgia", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + ses_text_a(cr, c->x, (pb->y + c->y) / 2, pb->a); + ses_text_a(cr, c->x, c->y, pc->a); + ses_text_a(cr, c->x, (pe->y + c->y) / 2, pe->a); + cairo_stroke(cr); + break; + + case SCF_EDA_PNP: + pb = c->pins[SCF_EDA_PNP_B]; + pc = c->pins[SCF_EDA_PNP_C]; + pe = c->pins[SCF_EDA_PNP_E]; + + vertical(&dx0, &dy0, c->x - pb->x, c->y - pb->y, 8); + forward (&dx3, &dy3, c->x - pb->x, c->y - pb->y, 8); + + cairo_arc(cr, c->x - dx3 / 2, c->y - dy3 / 2, 12, 0, 2 * M_PI); + + cairo_move_to (cr, pb->x, pb->y); + cairo_line_to (cr, c->x - dx3, c->y - dy3); + cairo_rel_move_to(cr, dx0, dy0); + cairo_rel_line_to(cr, -dx0 * 2, -dy0 * 2); + cairo_stroke(cr); + + if ((c->x + dx3 + dx0 > c->x + dx3 - dx0 && pe->x > pc->x) + || (c->x + dx3 + dx0 < c->x + dx3 - dx0 && pe->x < pc->x)) { + + cairo_move_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x + dx3 + dx0, c->y + dy3 + dy0); + cairo_line_to(cr, pe->x, pe->y); + + vertical(&dx1, &dy1, dx3 * 2 + dx0, dy3 * 2 + dy0, 4); + forward (&dx4, &dy4, dx3 * 2 + dx0, dy3 * 2 + dy0, 12); + + cairo_move_to(cr, c->x - dx3 + dx4 + dx1, c->y - dy3 + dy4 + dy1); + cairo_line_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x - dx3 + dx4 - dx1, c->y - dy3 + dy4 - dy1); + cairo_stroke(cr); + + cairo_move_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x + dx3 - dx0, c->y + dy3 - dy0); + cairo_line_to(cr, pc->x, pc->y); + cairo_stroke(cr); + } else { + cairo_move_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x + dx3 + dx0, c->y + dy3 + dy0); + cairo_line_to(cr, pc->x, pc->y); + cairo_stroke(cr); + + cairo_move_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x + dx3 - dx0, c->y + dy3 - dy0); + cairo_line_to(cr, pe->x, pe->y); + + vertical(&dx1, &dy1, dx3 * 2 - dx0, dy3 * 2 - dy0, 4); + forward (&dx4, &dy4, dx3 * 2 - dx0, dy3 * 2 - dy0, 12); + + cairo_move_to(cr, c->x - dx3 + dx4 + dx1, c->y - dy3 + dy4 + dy1); + cairo_line_to(cr, c->x - dx3, c->y - dy3); + cairo_line_to(cr, c->x - dx3 + dx4 - dx1, c->y - dy3 + dy4 - dy1); + cairo_stroke(cr); + } + cairo_select_font_face(cr, "Georgia", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); ses_text_a(cr, c->x, (pb->y + c->y) / 2, pb->a); ses_text_a(cr, c->x, c->y, pc->a); @@ -449,7 +510,7 @@ int ses_simplify_draw(ScfEfunction* f, const char* file, uint32_t bx, uint32_t b n = snprintf(text, sizeof(text) - 1, "%lgmV", (int64_t)(el->v * 1000.0 * SHOW_BITS) / SHOW_BITS); else n = snprintf(text, sizeof(text) - 1, "%lguV", (int64_t)(el->v * 1000000.0 * SHOW_BITS) / SHOW_BITS); - +#if 0 // A of line if (el->aout > 1e-1 || el->aout < -1e-1) n += snprintf(text + n, sizeof(text) - 1 - n, ", %lgA", (int64_t)(el->aout * SHOW_BITS) / SHOW_BITS); @@ -466,7 +527,7 @@ int ses_simplify_draw(ScfEfunction* f, const char* file, uint32_t bx, uint32_t b n += snprintf(text + n, sizeof(text) - 1 - n, ", in %lgmA", (int64_t)(el->ain * 1000.0 * SHOW_BITS) / SHOW_BITS); else n += snprintf(text + n, sizeof(text) - 1 - n, ", in %lguA", (int64_t)(el->ain * 1000000.0 * SHOW_BITS) / SHOW_BITS); - +#endif int cx = INT_MAX; int cy = l->y0; @@ -528,13 +589,13 @@ static int _simplify_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx char file[128]; snprintf(file, sizeof(file) - 1, "./simplify_%ld.png", i); -#if 1 +#if 0 if (count < 60 * 1000) return 0; #endif if (count % 10 == 0) { -#if 1 +#if 0 static FILE* fp = NULL; if (!fp) fp = fopen("v.txt", "w"); @@ -542,7 +603,7 @@ static int _simplify_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx if (fp) fprintf(fp, "%ld, %lg\n", i, f->elines[4]->v); #endif -// ses_simplify_draw(f, file, f->x, f->y, f->w, f->h, ns, count); + ses_simplify_draw(f, file, f->x, f->y, f->w, f->h, ns, count); i++; } diff --git a/ses_step_status.c b/ses_step_status.c index 01ee0f9..213775d 100644 --- a/ses_step_status.c +++ b/ses_step_status.c @@ -32,16 +32,11 @@ int __ses_path_status(ScfEfunction* f, ses_path_t* bridge, int* changed, scf_vec __ses_path_jr(f, bridge); - if (bridge->n_diodes + bridge->n_NPNs > 0) { + if (bridge->n_diodes + bridge->n_NPNs + bridge->n_PNPs > 0) { __ses_path_va_diode(f, bridge); __ses_path_jr (f, bridge); } - if (bridge->n_transistors > 0) { - __ses_path_va_transistor(f, bridge); - __ses_path_jr (f, bridge); - } - int ret = __ses_path_va(f, bridge, &__changed, ns, count); if (ret < 0) return ret; diff --git a/ses_step_topo.c b/ses_step_topo.c index 9bf978a..44da2bf 100644 --- a/ses_step_topo.c +++ b/ses_step_topo.c @@ -1,16 +1,31 @@ #include"ses_core.h" +static int __ses_dfs_add_path(scf_vector_t* paths, ses_path_t* path) +{ + ScfEpin* p; + int j; + + if (scf_vector_add(paths, path) < 0) + return -ENOMEM; + + for (j = 0; j < path->pins->size; j++) { + p = path->pins->data[j]; + p->pflag = 1; + p->path = (uintptr_t)path; + } + + return 0; +} + static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_vector_t* __paths, ses_path_t** ppath) { ScfEcomponent* c; ScfEline* el; ScfEpin* np; ScfEpin* p; - ScfEpin* p2; size_t i; size_t j; - size_t k; if (SCF_EDA_Status_OFF == rc->status) return SCF_EDA_Status_OFF; @@ -21,6 +36,9 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (SCF_EDA_NPN == rc->type && SCF_EDA_NPN_E == rp->id) return SCF_EDA_Path_OFF; + if (SCF_EDA_PNP == rc->type && SCF_EDA_PNP_E != rp->id) + return SCF_EDA_Path_OFF; + if (!*ppath) { *ppath = ses_path_alloc(); if (!*ppath) @@ -30,7 +48,8 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (scf_vector_add((*ppath)->pins, rp) < 0) return -ENOMEM; - if (SCF_EDA_NPN != rc->type || SCF_EDA_NPN_E != rp->id) + if (!((SCF_EDA_NPN == rc->type && SCF_EDA_NPN_E == rp->id) + || (SCF_EDA_PNP == rc->type && SCF_EDA_PNP_E == rp->id))) rp->vflag = 1; scf_logd("c%ld_p%ld, l%ld, vflag: %d, pflag: %d\n", rp->cid, rp->id, rp->lid, rp->vflag, rp->pflag); @@ -45,6 +64,8 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (SCF_EDA_NPN == rc->type && SCF_EDA_NPN_E != np->id) continue; + if (SCF_EDA_PNP == rc->type && SCF_EDA_PNP_E == np->id) + continue; scf_logd("c%ld_p%ld, l%ld, vflag: %d, pflag: %d\n", np->cid, np->id, np->lid, np->vflag, np->pflag); @@ -63,22 +84,24 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v return -ENOMEM; } + if (SCF_EDA_PNP == rc->type && 0 == (*ppath)->pins->size) { + + if (scf_vector_add((*ppath)->pins, rp) < 0) + return -ENOMEM; + } + if (scf_vector_add((*ppath)->pins, np) < 0) return -ENOMEM; - if (SCF_EDA_NPN != rc->type || SCF_EDA_NPN_E != np->id) + if (!((SCF_EDA_NPN == rc->type && SCF_EDA_NPN_E == np->id) + || (SCF_EDA_PNP == rc->type && SCF_EDA_PNP_E == np->id))) np->vflag = 1; if (SCF_EDA_PIN_NEG & el->flags) { - if (scf_vector_add(__paths, *ppath) < 0) - return -ENOMEM; - - for (j = 0; j < (*ppath)->pins->size; j++) { - p2 = (*ppath)->pins->data[j]; - p2->pflag = 1; - p2->path = (uintptr_t)*ppath; - } + ret = __ses_dfs_add_path(__paths, *ppath); + if (ret < 0) + return ret; *ppath = NULL; return 0; @@ -93,17 +116,13 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (p->pflag) { if (p != np && *ppath) { - scf_logd("branch: c%ld_p%ld, l%ld\n", c->id, p->id, el->id); + scf_logd("branch: c%ld_p%ld, l%ld\n\n", c->id, p->id, el->id); if ((*ppath)->pins->size > 0) { - if (scf_vector_add(__paths, *ppath) < 0) - return -ENOMEM; - - for (k = 0; k < (*ppath)->pins->size; k++) { - p2 = (*ppath)->pins->data[k]; - p2->pflag = 1; - p2->path = (uintptr_t)*ppath; - } + + ret = __ses_dfs_add_path(__paths, *ppath); + if (ret < 0) + return ret; } else ses_path_free(*ppath); @@ -117,28 +136,38 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (SCF_EDA_Capacitor == rc->type && SCF_EDA_Capacitor != c->type) { if (*ppath) { - if (scf_vector_add(__paths, *ppath) < 0) - return -ENOMEM; + if ((*ppath)->pins->size > 0) { - for (j = 0; j < (*ppath)->pins->size; j++) { - p2 = (*ppath)->pins->data[j]; - p2->pflag = 1; - p2->path = (uintptr_t)*ppath; - } + ret = __ses_dfs_add_path(__paths, *ppath); + if (ret < 0) + return ret; + } else + ses_path_free(*ppath); *ppath = NULL; } } - if (SCF_EDA_NPN != c->type || SCF_EDA_NPN_E != p->id) + if (!((SCF_EDA_NPN == c->type && SCF_EDA_NPN_E == p->id) + || (SCF_EDA_PNP == c->type && SCF_EDA_PNP_E == p->id))) p->vflag = 1; + ses_path_t* tmp = NULL; + + if (SCF_EDA_Capacitor != rc->type && SCF_EDA_Capacitor == c->type) { + tmp = *ppath; + *ppath = NULL; + } + ret = __ses_dfs_path(f, c, p, __paths, ppath); if (ret < 0) return ret; if (SCF_EDA_Path_OFF == ret) p->vflag = 0; + + if (tmp) + *ppath = tmp; } if (*ppath) { @@ -159,10 +188,10 @@ static int __ses_dfs_path(ScfEfunction* f, ScfEcomponent* rc, ScfEpin* rp, scf_v if (SCF_EDA_Path_OFF == ret) { rp->vflag = 0; - scf_logd("off: c%ld_p%ld, l%ld\n", rp->cid, rp->id, rp->lid); + scf_logd("off: c%ld_p%ld, l%ld\n\n", rp->cid, rp->id, rp->lid); } else if (SCF_EDA_Status_OFF == ret) - scf_logd("off: c%ld_p%ld, l%ld\n", rp->cid, rp->id, rp->lid); + scf_logd("off: c%ld_p%ld, l%ld\n\n", rp->cid, rp->id, rp->lid); } return ret; @@ -187,6 +216,25 @@ static int ses_pin_to_npn(const ScfEfunction* f, const ScfEpin* vip, int pid) return 0; } +static int ses_pin_to_pnp(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_PNP == 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]; @@ -195,7 +243,6 @@ static int ses_path_to_npn(const ScfEfunction* f, const ses_path_t* path, int pi return ses_pin_to_npn(f, p0, pid) || ses_pin_to_npn(f, p1, pid); } - static int _ses_child_cmp(const void* v0, const void* v1) { const ses_path_t* p0 = *(const ses_path_t**)v0; @@ -279,28 +326,32 @@ static int __topo_path_bridges(ScfEfunction* f, ses_path_t* path) c0 = f->components[p0->cid]; c1 = f->components[p1->cid]; - if (SCF_EDA_NPN == c0->type && SCF_EDA_NPN_C == p0->id) + if ((SCF_EDA_NPN == c0->type && SCF_EDA_NPN_C == p0->id) + || (SCF_EDA_PNP == c0->type && SCF_EDA_PNP_C == p0->id)) goto bridge_sp1; - if (SCF_EDA_NPN == c1->type && SCF_EDA_NPN_C == p1->id) + if ((SCF_EDA_NPN == c1->type && SCF_EDA_NPN_C == p1->id) + || (SCF_EDA_PNP == c1->type && SCF_EDA_PNP_C == p1->id)) goto bridge_sp0; if ((SCF_EDA_Diode == c0->type && SCF_EDA_Diode_POS == p0->id) - || (SCF_EDA_NPN == c0->type && SCF_EDA_NPN_B == p0->id)) + || (SCF_EDA_NPN == c0->type && SCF_EDA_NPN_B == p0->id) + || (SCF_EDA_PNP == c0->type && SCF_EDA_PNP_B == p0->id)) goto bridge_sp1; if ((SCF_EDA_Diode == c1->type && SCF_EDA_Diode_POS == p1->id) - || (SCF_EDA_NPN == c1->type && SCF_EDA_NPN_B == p1->id)) + || (SCF_EDA_NPN == c1->type && SCF_EDA_NPN_B == p1->id) + || (SCF_EDA_PNP == c1->type && SCF_EDA_PNP_B == p1->id)) goto bridge_sp0; - if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_B)) + if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_B) || ses_pin_to_pnp(f, p0, SCF_EDA_PNP_B)) goto bridge_sp1; - if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_B)) + if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_B) || ses_pin_to_pnp(f, p1, SCF_EDA_PNP_B)) goto bridge_sp0; - if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_C)) + if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_C) || ses_pin_to_pnp(f, p0, SCF_EDA_PNP_C)) goto bridge_sp1; - if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_C)) + if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_C) || ses_pin_to_pnp(f, p1, SCF_EDA_PNP_C)) goto bridge_sp0; // negative pin of path @@ -313,25 +364,27 @@ static int __topo_path_bridges(ScfEfunction* f, ses_path_t* path) if (SCF_EDA_PIN_IN & p1->flags) goto bridge_sp0; - if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_B)) + if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_B) || ses_pin_to_pnp(f, p0, SCF_EDA_PNP_B)) goto bridge_sp1; - if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_B)) + if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_B) || ses_pin_to_pnp(f, p1, SCF_EDA_PNP_B)) goto bridge_sp0; - if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_C)) + if (ses_pin_to_npn(f, p0, SCF_EDA_NPN_C) || ses_pin_to_pnp(f, p0, SCF_EDA_PNP_C)) goto bridge_sp1; - if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_C)) + if (ses_pin_to_npn(f, p1, SCF_EDA_NPN_C) || ses_pin_to_pnp(f, p1, SCF_EDA_PNP_C)) goto bridge_sp0; c0 = f->components[p0->cid]; c1 = f->components[p1->cid]; if ((SCF_EDA_Diode == c0->type && SCF_EDA_Diode_NEG == p0->id) - || (SCF_EDA_NPN == c0->type && SCF_EDA_NPN_E == p0->id)) + || (SCF_EDA_NPN == c0->type && SCF_EDA_NPN_E == p0->id) + || (SCF_EDA_PNP == c0->type && SCF_EDA_PNP_E == p0->id)) goto bridge_sp1; if ((SCF_EDA_Diode == c1->type && SCF_EDA_Diode_NEG == p1->id) - || (SCF_EDA_NPN == c1->type && SCF_EDA_NPN_E == p1->id)) + || (SCF_EDA_NPN == c1->type && SCF_EDA_NPN_E == p1->id) + || (SCF_EDA_PNP == c1->type && SCF_EDA_PNP_E == p1->id)) goto bridge_sp0; bridge_sp1: @@ -767,6 +820,7 @@ static int __topo_path_key_infos(ScfEfunction* f, ses_path_t* path) scf_vector_clear(path->infos, ( void (*)(void*) )free); path->n_diodes = 0; path->n_NPNs = 0; + path->n_PNPs = 0; for (i = 0; i < path->pins->size; i++) { p = path->pins->data[i]; @@ -820,6 +874,39 @@ static int __topo_path_key_infos(ScfEfunction* f, ses_path_t* path) } } + if (SCF_EDA_PNP == c->type) { + + if (SCF_EDA_PNP_B == p->id) { + if (!info) { + info = calloc(1, sizeof(ses_info_t)); + if (!info) + return -ENOMEM; + + info->i = i - 1; + } + + info->n_PNPs++; + path->n_PNPs++; + + if (__ses_branch_exist(path, i)) { + j = i; + goto _add; + } + + } else if (SCF_EDA_PNP_C == p->id) { + if (info) { + if (info->n_diodes + info->n_NPNs + info->n_PNPs > 0) { + j = i - 2; + goto _add; + } + + free(info); + info = NULL; + } + } + continue; + } + j = i - 1; _add: if (info) { @@ -996,6 +1083,7 @@ static void _topo_key_components(ScfEfunction* f, ses_path_t* path) int i; path->n_NPNs = 0; + path->n_PNPs = 0; path->n_diodes = 0; path->n_capacitors = 0; @@ -1017,6 +1105,14 @@ static void _topo_key_components(ScfEfunction* f, ses_path_t* path) else if (SCF_EDA_NPN_C == p->id) path->n_transistors++; + } else if (SCF_EDA_PNP == c->type) { + + if (SCF_EDA_PNP_B == p->id) + path->n_PNPs++; + + else if (SCF_EDA_PNP_C == p->id) + path->n_transistors++; + } else if (SCF_EDA_Capacitor == c->type) { if (0 == p->id) @@ -1403,21 +1499,7 @@ static int _topo_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ret = _topo_bridge_connections(f, ctx->paths); if (ret < 0) return ret; -#if 1 -// if (count > 30000) { - R = f->components[10]; - - double w0 = 2 * 3.1415926 * 100; - double w1 = 2 * 3.1415926 * 1000; - double w2 = 2 * 3.1415926 * 5000; - double r0 = sin(w0 * ns * (count - 30000) / 1e9); - double r1 = sin(w1 * ns * (count - 30000) / 1e9); - double r2 = sin(w2 * ns * (count - 30000) / 1e9); - R->dr = 10.0 * (r0 + r1 + r2); - - scf_logi("### c%ld->r: %lg, r: %lg\n", R->id, R->r, R->dr); -// } -#endif + int i; for (i = 0; i < ctx->paths->size; i++) { path = ctx->paths->data[i]; diff --git a/ses_step_va.c b/ses_step_va.c index 1f20b3a..cbdfb2c 100644 --- a/ses_step_va.c +++ b/ses_step_va.c @@ -1,5 +1,88 @@ #include"ses_core.h" +int __ses_status_check(ScfEfunction* f, ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe, int vinit) +{ + ScfEcomponent* c2; + ScfEline* el; + ScfEpin* p2; + + ScfEcomponent* B = f->components[0]; + ScfEpin* Bp = B->pins[SCF_EDA_Battery_POS]; + ScfEpin* Bn = B->pins[SCF_EDA_Battery_NEG]; + + size_t i; + double Voff = SCF_EDA_Diode == c->type ? SCF_EDA_V_Diode_OFF : SCF_EDA_V_NPN_OFF; + double Von = SCF_EDA_Diode == c->type ? SCF_EDA_V_Diode_ON : SCF_EDA_V_NPN_ON; + + pb->v = f->elines[pb->lid]->v; + pe->v = f->elines[pe->lid]->v; + + if (pb->v < SCF_EDA_V_MIN) { + + if (pe->v < SCF_EDA_V_MIN) + return 0; + + pb->v = pe->v + Von; + + if (pb->v > Bp->v) { + pb->v = Bp->v; + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } else + c->status = SCF_EDA_Status_ON; + goto _changed; + + } else if (pe->v < SCF_EDA_V_MIN) { + pe->v = pb->v - Von; + + if (pe->v < Bn->v) { + pe->v = Bn->v; + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + } else + c->status = SCF_EDA_Status_ON; + goto _changed; + + } else if (pb->v - pe->v < Voff) { + + if (c->status != SCF_EDA_Status_OFF) { + if (!c->lock) + c->status = SCF_EDA_Status_OFF; + goto _changed; + } + } else if (SCF_EDA_Status_ON != c->status) { + c->status = SCF_EDA_Status_ON; + goto _changed; + } + + return 0; + +_changed: + if (SCF_EDA_NPN == c->type || SCF_EDA_PNP == c->type) { + + p2 = c->pins [SCF_EDA_NPN_C]; + el = f->elines[p2->lid]; + el->vinit = vinit; + + for (i = 0; i + 1 < el->n_pins; i += 2) { + + c2 = f->components[el->pins[i]]; + p2 = c->pins [el->pins[i + 1]]; + + if ((SCF_EDA_NPN == c2->type || SCF_EDA_PNP == c2->type) && SCF_EDA_NPN_B == p2->id) { + c2->status = SCF_EDA_Status_ON; + c2->lock = 1; + + scf_loge("\033[35mc%ld, status: %d\033[0m\n", c2->id, c2->status); + } + } + } + + scf_loge("\033[34mc%ld, status: %d, pb->v: %lg, pe->v: %lg, diff: %lg, Von: %lg, Voff: %lg\033[0m\n", + c->id, c->status, pb->v, pe->v, pb->v - pe->v, Von, Voff); + return 1; +} + 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) { @@ -262,17 +345,18 @@ int __ses_path_va_branch(ScfEfunction* f, ses_path_t* path, int m, int n, double scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, r: %lg, p->a: %lg, a: %lg, p->pr: %lg, e%ld->v: %lg\n\n", path->index, i, p->cid, p->id, p->v, dv, r, p->a, a, p->pr, el->id, el->v); - if (SCF_EDA_Diode == c->type) { + switch (c->type) { + case SCF_EDA_Diode: - if (SCF_EDA_Diode_NEG == p->id) { + assert(SCF_EDA_Diode_NEG == p->id); p2 = path->pins->data[i - 1]; *changed += __ses_status_check(f, c, p2, p, 1); - } + break; - } else if (SCF_EDA_NPN == c->type) { + case SCF_EDA_NPN: - if (SCF_EDA_NPN_E == p->id) { + assert(SCF_EDA_PNP_E == p->id); p2 = path->pins->data[i - 1]; if (SCF_EDA_NPN_B == p2->id) { @@ -280,8 +364,23 @@ int __ses_path_va_branch(ScfEfunction* f, ses_path_t* path, int m, int n, double c->pins[SCF_EDA_NPN_C]->aconst = 1; } - } - } + break; + + case SCF_EDA_PNP: + + if (SCF_EDA_PNP_B == p->id) { + p2 = path->pins->data[i - 1]; + + assert(SCF_EDA_PNP_E == p2->id); + + *changed += __ses_status_check(f, c, p2, p, 1); + + c->pins[SCF_EDA_PNP_C]->aconst = 1; + } + break; + default: + break; + }; r = 0; } else { @@ -449,17 +548,18 @@ int __ses_path_va3(ScfEfunction* f, ses_path_t* path, int m, int n, double pr, i scf_loge("path: %d, i: %d, c%ldp%ld, p->v: %lg, dv: %lg, r: %lg, p->a: %lg, a: %lg, p->pr: %lg, e%ld->v: %lg\n\n", path->index, i, p->cid, p->id, p->v, dv, r, p->a, a, p->pr, el->id, el->v); - if (SCF_EDA_Diode == c->type) { + switch (c->type) { + case SCF_EDA_Diode: - if (SCF_EDA_Diode_NEG == p->id) { + assert(SCF_EDA_Diode_NEG == p->id); p2 = path->pins->data[i - 1]; *changed += __ses_status_check(f, c, p2, p, 1); - } + break; - } else if (SCF_EDA_NPN == c->type) { + case SCF_EDA_NPN: - if (SCF_EDA_NPN_E == p->id) { + assert(SCF_EDA_PNP_E == p->id); p2 = path->pins->data[i - 1]; if (SCF_EDA_NPN_B == p2->id) { @@ -467,8 +567,23 @@ int __ses_path_va3(ScfEfunction* f, ses_path_t* path, int m, int n, double pr, i c->pins[SCF_EDA_NPN_C]->aconst = 1; } - } - } + break; + + case SCF_EDA_PNP: + + if (SCF_EDA_PNP_B == p->id) { + p2 = path->pins->data[i - 1]; + + assert(SCF_EDA_PNP_E == p2->id); + + *changed += __ses_status_check(f, c, p2, p, 1); + + c->pins[SCF_EDA_PNP_C]->aconst = 1; + } + break; + default: + break; + }; r = 0; } else { diff --git a/ses_step_va_diode.c b/ses_step_va_diode.c index be5f8f9..286b466 100644 --- a/ses_step_va_diode.c +++ b/ses_step_va_diode.c @@ -44,6 +44,25 @@ void __ses_path_dr_forward(ScfEfunction* f, ses_path_t* path, int i, int j, doub p1->a = (1 + p1->hfe) * a; p1->aconst = 1; + a = p1->a; + + } else if (SCF_EDA_PNP == c->type && SCF_EDA_PNP_B == p->id) { + + ses_ui_r(&p->dr, NULL, SCF_EDA_V_PNP_ON, 0, a, 0); + + p->dr -= p->r; + + p1 = c->pins[SCF_EDA_PNP_C]; + p1->a = p1->hfe * a; + p1->aconst = 1; + + scf_logw("c%ldp%ld, v: %lg, r: %lg, a: %lg, dr: %lg, c%ldp%ld->a: %lg\n", + p->cid, p->id, SCF_EDA_V_PNP_ON, p->r, a, p->dr, p1->cid, p1->id, p1->a); + + p1 = c->pins[SCF_EDA_PNP_E]; + p1->a = (1 + p1->hfe) * a; + p1->aconst = 1; + a = p1->a; } } @@ -97,7 +116,7 @@ void __ses_path_split_i(ScfEfunction* f, ses_path_t* path, int i, int j, double cp1->sr = child->sr; cp1->pr = child->pr; - if (child->n_diodes + child->n_NPNs > 0) { + if (child->n_diodes + child->n_NPNs + child->n_PNPs > 0) { int ret = __ses_path_va_diode(f, child); if (ret < 0) @@ -119,7 +138,7 @@ void __ses_path_split_i(ScfEfunction* f, ses_path_t* path, int i, int j, double cp0->a = ca; - if (child->n_diodes + child->n_NPNs > 0) + if (child->n_diodes + child->n_NPNs + child->n_PNPs > 0) __ses_path_dr_forward(f, child, 0, child->pins->size - 1, ca); ok: @@ -131,54 +150,6 @@ ok: } } -void __ses_path_dr_reverse(ScfEfunction* f, ses_path_t* path, int i, int j, double a) -{ - ScfEpin* p = path->pins->data[i]; - ScfEpin* p1 = path->pins->data[j]; - - double r; - - int k; - for (k = j; k >= i; k--) { - - ScfEcomponent* c; - - p = path->pins->data[k]; - c = f->components[p->cid]; - - if (SCF_EDA_Diode == c->type && SCF_EDA_Diode_NEG == p->id) { - - ses_ui_r(&p->dr, NULL, SCF_EDA_V_Diode_ON, 0, a, 0); - - p->dr -= p->r; - - scf_logw("c%ldp%ld, v: %lg, r: %lg, a: %lg, dr: %lg\n", p->cid, p->id, SCF_EDA_V_Diode_ON, p->r, a, p->dr); - - p1 = c->pins[SCF_EDA_Diode_POS]; - p1->a = a; - - } else if (SCF_EDA_NPN == c->type && SCF_EDA_NPN_B == p->id) { - - p1 = c->pins[SCF_EDA_NPN_E]; - p1->a = a; - p1->aconst = 1; - - p1 = c->pins[SCF_EDA_NPN_C]; - - a /= (1 + p1->hfe); - - p1->a = p1->hfe * a; - p1->aconst = 1; - - ses_ui_r(&p->dr, NULL, SCF_EDA_V_NPN_ON, 0, a, 0); - - p->dr -= p->r; - - scf_logw("c%ldp%ld, v: %lg, r: %lg, a: %lg, dr: %lg\n", p->cid, p->id, SCF_EDA_V_NPN_ON, p->r, a, p->dr); - } - } -} - static void __ses_path_a_diode(ScfEfunction* f, ses_path_t* path, int i, int k, double cv, double* a) { ses_info_t* info; @@ -201,7 +172,9 @@ static void __ses_path_a_diode(ScfEfunction* f, ses_path_t* path, int i, int k, pi = path->pins->data[i]; pj = path->pins->data[info->i]; - v -= info->n_diodes * SCF_EDA_V_Diode_ON + info->n_NPNs * SCF_EDA_V_NPN_ON; + v -= info->n_diodes * SCF_EDA_V_Diode_ON; + v -= info->n_NPNs * SCF_EDA_V_NPN_ON; + v -= info->n_PNPs * SCF_EDA_V_PNP_ON; __ses_path_pr(f, path, i, info->i, NULL, &_r); @@ -241,12 +214,12 @@ int __ses_path_va_diode(ScfEfunction* f, ses_path_t* path) ScfEpin* pi; ScfEpin* pj; - if ((path->n_diodes + path->n_NPNs) * 2 >= path->pins->size) { + if ((path->n_diodes + path->n_NPNs + path->n_PNPs) * 2 >= path->pins->size) { scf_loge("all components are diodes\n\n"); return -1; } - if (path->n_diodes + path->n_NPNs <= 0) + if (path->n_diodes + path->n_NPNs + path->n_PNPs <= 0) return 0; p0 = path->pins->data[0]; @@ -276,7 +249,8 @@ int __ses_path_va_diode(ScfEfunction* f, ses_path_t* path) pi->v = el->v; assert((SCF_EDA_Diode == c->type && SCF_EDA_Diode_POS == pi->id) - || (SCF_EDA_NPN == c->type && SCF_EDA_NPN_B == pi->id)); + || (SCF_EDA_NPN == c->type && SCF_EDA_NPN_B == pi->id) + || (SCF_EDA_PNP == c->type && SCF_EDA_PNP_E == pi->id)); __ses_path_capacitors(f, path, i, path->pins->size - 1, &cv); @@ -298,7 +272,9 @@ int __ses_path_va_diode(ScfEfunction* f, ses_path_t* path) __ses_path_capacitors(f, path, i, info->i, &cv2); pi->v = p0->v - v - cv2; - pj->v = pi->v - info->n_diodes * SCF_EDA_V_Diode_ON - info->n_NPNs * SCF_EDA_V_NPN_ON; + pj->v = pi->v - info->n_diodes * SCF_EDA_V_Diode_ON + - info->n_NPNs * SCF_EDA_V_NPN_ON + - info->n_PNPs * SCF_EDA_V_PNP_ON; scf_logi("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, cv2: %lg, r: %lg, v: %lg, a: %lg\n", p0->cid, p0->id, p0->v, pi->cid, pi->id, pi->v, pj->cid, pj->id, pj->v, cv2, r, v, a); diff --git a/ses_step_va_transistor.c b/ses_step_va_transistor.c deleted file mode 100644 index 482e3df..0000000 --- a/ses_step_va_transistor.c +++ /dev/null @@ -1,301 +0,0 @@ -#include"ses_core.h" - -void __ses_path_dr_transistor(ScfEfunction* f, ses_path_t* path, int i, int j) -{ - ScfEpin* p = path->pins->data[i]; - ScfEpin* p1 = path->pins->data[j]; - - double v = p->v - p1->v; - double r; - double dr; - - __ses_path_sr(f, path, i, j, &r); - - ses_ui_r(&dr, NULL, v, 0, p->a, 0); - - p->dr = dr - r; - - scf_logi("c%ldp%ld--c%ldp%ld, v: %lg, r: %lg, dr: %lg, p->sr: %lg, p->a: %lg, p->dr: %lg\n", - p->cid, p->id, p1->cid, p1->id, v, r, dr, p->sr, p->a, p->dr); -} - -int __ses_status_check(ScfEfunction* f, ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe, int vinit) -{ - ScfEcomponent* c2; - ScfEline* el; - ScfEpin* p2; - - ScfEcomponent* B = f->components[0]; - ScfEpin* Bp = B->pins[SCF_EDA_Battery_POS]; - ScfEpin* Bn = B->pins[SCF_EDA_Battery_NEG]; - - size_t i; - double Voff = SCF_EDA_Diode == c->type ? SCF_EDA_V_Diode_OFF : SCF_EDA_V_NPN_OFF; - double Von = SCF_EDA_Diode == c->type ? SCF_EDA_V_Diode_ON : SCF_EDA_V_NPN_ON; - - pb->v = f->elines[pb->lid]->v; - pe->v = f->elines[pe->lid]->v; - - if (pb->v < SCF_EDA_V_MIN) { - - if (pe->v < SCF_EDA_V_MIN) - return 0; - - pb->v = pe->v + Von; - - if (pb->v > Bp->v) { - pb->v = Bp->v; - if (!c->lock) - c->status = SCF_EDA_Status_OFF; - } else - c->status = SCF_EDA_Status_ON; - goto _changed; - - } else if (pe->v < SCF_EDA_V_MIN) { - pe->v = pb->v - Von; - - if (pe->v < Bn->v) { - pe->v = Bn->v; - if (!c->lock) - c->status = SCF_EDA_Status_OFF; - } else - c->status = SCF_EDA_Status_ON; - goto _changed; - - } else if (pb->v - pe->v < Voff) { - - if (c->status != SCF_EDA_Status_OFF) { - if (!c->lock) - c->status = SCF_EDA_Status_OFF; - goto _changed; - } - } else if (SCF_EDA_Status_ON != c->status) { - c->status = SCF_EDA_Status_ON; - goto _changed; - } - - return 0; - -_changed: - if (SCF_EDA_NPN == c->type) { - - p2 = c->pins [SCF_EDA_NPN_C]; - el = f->elines[p2->lid]; - el->vinit = vinit; - - for (i = 0; i + 1 < el->n_pins; i += 2) { - - c2 = f->components[el->pins[i]]; - p2 = c->pins [el->pins[i + 1]]; - - if (SCF_EDA_NPN == c2->type && SCF_EDA_NPN_B == p2->id) { - c2->status = SCF_EDA_Status_ON; - c2->lock = 1; - - scf_loge("\033[35mc%ld, status: %d\033[0m\n", c2->id, c2->status); - } - } - } - - scf_loge("\033[34mc%ld, status: %d, pb->v: %lg, pe->v: %lg, diff: %lg, Von: %lg, Voff: %lg\033[0m\n", - c->id, c->status, pb->v, pe->v, pb->v - pe->v, Von, Voff); - return 1; -} - -int __ses_path_va_transistor(ScfEfunction* f, ses_path_t* path) -{ - ScfEcomponent* c; - ScfEline* el; - ScfEpin* p0; - ScfEpin* pj; - - ScfEpin* p; - ScfEpin* pc; - ScfEpin* pb; - - int i; - int j = path->pins->size - 1; - - p0 = path->pins->data[0]; - pj = path->pins->data[j]; - - el = f->elines[p0->lid]; - p0->v = el->v; - - el = f->elines[pj->lid]; - pj->v = el->v; - - for (i = path->pins->size - 1; i >= 0; i--) { - pc = path->pins->data[i]; - pj = path->pins->data[j]; - - double v; - double a; - double pr; - double _pr; - - c = f->components[pc->cid]; - - scf_logd("i: %d, c%ldp%ld--c%ldp%ld, pc->v: %lg, pc->a: %lg\n", i, p0->cid, p0->id, pc->cid, pc->id, pc->v, pc->a); - - if (SCF_EDA_NPN != c->type || SCF_EDA_NPN_C != pc->id) { - - if (j < path->pins->size - 1) { - pc->a = pj->a; - - if (pc->lid != pj->lid) { - __ses_path_pr(f, path, i, j, NULL, &pr); - - ses_ir_u(&v, NULL, pj->a, 0, pr, 0); - - pc->v = p0->v - v; - - if (path->childs) - __ses_path_split_i(f, path, i, j, pj->a, &pc->a); - - } else - pc->v = pj->v; - - j = i; - } - continue; - } - - if (!pc->aconst) - break; - - pb = c->pins[SCF_EDA_NPN_B]; - pc->a = pc->hfe * pb->a; - - __ses_path_pr(f, path, 0, i, NULL, &pr); - - ses_ir_u(&v, NULL, pc->a, 0, pr, 0); - - 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, pj: c%ldp%ld->v: %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, pj->cid, pj->id, pj->v); - - if (pc->v < pj->v) { - v = p0->v - pj->v; - - __ses_path_pr(f, path, 0, j, NULL, &_pr); - - ses_ur_i(&a, NULL, v, 0, _pr, 0); - - if (path->childs) - __ses_path_split_i(f, path, 0, j, a, &a); - - ses_ir_u(&v, NULL, a, 0, pr, 0); - - pc->v = p0->v - v; - pc->a = a; - - scf_logi("i: %d, c%ldp%ld--c%ldp%ld, v: %lg, pc->v: %lg, pc->a: %lg, pr: %lg, _pr: %lg pc->pr: %lg\n", - i, p0->cid, p0->id, pc->cid, pc->id, v, pc->v, pc->a, pr, _pr, pc->pr); - } - - el = f->elines[pc->lid]; - el->v = pc->v; - - scf_logw("i: %d, c%ldp%ld--c%ldp%ld, v: %lg, pc->v: %lg, pc->a: %lg, pr: %lg, pc->dr: %lg\n", - i, p0->cid, p0->id, pc->cid, pc->id, v, pc->v, pc->a, pr, pc->dr); - - a = pc->a; - - if (path->childs) { - __ses_path_split_i(f, path, i, j, a, &pc->a); - - if (i > 0) { - p = path->pins->data[i - 1]; - p->a = a; - p->v = el->v; - - __ses_path_split_i(f, path, 0, i - 1, a, &p->a); - } - } else - p0->a = a; - - __ses_path_dr_transistor(f, path, i, j); - - scf_loge("i: %d, c%ldp%ld--c%ldp%ld, v: %lg, pc->v: %lg, pc->a: %lg, pr: %lg, pc->dr: %lg\n\n", - i, p0->cid, p0->id, pc->cid, pc->id, v, pc->v, pc->a, pr, pc->dr); - - j = i; - } - - return 0; -} - -static int ses_path_va_transistor(ScfEfunction* f, ses_path_t* path) -{ - ses_path_t* child; - ScfEcomponent* B; - ScfEpin* p0; - ScfEpin* p1; - ScfEpin* Bp; - ScfEpin* Bn; - - size_t i; - size_t j; - size_t k; - - if (!path || path->pins->size < 2) - return -EINVAL; - - if (2 == path->pins->size) - return 0; - - B = f->components[0]; - Bp = B->pins[SCF_EDA_Battery_POS]; - Bn = B->pins[SCF_EDA_Battery_NEG]; - - p0 = path->pins->data[0]; - p1 = path->pins->data[path->pins->size - 1]; - - __ses_path_jr(f, path); - - int ret = __ses_path_va_transistor(f, path); - if (ret < 0) - return ret; - - if (path->childs) { - for (j = 0; j < path->childs->size; j++) { - child = path->childs->data[j]; - - ret = ses_path_va_transistor(f, child); - if (ret < 0) - return ret; - } - } - - return 0; -} - -static int _va_transistor_handler(ScfEfunction* f, int64_t ns, int64_t count, ses_ctx_t* ctx) -{ - ses_path_t* path; - - int i; - - for (i = 0; i < ctx->paths->size; i++) { - path = ctx->paths->data[i]; - - scf_logi("i: %d, path->index: %d\n", i, path->index); - - int ret = ses_path_va_transistor(f, path); - if (ret < 0) - return ret; - - printf("\n"); - } - - return 0; -} - -ses_step_t ses_step_va_transistor = -{ - .name = "va_transistor", - - .handler = _va_transistor_handler, -}; diff --git a/ses_steps.c b/ses_steps.c index 161450f..a269c8d 100644 --- a/ses_steps.c +++ b/ses_steps.c @@ -3,13 +3,10 @@ extern ses_step_t ses_step_battery; extern ses_step_t ses_step_dc_input; -//extern ses_step_t ses_step_ac_start; extern ses_step_t ses_step_dc_diode; -extern ses_step_t ses_step_dc_transistor; - -//extern ses_step_t ses_step_ac_transistor; -//extern ses_step_t ses_step_ac_diode; +extern ses_step_t ses_step_dc_npn; +extern ses_step_t ses_step_dc_pnp; extern ses_step_t ses_step_topo; @@ -24,7 +21,6 @@ extern ses_step_t ses_step_va_nodes; extern ses_step_t ses_step_va_capacitor; extern ses_step_t ses_step_a_stat; -extern ses_step_t ses_step_a_balance; extern ses_step_t ses_step_output; extern ses_step_t ses_step_simplify; @@ -41,16 +37,13 @@ static ses_step_t* ses_steps_0[] = static ses_step_t* ses_steps_1[] = { &ses_step_dc_diode, - &ses_step_dc_transistor, + &ses_step_dc_npn, + &ses_step_dc_pnp, &ses_step_topo, -// &ses_step_jr, - &ses_step_va_diode, - &ses_step_va_transistor, -// &ses_step_jr, &ses_step_va, &ses_step_status, }; @@ -58,9 +51,8 @@ static ses_step_t* ses_steps_1[] = static ses_step_t* ses_steps_2[] = { &ses_step_open, -// &ses_step_simplify2, &ses_step_va_nodes, - &ses_step_va_capacitor, +// &ses_step_va_capacitor, // &ses_step_a_stat, diff --git a/ses_utils.c b/ses_utils.c index a9231e9..a9ba53e 100644 --- a/ses_utils.c +++ b/ses_utils.c @@ -98,8 +98,8 @@ void ses_edge_print(ses_edge_t* edge) printf(" "); printf(")"); - if (edge->npn_b) - printf(" b[%d]", edge->npn_b->index); + if (edge->edge_b) + printf(" b[%d]", edge->edge_b->index); printf("; "); } diff --git a/test/Makefile b/test/Makefile index 34d479e..a10716e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ #CFILES += main.c #CFILES += test.c -CFILES += fft.c +#CFILES += fft.c +CFILES += pnp.c CFILES += ../scf_eda_pack.c CFILES += ../pack/scf_pack.c diff --git a/test/pnp.c b/test/pnp.c new file mode 100644 index 0000000..8954480 --- /dev/null +++ b/test/pnp.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include"ses_core.h" + +int main(int argc, char* argv[]) +{ + ScfEcomponent* B; + + ScfEcomponent* R0; + ScfEcomponent* C0; + ScfEcomponent* T0; + + ScfEcomponent* R1; + ScfEcomponent* R2; + ScfEcomponent* R3; + ScfEcomponent* C1; + ScfEcomponent* C2; + ScfEcomponent* C3; + + ScfEcomponent* R4; + ScfEcomponent* R5; + + ScfEfunction* f; + ScfEboard* b; + + b = scf_eboard__alloc(); + f = scf_efunction__alloc("sin_oscillator"); + + EDA_INST_ADD_COMPONENT(f, B, SCF_EDA_Battery); + + B->pins[SCF_EDA_Battery_NEG]->flags = SCF_EDA_PIN_NEG; + B->pins[SCF_EDA_Battery_POS]->flags = SCF_EDA_PIN_POS; + + EDA_INST_ADD_COMPONENT(f, R0, SCF_EDA_Resistor); + EDA_INST_ADD_COMPONENT(f, C0, SCF_EDA_Capacitor); + EDA_INST_ADD_COMPONENT(f, T0, SCF_EDA_PNP); + + EDA_INST_ADD_COMPONENT(f, R1, SCF_EDA_Resistor); + EDA_INST_ADD_COMPONENT(f, R2, SCF_EDA_Resistor); + EDA_INST_ADD_COMPONENT(f, R3, SCF_EDA_Resistor); + EDA_INST_ADD_COMPONENT(f, C1, SCF_EDA_Capacitor); + EDA_INST_ADD_COMPONENT(f, C2, SCF_EDA_Capacitor); + EDA_INST_ADD_COMPONENT(f, C3, SCF_EDA_Capacitor); + + EDA_INST_ADD_COMPONENT(f, R4, SCF_EDA_Resistor); + EDA_INST_ADD_COMPONENT(f, R5, SCF_EDA_Resistor); + + EDA_PIN_ADD_PIN(B, SCF_EDA_Battery_POS, R0, 1); + EDA_PIN_ADD_PIN(R0, 1, C0, 1); + EDA_PIN_ADD_PIN(R0, 0, C0, 0); + EDA_PIN_ADD_PIN(R0, 0, T0, SCF_EDA_NPN_E); + EDA_PIN_ADD_PIN(T0, SCF_EDA_NPN_C, R5, 1); + EDA_PIN_ADD_PIN(R5, 0, B, SCF_EDA_Battery_NEG); + + EDA_PIN_ADD_PIN(B, SCF_EDA_Battery_POS, R4, 1); + EDA_PIN_ADD_PIN(R4, 0, R3, 1); + EDA_PIN_ADD_PIN(R3, 1, T0, SCF_EDA_NPN_B); + EDA_PIN_ADD_PIN(R3, 0, B, SCF_EDA_Battery_NEG); + + EDA_PIN_ADD_PIN(C1, 1, T0, SCF_EDA_NPN_C); + EDA_PIN_ADD_PIN(C1, 0, C2, 1); + EDA_PIN_ADD_PIN(C2, 0, C3, 1); + EDA_PIN_ADD_PIN(C3, 0, T0, SCF_EDA_NPN_B); + + EDA_PIN_ADD_PIN(C1, 0, R1, 1); + EDA_PIN_ADD_PIN(C2, 0, R2, 1); + EDA_PIN_ADD_PIN(R1, 0, B, SCF_EDA_Battery_NEG); + 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 = 150; + + 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; + C2->uf = 0.01; + C3->uf = 0.01; + C1->r = 1; + C2->r = 1; + C3->r = 1; + + scf_eboard__add_function(b, f); + + int len = 0; + uint8_t* buf = NULL; + + ScfEboard_pack(b, &buf, &len); + ScfEboard_free(b); + b = NULL; + + FILE* fp = fopen("./pnp_oscillator.cpk", "wb"); + if (!fp) + return -EINVAL; + + fwrite(buf, len, 1, fp); + fclose(fp); + + return 0; +}