embedded raw file storage

This commit is contained in:
Stefan Frederik 2022-01-21 19:17:43 +01:00
parent 609d0d0fdf
commit 320ad6e2aa
7 changed files with 1732 additions and 287 deletions

View File

@ -40,7 +40,7 @@ static int waves_selected(int event, int key, int state, int button)
r = &xctx->rect[GRIDLAYER][i];
if(!(r->flags & 1) ) continue;
if( (xctx->ui_state & GRAPHPAN) ||
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 40, r->y1 + 20, r->x2 - 30, r->y2 - 10) ) {
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 20, r->y1 + 20, r->x2 - 30, r->y2 - 10) ) {
is_inside = 1;
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
}

View File

@ -1478,216 +1478,6 @@ void drawtemprect(GC gc, int what, double rectx1,double recty1,double rectx2,dou
}
}
/* read the binary portion of a ngspice raw simulation file
* data layout in memory arranged to maximize cache locality
* when looking up data
*/
void read_binary_block(FILE *fd)
{
int p, v;
double *tmp;
size_t size = 0;
int offset = 0;
for(p = 0 ; p < xctx->graph_datasets; p++) {
size += xctx->graph_nvars * xctx->graph_npoints[p];
offset += xctx->graph_npoints[p];
}
/* read buffer */
tmp = my_calloc(1405, xctx->graph_nvars, sizeof(double *));
/* allocate storage for binary block */
if(!xctx->graph_values) xctx->graph_values = my_calloc(118, xctx->graph_nvars, sizeof(SPICE_DATA *));
for(p = 0 ; p < xctx->graph_nvars; p++) {
my_realloc(372, &xctx->graph_values[p], (size + xctx->graph_npoints[xctx->graph_datasets]) * sizeof(double));
}
/* read binary block */
for(p = 0; p < xctx->graph_npoints[xctx->graph_datasets]; p++) {
if(fread(tmp, sizeof(double), xctx->graph_nvars, fd) != xctx->graph_nvars) {
dbg(0, "Warning: binary block is not of correct size\n");
}
/* assign to xschem struct, memory aligned per variable, for cache locality */
for(v = 0; v < xctx->graph_nvars; v++) {
xctx->graph_values[v][offset + p] = tmp[v];
}
}
my_free(1406, &tmp);
}
/* parse ascii raw header section:
* returns: 1 if dataset and variables were read.
* 0 if transient sim dataset not found
* -1 on EOF
* Typical ascii header of raw file looks like:
*
* Title: **.subckt poweramp
* Date: Thu Nov 21 18:36:25 2019
* Plotname: Transient Analysis
* Flags: real
* No. Variables: 158
* No. Points: 90267
* Variables:
* 0 time time
* 1 v(net1) voltage
* 2 v(vss) voltage
* ...
* ...
* 155 i(v.x1.vd) current
* 156 i(v0) current
* 157 i(v1) current
* Binary:
*/
int read_dataset(FILE *fd)
{
int variables = 0, i, done_points = 0;
char line[PATH_MAX], varname[PATH_MAX];
char *ptr;
int sim_type = 0; /* 1: transient, 2: dc, 4: ... */
int done_header = 0;
int exit_status = 0;
while((ptr = fgets(line, sizeof(line), fd)) ) {
/* after this line comes the binary blob made of nvars * npoints * sizeof(double) bytes */
if(!strcmp(line, "Binary:\n")) {
int npoints = xctx->graph_npoints[xctx->graph_datasets];
if(sim_type) {
done_header = 1;
read_binary_block(fd);
dbg(1, "read_dataset(): read binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints);
xctx->graph_datasets++;
exit_status = 1;
} else {
dbg(1, "read_dataset(): skip binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints);
fseek(fd, xctx->graph_nvars * npoints * sizeof(double), SEEK_CUR); /* skip binary block */
}
done_points = 0;
}
else if(!strncmp(line, "Plotname: Transient Analysis", 28)) {
if(sim_type && sim_type != 1) sim_type = 0;
else sim_type = 1;
}
else if(!strncmp(line, "Plotname: DC transfer characteristic", 36)) {
if(sim_type && sim_type != 2) sim_type = 0;
else sim_type = 2;
}
else if(!strncmp(line, "Plotname:", 9)) {
sim_type = 0;
}
/* points and vars are needed for all sections (also ones we are not interested in)
* to skip binary blobs */
else if(!strncmp(line, "No. of Data Rows :", 18)) {
/* array of number of points of datasets (they are of varialbe length) */
my_realloc(1414, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int));
sscanf(line, "No. of Data Rows : %d", &xctx->graph_npoints[xctx->graph_datasets]);
done_points = 1;
}
else if(!strncmp(line, "No. Variables:", 14)) {
sscanf(line, "No. Variables: %d", &xctx->graph_nvars);
}
else if(!done_points && !strncmp(line, "No. Points:", 11)) {
my_realloc(1415, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int));
sscanf(line, "No. Points: %d", &xctx->graph_npoints[xctx->graph_datasets]);
}
if(!done_header && variables) {
/* get the list of lines with index and node name */
if(!xctx->graph_names) xctx->graph_names = my_calloc(426, xctx->graph_nvars, sizeof(char *));
sscanf(line, "%d %s", &i, varname); /* read index and name of saved waveform */
xctx->graph_names[i] = my_malloc(415, strlen(varname) + 1);
strcpy(xctx->graph_names[i], varname);
/* use hash table to store index number of variables */
int_hash_lookup(xctx->raw_table, xctx->graph_names[i], i, XINSERT_NOREPLACE);
dbg(1, "read_dataset(): get node list -> names[%d] = %s\n", i, xctx->graph_names[i]);
}
/* after this line comes the list of indexes and associated nodes */
if(sim_type && !strncmp(line, "Variables:", 10)) {
variables = 1 ;
}
}
dbg(1, "read_dataset(): datasets=%d, last npoints=%d, nvars=%d\n",
xctx->graph_datasets, xctx->graph_npoints[xctx->graph_datasets-1], xctx->graph_nvars);
return exit_status;
}
void free_rawfile(int dr)
{
int i;
int deleted = 0;
if(xctx->graph_names) {
deleted = 1;
for(i = 0 ; i < xctx->graph_nvars; i++) {
my_free(510, &xctx->graph_names[i]);
}
my_free(968, &xctx->graph_names);
}
if(xctx->graph_values) {
deleted = 1;
for(i = 0 ; i < xctx->graph_nvars; i++) {
my_free(512, &xctx->graph_values[i]);
}
my_free(528, &xctx->graph_values);
}
if(xctx->graph_npoints) my_free(1413, &xctx->graph_npoints);
if(xctx->raw_schname) my_free(1393, &xctx->raw_schname);
xctx->graph_datasets = 0;
xctx->graph_nvars = 0;
int_hash_free(xctx->raw_table);
if(deleted && dr) draw();
}
/* read a ngspice raw file (with data portion in binary format) */
int read_rawfile(const char *f)
{
int res = 0;
FILE *fd;
if(xctx->graph_values || xctx->graph_npoints || xctx->graph_nvars || xctx->graph_datasets) {
dbg(0, "read_rawfile(): must clear current raw file before loading new\n");
return 0;
}
fd = fopen(f, fopen_read_mode);
if(fd) {
if((res = read_dataset(fd)) == 1) {
dbg(0, "Raw file data read\n");
my_strdup2(1394, &xctx->raw_schname, xctx->sch[xctx->currsch]);
draw();
} else {
dbg(0, "read_rawfile(): no useful data found\n");
}
fclose(fd);
return res;
}
dbg(0, "read_rawfile(): failed to open file %s for reading\n", f);
return 0;
}
int get_raw_index(const char *node)
{
char vnode[300];
Int_hashentry *entry;
if(xctx->graph_values) {
entry = int_hash_lookup(xctx->raw_table, node, 0, XLOOKUP);
if(!entry) {
my_snprintf(vnode, S(vnode), "v(%s)", node);
entry = int_hash_lookup(xctx->raw_table, vnode, 0, XLOOKUP);
}
if(entry) return entry->value;
}
return -1;
}
double get_raw_value(int dataset, int idx, int point)
{
int i, ofs;
ofs = 0;
if(xctx->graph_values) {
for(i = 0; i < dataset; i++) {
ofs += xctx->graph_npoints[i];
}
return xctx->graph_values[idx][ofs + point];
}
return 0.0;
}
/* round to closest 1e-ee. 2e-ee, 5e-ee
* example: delta = 0.234 --> 0.2
* 3.23 --> 5
@ -2321,6 +2111,37 @@ static void show_node_measures(int measure_p, double measure_x, double measure_p
} /* if(measure_p >= 0) */
}
int embed_rawfile(const char *rawfile)
{
int res = 0;
size_t len;
char *ptr;
if(xctx->lastsel==1 && xctx->sel_array[0].type==ELEMENT) {
xInstance *i = &xctx->inst[xctx->sel_array[0].n];
xctx->push_undo();
set_modify(1);
ptr = base64_from_file(rawfile, &len);
my_strdup2(1466, &i->prop_ptr, subst_token(i->prop_ptr, "spice_data", ptr));
my_free(1481, &ptr);
}
return res;
}
int read_embedded_rawfile(void)
{
int res = 0;
if(xctx->lastsel==1 && xctx->sel_array[0].type==ELEMENT) {
xInstance *i = &xctx->inst[xctx->sel_array[0].n];
const char *b64_spice_data;
if(i->prop_ptr && (b64_spice_data = get_tok_value(i->prop_ptr, "spice_data", 0))[0]) {
res = read_rawfile_from_attr(b64_spice_data, strlen(b64_spice_data));
}
}
return res;
}
/* flags:
* 1: do final XCopyArea (copy 2nd buffer areas to screen)
* If draw_graph_all() is called from draw() no need to do XCopyArea, as draw() does it already.
@ -2660,10 +2481,8 @@ int draw_images_all(void)
cairo_surface_write_to_png_stream(emb_ptr->image, png_writer, &closure);
dbg(1, "draw_images_all(): length3 = %d\n", closure.pos);
/* put base64 encoded data to rect image_data attrinute */
image_data = base64_encode(closure.buffer, closure.pos, &olength);
image_data = base64_encode(closure.buffer, closure.pos, &olength, 0);
my_free(1468, &closure.buffer);
my_realloc(1466, &image_data, olength + 1);
image_data[olength] = '\0';
my_strdup2(1473, &r->prop_ptr, subst_token(r->prop_ptr, "image_data", image_data));
my_free(1474, &image_data);
} else {

View File

@ -29,7 +29,7 @@
#undef BASE64_BREAK_LINES
/* Caller should free returned buffer */
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) {
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length, int brk) {
static const char b64_enc[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
@ -45,8 +45,10 @@ char *base64_encode(const unsigned char *data, size_t input_length, size_t *outp
size_t alloc_length;
char *encoded_data;
int octet_a, octet_b, octet_c, triple;
*output_length = (1 + ((4 * ((input_length + 2) / 3)) / 4096)) * 4096;
alloc_length = *output_length;
*output_length = 4 * ((input_length + 2) / 3);
alloc_length = (1 + (*output_length / 4096)) * 4096;
encoded_data = my_malloc(1469, alloc_length);
if (encoded_data == NULL) return NULL;
cnt = 0;
@ -61,12 +63,10 @@ char *base64_encode(const unsigned char *data, size_t input_length, size_t *outp
alloc_length += 4096;
my_realloc(1471, &encoded_data, alloc_length);
}
#ifdef BASE64_BREAK_LINES
if((cnt & 31) == 0) {
if(brk && ( (cnt & 31) == 0) ) {
*output_length += 1;
encoded_data[j++] = '\n';
}
#endif
encoded_data[j++] = b64_enc[(triple >> 18) & 0x3F];
encoded_data[j++] = b64_enc[(triple >> 12) & 0x3F];
encoded_data[j++] = b64_enc[(triple >> 6) & 0x3F];
@ -75,6 +75,7 @@ char *base64_encode(const unsigned char *data, size_t input_length, size_t *outp
}
for (i = 0; i < mod_table[input_length % 3]; i++)
encoded_data[*output_length - 1 - i] = '=';
encoded_data[*output_length] = '\0'; /* add \0 at end so it can be used as a regular char string */
return encoded_data;
}
@ -130,6 +131,270 @@ unsigned char *base64_decode(const char *data, size_t input_length, size_t *outp
return decoded_data;
}
/* SPICE RAWFILE ROUTINES */
/* read the binary portion of a ngspice raw simulation file
* data layout in memory arranged to maximize cache locality
* when looking up data
*/
static void read_binary_block(FILE *fd)
{
int p, v;
double *tmp;
size_t size = 0;
int offset = 0;
for(p = 0 ; p < xctx->graph_datasets; p++) {
size += xctx->graph_nvars * xctx->graph_npoints[p];
offset += xctx->graph_npoints[p];
}
/* read buffer */
tmp = my_calloc(1405, xctx->graph_nvars, sizeof(double *));
/* allocate storage for binary block */
if(!xctx->graph_values) xctx->graph_values = my_calloc(118, xctx->graph_nvars, sizeof(SPICE_DATA *));
for(p = 0 ; p < xctx->graph_nvars; p++) {
my_realloc(372, &xctx->graph_values[p], (size + xctx->graph_npoints[xctx->graph_datasets]) * sizeof(double));
}
/* read binary block */
for(p = 0; p < xctx->graph_npoints[xctx->graph_datasets]; p++) {
if(fread(tmp, sizeof(double), xctx->graph_nvars, fd) != xctx->graph_nvars) {
dbg(0, "Warning: binary block is not of correct size\n");
}
/* assign to xschem struct, memory aligned per variable, for cache locality */
for(v = 0; v < xctx->graph_nvars; v++) {
xctx->graph_values[v][offset + p] = tmp[v];
}
}
my_free(1406, &tmp);
}
/* parse ascii raw header section:
* returns: 1 if dataset and variables were read.
* 0 if transient sim dataset not found
* -1 on EOF
* Typical ascii header of raw file looks like:
*
* Title: **.subckt poweramp
* Date: Thu Nov 21 18:36:25 2019
* Plotname: Transient Analysis
* Flags: real
* No. Variables: 158
* No. Points: 90267
* Variables:
* 0 time time
* 1 v(net1) voltage
* 2 v(vss) voltage
* ...
* ...
* 155 i(v.x1.vd) current
* 156 i(v0) current
* 157 i(v1) current
* Binary:
*/
static int read_dataset(FILE *fd)
{
int variables = 0, i, done_points = 0;
char line[PATH_MAX], varname[PATH_MAX];
char *ptr;
int sim_type = 0; /* 1: transient, 2: dc, 4: ... */
int done_header = 0;
int exit_status = 0;
while((ptr = fgets(line, sizeof(line), fd)) ) {
/* after this line comes the binary blob made of nvars * npoints * sizeof(double) bytes */
if(!strcmp(line, "Binary:\n")) {
int npoints = xctx->graph_npoints[xctx->graph_datasets];
if(sim_type) {
done_header = 1;
read_binary_block(fd);
dbg(1, "read_dataset(): read binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints);
xctx->graph_datasets++;
exit_status = 1;
} else {
dbg(1, "read_dataset(): skip binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints);
fseek(fd, xctx->graph_nvars * npoints * sizeof(double), SEEK_CUR); /* skip binary block */
}
done_points = 0;
}
else if(!strncmp(line, "Plotname: Transient Analysis", 28)) {
if(sim_type && sim_type != 1) sim_type = 0;
else sim_type = 1;
}
else if(!strncmp(line, "Plotname: DC transfer characteristic", 36)) {
if(sim_type && sim_type != 2) sim_type = 0;
else sim_type = 2;
}
else if(!strncmp(line, "Plotname:", 9)) {
sim_type = 0;
}
/* points and vars are needed for all sections (also ones we are not interested in)
* to skip binary blobs */
else if(!strncmp(line, "No. of Data Rows :", 18)) {
/* array of number of points of datasets (they are of varialbe length) */
my_realloc(1414, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int));
sscanf(line, "No. of Data Rows : %d", &xctx->graph_npoints[xctx->graph_datasets]);
done_points = 1;
}
else if(!strncmp(line, "No. Variables:", 14)) {
sscanf(line, "No. Variables: %d", &xctx->graph_nvars);
}
else if(!done_points && !strncmp(line, "No. Points:", 11)) {
my_realloc(1415, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int));
sscanf(line, "No. Points: %d", &xctx->graph_npoints[xctx->graph_datasets]);
}
if(!done_header && variables) {
/* get the list of lines with index and node name */
if(!xctx->graph_names) xctx->graph_names = my_calloc(426, xctx->graph_nvars, sizeof(char *));
sscanf(line, "%d %s", &i, varname); /* read index and name of saved waveform */
xctx->graph_names[i] = my_malloc(415, strlen(varname) + 1);
strcpy(xctx->graph_names[i], varname);
/* use hash table to store index number of variables */
int_hash_lookup(xctx->raw_table, xctx->graph_names[i], i, XINSERT_NOREPLACE);
dbg(1, "read_dataset(): get node list -> names[%d] = %s\n", i, xctx->graph_names[i]);
}
/* after this line comes the list of indexes and associated nodes */
if(sim_type && !strncmp(line, "Variables:", 10)) {
variables = 1 ;
}
}
dbg(1, "read_dataset(): datasets=%d, last npoints=%d, nvars=%d\n",
xctx->graph_datasets, xctx->graph_npoints[xctx->graph_datasets-1], xctx->graph_nvars);
return exit_status;
}
void free_rawfile(int dr)
{
int i;
int deleted = 0;
if(xctx->graph_names) {
deleted = 1;
for(i = 0 ; i < xctx->graph_nvars; i++) {
my_free(510, &xctx->graph_names[i]);
}
my_free(968, &xctx->graph_names);
}
if(xctx->graph_values) {
deleted = 1;
for(i = 0 ; i < xctx->graph_nvars; i++) {
my_free(512, &xctx->graph_values[i]);
}
my_free(528, &xctx->graph_values);
}
if(xctx->graph_npoints) my_free(1413, &xctx->graph_npoints);
if(xctx->raw_schname) my_free(1393, &xctx->raw_schname);
xctx->graph_datasets = 0;
xctx->graph_nvars = 0;
int_hash_free(xctx->raw_table);
if(deleted && dr) draw();
}
/* caller must free returned pointer */
char *base64_from_file(const char *f, size_t *length)
{
FILE *fd;
struct stat st;
unsigned char *s = NULL;
char *b64s = NULL;
size_t len;
if (stat(f, &st) == 0 && ( (st.st_mode & S_IFMT) == S_IFREG) ) {
len = st.st_size;
fd = fopen(f, fopen_read_mode);
if(fd) {
s = my_malloc(1475, len);
fread(s, len, 1, fd);
fclose(fd);
b64s = base64_encode(s, len, length, 1);
my_free(1477, &s);
}
else {
dbg(0, "base64_from_file(): failed to open file %s for reading\n", f);
}
}
return b64s;
}
int read_rawfile_from_attr(const char *b64s, size_t length)
{
int res = 0;
unsigned char *s;
size_t decoded_length;
FILE *fd;
char *tmp_filename;
if(xctx->graph_values || xctx->graph_npoints || xctx->graph_nvars || xctx->graph_datasets) {
dbg(0, "read_rawfile(_from_attr(): must clear current raw file before loading new\n");
return res;
}
if( (fd = open_tmpfile("rawfile_", &tmp_filename)) ) {
s = base64_decode(b64s, length, &decoded_length);
fwrite(s, decoded_length, 1, fd);
fclose(fd);
my_free(1479, &s);
res = read_rawfile(tmp_filename);
unlink(tmp_filename);
} else {
dbg(0, "read_rawfile_from_attr(): failed to open file %s for reading\n", tmp_filename);
}
return res;
}
/* read a ngspice raw file (with data portion in binary format) */
int read_rawfile(const char *f)
{
int res = 0;
FILE *fd;
if(xctx->graph_values || xctx->graph_npoints || xctx->graph_nvars || xctx->graph_datasets) {
dbg(0, "read_rawfile(): must clear current raw file before loading new\n");
return res;
}
fd = fopen(f, fopen_read_mode);
if(fd) {
if((res = read_dataset(fd)) == 1) {
dbg(0, "Raw file data read\n");
my_strdup2(1394, &xctx->raw_schname, xctx->sch[xctx->currsch]);
draw();
} else {
dbg(0, "read_rawfile(): no useful data found\n");
}
fclose(fd);
return res;
}
dbg(0, "read_rawfile(): failed to open file %s for reading\n", f);
return 0;
}
int get_raw_index(const char *node)
{
char vnode[300];
Int_hashentry *entry;
if(xctx->graph_values) {
entry = int_hash_lookup(xctx->raw_table, node, 0, XLOOKUP);
if(!entry) {
my_snprintf(vnode, S(vnode), "v(%s)", node);
entry = int_hash_lookup(xctx->raw_table, vnode, 0, XLOOKUP);
}
if(entry) return entry->value;
}
return -1;
}
double get_raw_value(int dataset, int idx, int point)
{
int i, ofs;
ofs = 0;
if(xctx->graph_values) {
for(i = 0; i < dataset; i++) {
ofs += xctx->graph_npoints[i];
}
return xctx->graph_values[idx][ofs + point];
}
return 0.0;
}
/* END SPICE RAWFILE ROUTINES */
/*
read an unknown xschem record usually like:
text {string} text {string}....

View File

@ -635,6 +635,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
else if(!strcmp(argv[1],"embed_rawfile"))
{
cmd_found = 1;
if(argc > 2) {
embed_rawfile(argv[2]);
}
Tcl_ResetResult(interp);
}
else if(!strcmp(argv[1],"enable_layers"))
{
cmd_found = 1;
@ -1778,7 +1786,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int i, p, no_of_pins;
cmd_found = 1;
if( (i = get_instance(argv[2])) < 0 ) {
Tcl_SetResult(interp, "xschem getprop: instance not found", TCL_STATIC);
Tcl_SetResult(interp, "xschem pinlist: instance not found", TCL_STATIC);
return TCL_ERROR;
}
no_of_pins= (xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER];
@ -2047,7 +2055,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
}
if(!strcmp(argv[1], "raw_read"))
{
cmd_found = 1;
@ -2061,7 +2068,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
Tcl_ResetResult(interp);
}
if(!strcmp(argv[1], "raw_read_from_attr"))
{
cmd_found = 1;
if(schematic_waves_loaded()) {
free_rawfile(1);
} else {
free_rawfile(0);
read_embedded_rawfile();
if(schematic_waves_loaded()) tclsetvar("rawfile_loaded", "1");
else tclsetvar("rawfile_loaded", "0");
}
Tcl_ResetResult(interp);
}
if(!strcmp(argv[1], "rebuild_connectivity"))
{
cmd_found = 1;
@ -2633,8 +2652,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(argv[1][0] == 't') {
if(!strcmp(argv[1],"test"))
{
size_t len;
char *s;
cmd_found = 1;
Tcl_ResetResult(interp);
if(argc > 2) {
Tcl_AppendResult(interp, (s = base64_from_file(argv[2], &len)), NULL);
my_free(1480, &s);
}
/* Tcl_ResetResult(interp); */
}
else if(!strcmp(argv[1],"toggle_colorscheme"))

View File

@ -1000,19 +1000,23 @@ extern int cli_opt_load_initfile;
extern Xschem_ctx *xctx;
/* FUNCTIONS */
extern int embed_rawfile(const char *rawfile);
extern int read_rawfile_from_attr(const char *b64s, size_t length);
extern int read_embedded_rawfile(void);
extern char *base64_from_file(const char *f, size_t *length);
extern int set_rect_flags(xRect *r);
extern int set_rect_extraptr(int what, xRect *drptr, xRect *srptr);
extern unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
extern char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length);
extern char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length, int brk);
extern int get_raw_index(const char *node);
extern void free_rawfile(int dr);
extern int read_rawfile(const char *f);
extern double get_raw_value(int dataset, int idx, int point);
extern int schematic_waves_loaded(void);
extern void draw_graph(int i, int flags, Graph_ctx *gr);
extern void draw_graph_all(int flags);
extern int draw_images_all(void);
extern void setup_graph_data(int i, const int flags, int skip, Graph_ctx *gr);
extern void free_rawfile(int dr);
extern int read_rawfile(const char *f);
extern double timer(int start);
extern void enable_layers(void);
extern void set_snap(double);

File diff suppressed because one or more lines are too long

View File

@ -121,14 +121,11 @@ N 860 -470 860 -430 { lab=#net3}
N 960 -650 980 -650 { lab=#net4}
N 310 -450 345 -450 {lab=PANEL}
C {title.sym} 160 -40 0 0 {name=l1 author="Stefan Schippers" net_name=true}
C {code_shown.sym} 245 -245 0 0 {name=CONTROL value="* .control
* save all
* tran 5n 500u uic
* write led_driver.raw
* .endc
.option savecurrents
*.save all
.tran 20n 200u uic
C {code_shown.sym} 245 -245 0 0 {name=CONTROL value=".control
save v(panel) v(sw) v(led) i(vpanel)
tran 1u 200u uic
write solar_panel.raw
.endc
* .dc VP 0 21 0.01
" net_name=true}
C {code.sym} 15 -225 0 0 {name=MODELS value=".MODEL DIODE D(IS=1.139e-08 RS=0.99 CJO=9.3e-12 VJ=1.6 M=0.411 BV=30 EG=0.7 )