embedded raw file storage
This commit is contained in:
parent
609d0d0fdf
commit
320ad6e2aa
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
245
src/draw.c
245
src/draw.c
|
|
@ -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 {
|
||||
|
|
|
|||
277
src/save.c
277
src/save.c
|
|
@ -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}....
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
|
|
|
|||
10
src/xschem.h
10
src/xschem.h
|
|
@ -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
|
|
@ -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 )
|
||||
|
|
|
|||
Loading…
Reference in New Issue