📄 loadsig.c
字号:
/* * loadsig.c: retrieval of HSPICE data into MATLAB * written by Michael Perrott while at Silicon * Laboratories. This code leveraged the work of * Stephen G. Tell (i.e., his Gwave viewer) to * develop the Hspice loading functions. At this * point, the code here has little similarity to the * routines he provided, but many thanks to Stephen * for providing enough info to get started. * For those wishing to modify this code - good luck! * Unfortunatley, it is quite "hacked" due * to the fact that the actual binary format of Hspice output * was never provided (i.e., I simply updated the * code each time a new issue was found), and due to the * fact that I had little time to develop it. However, * after years of use, it's pretty solid now. * * To compile this code into a mex file for Matlab, simply * run Matlab in the directory that loadsig.c is contained * and then type: * mex loadsig.c * You'll then have a loadsig mex function for whatever * computer (i.e., Sun, Linux, Windows) that you're running * on at the time. * * I do ask for one thing for those that use this code - please * keep my name and Silicon Labs attached to it when the user * first executes it (as currently done). I am not particularly * interested in getting anything for this package other then * recognition, but I do want that since this was a nontrivial * amount of work. Of course, if you want to throw money at me, * I'm happy to accomodate you. :) - Michael Perrott 6/3/03 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the MxFree * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#define MAX_NAME_LENGTH 1000#define MAX_HEADER_BLOCKS 100#define TIME 1#define FREQUENCY 4#define VOLTAGE 2#define CURRENT 3#define UNKNOWN 0#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <float.h>#include "mat.h"#include "mex.h" typedef struct { char **signal_name, **sweep_name; int *signal_type; /* i.e. FREQ, TIME, VOLTAGE ... */ int num_signals, num_data_rows, num_data_cols, nauto; int current_column, cur_sweep, num_sweeps, num_sweep_vars, num_sweep_names; int *signal_first_row,*signal_num_rows; float **signal_data, **sweep_data; int block_size;} SpiceData; int fread_float_values(char *simsource,float *fval, FILE *fp);size_t fread_int_values(char *simsource, unsigned int *ibuf, int size_of_block, FILE *fp);int hs_determine_variables(FILE *fp, SpiceData *sf, char *simsource);void hs_process_header(char *line, SpiceData *sf);int hs_read_column(FILE *fp, SpiceData *sf, char *simsource);SpiceData *init_SpiceData(int num_signals, int nauto, int num_data_rows, int num_data_cols, int num_sweeps, int num_sweep_vars, int num_sweep_names, int block_size);int hs_determine_num_data_rows(char *line, int num_signals, int nauto, int *ind_sig_type, int num_sweep_names, int *num_sweep_vars);SpiceData *hs_allocate_sf(FILE *fp, char *simsource);int hs_validate_column(FILE *fp, int num_data_rows, int current_column, int num_sweep_vars, int block_size, char *simsource, int col_count);void free_SpiceData(SpiceData *A);void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){SpiceData *sf;FILE *fp;int i,j,k,m,sweep_name_num;float val;/* char name[MAX_NAME_LENGTH],filename[MAX_NAME_LENGTH]; */char filename[MAX_NAME_LENGTH], simsource[MAX_NAME_LENGTH];mxArray *pa1;double *matData;const char *field_name[20] = {"name","data"};static first_run=0;/* mexPrintf("field_name = %s, %s\n",field_name[0],field_name[1]); */if (nrhs != 1) mexErrMsgTxt("Error: missing filename. Usage: x = loadsig('filename')");if (!mxIsChar(prhs[0])) mexErrMsgTxt("Error: filename must be a string");if (nlhs != 1) mexErrMsgTxt("Error: missing output variable. Usage: x = loadsig('filename')");mxGetString(prhs[0],filename,MAX_NAME_LENGTH);if (first_run == 0) { first_run = 1; mexPrintf("\n*********************************************************\n"); mexPrintf(" Hspice Toolbox for Matlab\n"); mexPrintf(" written by Michael Perrott (http://www-mtl.mit.edu/~perrott)\n"); mexPrintf(" while at Silicon Laboratories (http://www.silabs.com)\n"); mexPrintf(" Copyright (C) 1999 by Silicon Laboratories, Inc.\n"); mexPrintf(" This software is distributed under the terms of\n"); mexPrintf(" the GNU Public License (see the COPYING file\n"); mexPrintf(" for more details), and comes with no warranty or support\n"); mexPrintf("*********************************************************\n\n"); }if ((fp = fopen(filename,"rb")) == NULL) mexErrMsgTxt("Error: file can't be opened");sf = hs_allocate_sf(fp,simsource);/*mexPrintf("num_data_cols = %d, num_data_rows = %d, num_signals = %d\n", sf->num_data_cols, sf->num_data_rows, sf->num_signals);mexPrintf("current_col = %d\n",sf->current_column);*/if (sf == NULL) return;if (hs_determine_variables(fp,sf,simsource) == 0) return;/*mexPrintf("num_data_cols = %d, num_data_rows = %d, num_signals = %d\n", sf->num_data_cols, sf->num_data_rows, sf->num_signals);mexPrintf("current_col = %d\n",sf->current_column);*/for (k = 0; k < sf->num_signals; k++) { for (i = 0; sf->signal_name[k][i] != '\0'; i++) if (sf->signal_name[k][i] == '.' || sf->signal_name[k][i] == '(' || sf->signal_name[k][i] == ')' || sf->signal_name[k][i] == '+' || sf->signal_name[k][i] == '[' || sf->signal_name[k][i] == ']' || sf->signal_name[k][i] == '-' || sf->signal_name[k][i] == '*' || sf->signal_name[k][i] == '/' || sf->signal_name[k][i] == ',') sf->signal_name[k][i] = '_'; /* if (k == 0) sprintf(name,"i"); else sprintf(name,"d"); switch(sf->signal_type[k]) { case TIME: strcat(name,"t_"); break; case FREQUENCY: strcat(name,"f_"); break; case VOLTAGE: strcat(name,"v_"); break; case CURRENT: strcat(name,"i_"); break; default: strcat(name,"u_"); break; } strncat(name,sf->signal_name[k],MAX_NAME_LENGTH-3); sprintf(sf->signal_name[k],"%s",name); */ }/*for (i = 0; i < sf->num_signals; i++) mexPrintf("%s, type = %d, first_row = %d, num_rows = %d\n", sf->signal_name[i], sf->signal_type[i], sf->signal_first_row[i], sf->signal_num_rows[i]);mexPrintf("num_signals = %d, nauto = %d\n", sf->num_signals, sf->nauto);mexPrintf("num_data_rows = %d, num_data_cols = %d, current_column = %d\n", sf->num_data_rows, sf->num_data_cols, sf->current_column);*/for (k = 0; k < sf->num_sweeps; k++) { sf->cur_sweep = k; sf->current_column = 0; if (k > 0) { while(1) { if (fread_float_values(simsource,&val, fp) != 1) { mexPrintf("error: premature file end\n"); return; } if (strncmp(simsource,"hspice",6) == 0) { if (val >= (1e30 - DBL_EPSILON)) { fseek(fp,20,SEEK_CUR); break; } } } } for (i = 0; i < sf->num_data_cols; i++) { if(hs_read_column(fp,sf,simsource) == 1) { mexPrintf("error: premature break\n"); break; } } }fclose(fp);/* write into MATLAB structure */plhs[0] = mxCreateStructMatrix(sf->num_signals+sf->num_sweep_vars,1,2,field_name);/*mexPrintf("num fields = %d\n",mxGetNumberOfFields(plhs[0]));mexPrintf("size = %d\n",mxGetN(plhs[0])*mxGetM(plhs[0]));for (i = 0; i < 2; i++) mexPrintf("field name = %s\n",mxGetFieldNameByNumber(plhs[0],i));*/for (k = 0; k < sf->num_signals; k++) { /* copy over the signal name to the structure */ pa1 = mxCreateString(sf->signal_name[k]); mxSetField(plhs[0],k,field_name[0],pa1); if (sf->signal_num_rows[k] == 1) pa1 = mxCreateDoubleMatrix(sf->num_data_cols,sf->num_sweeps,mxREAL); else pa1 = mxCreateDoubleMatrix(sf->num_data_cols,sf->num_sweeps,mxCOMPLEX); /* copy over the spice data to the matlab matrix */ matData = mxGetPr(pa1); j = 0; /* first data row */ for (i = 0; i < sf->num_data_cols; i++) { for (m = 0; m < sf->num_sweeps; m++) { matData[i + m*sf->num_data_cols] = sf->signal_data[sf->signal_first_row[k]+j+m*sf->num_data_rows][i]; } } if (sf->signal_num_rows[k] == 2) { /* mexPrintf("complex for k = %d\n",k); */ matData = mxGetPi(pa1); j = 1; /* second data row */ for (i = 0; i < sf->num_data_cols; i++) { for (m = 0; m < sf->num_sweeps; m++) { matData[i + m*sf->num_data_cols] = sf->signal_data[sf->signal_first_row[k]+j+m*sf->num_data_rows][i]; } } } mxSetField(plhs[0],k,field_name[1],pa1); }/* copy sweep parameters */for (sweep_name_num = 0; k < sf->num_signals+sf->num_sweep_vars; k++, sweep_name_num++) { /* copy over the sweep parameter name to the structure */ pa1 = mxCreateString(sf->sweep_name[sweep_name_num]); mxSetField(plhs[0],k,field_name[0],pa1); pa1 = mxCreateDoubleMatrix(1,sf->num_sweeps,mxREAL); /* copy over the spice data to the matlab matrix */ matData = mxGetPr(pa1); for (i = 0; i < sf->num_sweeps; i++) { matData[i] = sf->sweep_data[sweep_name_num][i]; } mxSetField(plhs[0],k,field_name[1],pa1); }free_SpiceData(sf);return;}SpiceData *hs_allocate_sf(FILE *fp, char *simsource){ char *ahdr; unsigned int ahdrsize, term_seq; int nprobe,num_signals,nauto,block_size; char nbuf[16], version[16], full_version[50]; int data_rows,i,data_cols,nsweep_var,nsweep_names; int sig_type,val_flag,sweep_count; int char_position,j; unsigned int header_seg_length[MAX_HEADER_BLOCKS],k; unsigned int ibuf[4]; int col_count; /* probably not necessary to rewind, but just to make sure ... */ rewind(fp); /* assume hspice is simulation source by default */ sprintf(simsource,"hspice"); if(fread_int_values(simsource,ibuf, 4, fp) != 4) { mexPrintf("error in hs_allocate_sf: EOF reading block1 header\n"); return(NULL); } if(ibuf[0] != 4 || ibuf[2] != 4) { /* check if Windows Hspice */ /* printf("ibuf[0] = %x, ibuf[1] = %x, ibuf[2] = %x, ibuf[3] = %x\n", ibuf[0],ibuf[1],ibuf[2],ibuf[3]); */ if (ibuf[0] == 0x4000000 && ibuf[2] == 0x4000000) { sprintf(simsource,"hspice_win"); /* printf("sim = %s\n",simsource); */ rewind(fp); if (fread_int_values(simsource,ibuf, 4, fp) != 4) { mexPrintf("error in hs_allocate_sf: EOF reading block1 header\n"); return(NULL); } /* printf("ibuf[0] = %x, ibuf[1] = %x, ibuf[2] = %x, ibuf[3] = %x\n", ibuf[0],ibuf[1],ibuf[2],ibuf[3]); */ if (ibuf[0] != 4 || ibuf[2] != 4) { mexPrintf("error in hs_allocate_sf: unexpected values in block1 header\n"); return(NULL); } } else { mexPrintf("error in hs_allocate_sf: unexpected values in block1 header\n"); return(NULL); } } ahdrsize = 0; for (i = 0; i < MAX_HEADER_BLOCKS; i++) { header_seg_length[i] =ibuf[3]; ahdrsize += header_seg_length[i]; fseek(fp,header_seg_length[i]-8,SEEK_CUR); if(fread_int_values(simsource,&term_seq,1, fp) != 1) { mexPrintf("error in hs_allocate_sf: EOF reading block trailer\n"); return(NULL); } /* mexPrintf("term_seq = %x\n",term_seq); */ fseek(fp,4,SEEK_CUR); if(fread_int_values(simsource,ibuf,1, fp) != 1) { mexPrintf("error in hs_allocate_sf: EOF reading block trailer\n"); return(NULL); } /* mexPrintf("ibuf[0] = %x, ibuf[1] = %x, ibuf[2] = %x, ibuf[3] = %x, head_length = %x\n", ibuf[0],ibuf[1],ibuf[2],ibuf[3],header_seg_length[i]); */ if (ibuf[0] != header_seg_length[i]) { mexPrintf("error in hs_allocate_sf: block trailer mismatch\n"); return(NULL); } if(fread_int_values(simsource,ibuf, 4, fp) != 4) { mexPrintf("error in hs_allocate_sf: EOF reading block header\n"); return(NULL); } if(ibuf[0] != 4 || ibuf[2] != 4) { mexPrintf("error in hs_allocate_sf: unexepected values in block header\n"); return(NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -