From: ametama Date: Mon, 2 Feb 2026 01:39:20 +0000 (+0100) Subject: task: netlist preprocessing, reading of design score X-Git-Url: https://git.wafflesoft.org/?a=commitdiff_plain;h=f9d3f68e838030858829987e7e4cafa8db7f3f64;p=ngsolve.git task: netlist preprocessing, reading of design score --- diff --git a/src/main.c b/src/main.c index 88066d0..528b74f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "argph.h" @@ -11,9 +12,17 @@ typedef struct { int input_write; int output_read; int output_write; -} child_process; +} ngspice_process; -task_def task; +task_def taskg; + +char *macros = \ + "#define Minimize(expr) let __ngsolve_f=__ngsolve_f+expr\n" + "#define Maximize(expr) Minimize(-expr)\n" + "#define Constrain(expr) let __ngsolve_c=__ngsolve_c+expr\n" + "#define Lt(a, b) max(exp(a - b) - 1, 0)\n" + "#define Gt(a, b) Lt(b, a)\n" + "#define Band(v, lo, hi) Lt(lo, v) + Lt(v, hi)\n"; char *readfile(FILE *f) { if (f == NULL) return NULL; @@ -24,7 +33,6 @@ char *readfile(FILE *f) { fseek(f, 0, SEEK_SET); str = malloc(f_size + 1); for (size_t i = 0; i < f_size; i++) str[i] = (char) fgetc(f); - str[f_size] = '\0'; return str; } @@ -40,78 +48,101 @@ char *readstream(int fd) { return buf; } -void spawn_ngspice(child_process *chp) { +void load_netlist(task_def *task) { + FILE *netlist = fopen(taskg.netlist_file, "r"); + char *netlist_raw = readfile(netlist); + fclose(netlist); + int in[2]; + int out[2]; + pipe(in); + pipe(out); + pid_t p = fork(); + if (!p) { + close(in[1]); + close(out[0]); + dup2(in[0], STDIN_FILENO); + dup2(out[1], STDOUT_FILENO); + if (execlp("gcc", "gcc", "-E", "-P", "-x", "c", "-", NULL)) { + printf("ngsolve: FATAL EXCEPTION\n gcc invocation unsuccessful. Check that a working binary is added to PATH as `gcc`."); + exit(1); + } + } + close(in[0]); + close(out[1]); + dprintf(in[1], "%s\n%s", macros, netlist_raw); + free(netlist_raw); + close(in[1]); + task->netlist = readstream(out[0]); + close(out[0]); +} + +void spawn_ngspice(ngspice_process *chp) { if (pipe(&chp->input_read) || pipe(&chp->output_read)) { printf("ngsolve: FATAL EXCEPTION\n pipe creation unsuccessful."); exit(1); } pid_t p = fork(); if (!p) { - close(chp->input_write); // Used by parent. - close(chp->output_read); // Used by parent. - // Connect stdin to pipe in parent. + close(chp->input_write); + close(chp->output_read); + // STDOUT is not linked to chp->output_write as this + // would pollute the pipe with ngspice logs. dup2(chp->input_read, STDIN_FILENO); // Convert to an ngspice process; - // execlp does not (!) return to caller. + // execlp does not (!) return to caller if successful. if (execlp("ngspice", "ngspice", "<&0", NULL)) { printf("ngsolve: FATAL EXCEPTION\n ngspice invocation unsuccessful. Check that a working binary is added to PATH as `ngspice`."); exit(1); } } - close(chp->input_read); // Used by child. - close(chp->output_write); // Used by child. + close(chp->input_read); + close(chp->output_write); chp->pid = p; } double fitness(double *x) { - child_process chp; + ngspice_process chp; spawn_ngspice(&chp); dprintf(chp.input_write, "ngsolve\n"); - for (size_t d = 0; d < task.dvarc; d++) - dprintf(chp.input_write, ".PARAM %s=%f\n", task.dvars[d].symbol, x[d]); - dprintf(chp.input_write, "%s\n.CONTROL\necho \"", task.netlist); - for (size_t d = 0; d < task.mvarc; d++) - dprintf(chp.input_write, "$&%s ", task.mvars[d].symbol); - dprintf(chp.input_write, "\" >&%d\nexec %d>&-\n.ENDC\n.END\n" /* Done writing (writes EOF to parent on chp.output_write). */, chp.output_write, chp.output_write); + for (size_t d = 0; d < taskg.dvarc; d++) + dprintf(chp.input_write, ".PARAM %s=%f\n", taskg.dvars[d].symbol, x[d]); + // Note: ngspice manual specifies input files have to end on ".END\n". + // This seems to not be enforced, so this control statement can be appended after it. + dprintf(chp.input_write, "*%s\n.CONTROL\necho \"$&__ngsolve_c $&__ngsolve_f\" >&%d\nexec %d>&-\n.ENDC\n", taskg.netlist, chp.output_write, chp.output_write); close(chp.input_write); // Done writing (writes EOF to ngspice on chp.input_write). - // Measurements are retrieved here to calculate fitness. - // Calculating fitness using statements added to the input - // to ngspice has been considered but the input language - // appears to be too weak or buggy to do this sensibly. - double *mvars = malloc(sizeof(double) * task.mvarc); - char *mvar_output = readstream(chp.output_read); - char *pos = mvar_output; - for (int d = 0; d < task.mvarc; d++) mvars[d] = strtod(pos, &pos); - free(mvar_output); - // TODO: add constraints to task. - // TODO: calculate fitness. - free(mvars); + char *outp = readstream(chp.output_read); + close(chp.output_read); + char *pos = outp; + double constraints = strtod(pos, &pos); + double fitness = strtod(pos, &pos); + free(outp); + // TODO: convert this into first finding valid + // area (constraints) and then optimizing for fitness. + return constraints + fitness; } void optimize() { - double *sample_range_min = malloc(sizeof(double) * task.dvarc); - double *sample_range_max = malloc(sizeof(double) * task.dvarc); - for (size_t d = 0; d < task.dvarc; d++) { - sample_range_min[d] = task.dvars[d].sample_min; - sample_range_max[d] = task.dvars[d].sample_max; + double *sample_range_min = malloc(sizeof(double) * taskg.dvarc); + double *sample_range_max = malloc(sizeof(double) * taskg.dvarc); + for (size_t d = 0; d < taskg.dvarc; d++) { + sample_range_min[d] = taskg.dvars[d].sample_min; + sample_range_max[d] = taskg.dvars[d].sample_max; } - FILE *netlist = fopen(task.netlist_file, "r"); - task.netlist = readfile(netlist); - fclose(netlist); + load_netlist(&taskg); cgo_de_parameters par = { - task.dvarc, - task.agentc, + taskg.dvarc, + taskg.agentc, sample_range_min, sample_range_max, fitness, 0.9, 0.8 }; - double *res = malloc(sizeof(double) * task.dvarc); + double *res = malloc(sizeof(double) * taskg.dvarc); cgo_de(&par, res); printf("ngsolve: converged at x=("); - for (size_t d = 0; d < task.dvarc - 1; d++) printf("%s=%f, ", task.dvars[d].symbol, res[d]); - printf("%s=%f) with f(x)=%f\n", task.dvars[task.dvarc - 1].symbol, res[task.dvarc - 1], fitness(res)); + for (size_t d = 0; d < taskg.dvarc - 1; d++) printf("%s=%f, ", taskg.dvars[d].symbol, res[d]); + printf("%s=%f) with f(x)=%f\n", taskg.dvars[taskg.dvarc - 1].symbol, res[taskg.dvarc - 1], fitness(res)); } int main(int argc, char *argv[]) { diff --git a/test.ch b/test.ch new file mode 100644 index 0000000..fb348f3 --- /dev/null +++ b/test.ch @@ -0,0 +1,3 @@ +#define A 123 + +A