1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "rcx/extprocess.h"
34 
35 #include "utl/Logger.h"
36 
37 namespace rcx {
38 
39 using utl::RCX;
40 
extConductor(Logger * logger)41 extConductor::extConductor(Logger* logger) {
42   strcpy(_name, "");
43   _height = 0;
44   _distance = 0;
45   _thickness = 0;
46   _min_width = 0;
47   _min_spacing = 0;
48   _origin_x = 0;
49   _bottom_left_x = 0;
50   _bottom_right_x = 0;
51   _top_left_x = 0;
52   _top_right_x = 0;
53   _var_table_index = 0;
54   _p = 0.0;
55   _min_cw_del = 0;
56   _max_cw_del = 0;
57   _min_ct_del = 0;
58   _max_ct_del = 0;
59   _min_ca = 0;
60   _max_ca = 0;
61   _top_ext = 0;
62   _bot_ext = 0;
63   logger_ = logger;
64 }
printConductor(FILE * fp,Ath__parser * parse)65 void extConductor::printConductor(FILE* fp, Ath__parser* parse) {
66   fprintf(fp, "CONDUCTOR {\n");
67 
68   parse->printString(fp, "\t", "name", _name);
69   parse->printDouble(fp, "\t", "height", _height, true);
70   parse->printDouble(fp, "\t", "thickness", _thickness, true);
71 
72   parse->printDouble(fp, "\t", "min_width", _min_width, true);
73   parse->printDouble(fp, "\t", "min_spacing", _min_spacing, true);
74   parse->printDouble(fp, "\t", "origin_x", _origin_x, true);
75   parse->printDouble(fp, "\t", "bottom_left_x", _bottom_left_x, true);
76   parse->printDouble(fp, "\t", "bottom_right_x", _bottom_right_x, true);
77   parse->printDouble(fp, "\t", "top_left_x", _top_left_x, true);
78   parse->printDouble(fp, "\t", "top_right_x", _top_right_x, true);
79   parse->printDouble(fp, "\t", "top_extension", _top_ext, false);
80   parse->printDouble(fp, "\t", "bottom_extension", _bot_ext, false);
81   parse->printInt(fp, "\t", "var_table", _var_table_index, true);
82   parse->printDouble(fp, "\t", "resistivity", _p, true);
83 
84   fprintf(fp, "}\n");
85 }
readConductor(Ath__parser * parser)86 bool extConductor::readConductor(Ath__parser* parser) {
87   if (parser->setDoubleVal("distance", 1, _distance))
88     return true;
89   else if (parser->setDoubleVal("height", 1, _height))
90     return true;
91   else if (parser->setDoubleVal("thickness", 1, _thickness))
92     return true;
93   else if (parser->setDoubleVal("min_width", 1, _min_width))
94     return true;
95   else if (parser->setDoubleVal("min_spacing", 1, _min_spacing))
96     return true;
97   else if (parser->setDoubleVal("origin_x", 1, _origin_x))
98     return true;
99   else if (parser->setDoubleVal("bottom_left_x", 1, _bottom_left_x))
100     return true;
101   else if (parser->setDoubleVal("bottom_right_x", 1, _bottom_right_x))
102     return true;
103   else if (parser->setDoubleVal("top_left_x", 1, _top_left_x))
104     return true;
105   else if (parser->setDoubleVal("top_right_x", 1, _top_right_x))
106     return true;
107   else if (parser->setIntVal("var_table", 1, _var_table_index))
108     return true;
109   else if (parser->setDoubleVal("resistivity", 1, _p))
110     return true;
111   else if (parser->setDoubleVal("min_cw_del", 1, _min_cw_del))
112     return true;
113   else if (parser->setDoubleVal("max_cw_del", 1, _max_cw_del))
114     return true;
115   else if (parser->setDoubleVal("min_ct_del", 1, _min_ct_del))
116     return true;
117   else if (parser->setDoubleVal("max_ct_del", 1, _max_ct_del))
118     return true;
119   else if (parser->setDoubleVal("min_ca", 1, _min_ca))
120     return true;
121   else if (parser->setDoubleVal("max_ca", 1, _max_ca))
122     return true;
123   else if (parser->setDoubleVal("top_extension", 1, _top_ext))
124     return true;
125   else if (parser->setDoubleVal("bottom_extension", 1, _bot_ext))
126     return true;
127 
128   return false;
129 }
130 
extDielectric(Logger * logger)131 extDielectric::extDielectric(Logger* logger) {
132   strcpy(_name, "");
133   strcpy(_non_conformal_metal, "");
134   _epsilon = 0;
135   _height = 0;
136   _distance = 0;
137   _thickness = 0;
138   _left_thickness = 0;
139   _right_thickness = 0;
140   _top_thickness = 0;
141   _bottom_thickness = 0;
142   _conformal = false;
143   _trench = false;
144   _bottom_ext = 0;
145   _slope = 0;
146   _met = 0;
147   _nextMet = 0;
148   logger_ = logger;
149 }
printDielectric(FILE * fp,Ath__parser * parse)150 void extDielectric::printDielectric(FILE* fp, Ath__parser* parse) {
151   fprintf(fp, "DIELECTRIC {\n");
152 
153   parse->printString(fp, "\t", "name", _name);
154   parse->printDouble(fp, "\t", "epsilon", _epsilon);
155   if (!_conformal && !_trench)
156     parse->printString(fp, "\t", "non_conformal_metal", _non_conformal_metal,
157                        true);
158 
159   parse->printDouble(fp, "\t", "height", _height, true);
160   parse->printDouble(fp, "\t", "thickness", _thickness, true);
161 
162   parse->printDouble(fp, "\t", "left_thickness", _left_thickness, true);
163   parse->printDouble(fp, "\t", "right_thickness", _right_thickness, true);
164   parse->printDouble(fp, "\t", "top_thickness", _top_thickness, true);
165   parse->printDouble(fp, "\t", "bottom_thickness", _bottom_thickness, true);
166   parse->printDouble(fp, "\t", "bottom_ext", _bottom_ext, true);
167   parse->printDouble(fp, "\t", "slope", _slope, false);
168   parse->printInt(fp, "\t", "met", _met, true);
169   parse->printInt(fp, "\t", "next_met", _nextMet, true);
170 
171   fprintf(fp, "}\n");
172 }
printDielectric(FILE * fp,float planeWidth,float planeThickness)173 void extDielectric::printDielectric(FILE* fp, float planeWidth,
174                                     float planeThickness) {
175   fprintf(fp, "BOX NAME %-15s; CX=0; CY=%g; W=%g; H= %g; DIEL= %g;\n", _name,
176           _height, planeWidth, planeThickness, _epsilon);
177 }
printDielectric3D(FILE * fp,float blockWidth,float blockThickness,float blockLength)178 void extDielectric::printDielectric3D(FILE* fp, float blockWidth,
179                                       float blockThickness, float blockLength) {
180   fprintf(fp,
181           "BLOCK NAME %-15s; V1=0,%g,%g; LENGTH=%g; WIDTH=%g; HEIGHT=%g; "
182           "DIEL=%g;\n",
183           _name, _height - (blockThickness * 0.5), blockLength * 0.5,
184           blockThickness, blockWidth, blockLength, _epsilon);
185 }
writeRaphaelDielPoly(FILE * fp,double X,double width,extDielectric * diel)186 void extMasterConductor::writeRaphaelDielPoly(FILE* fp, double X, double width,
187                                               extDielectric* diel) {
188   fprintf(fp, "POLY NAME= %s; ", diel->_name);
189 
190   fprintf(fp, " COORD= ");
191 
192   writeRaphaelPointXY(fp, X + _loLeft[0], _loLeft[2]);
193   writeRaphaelPointXY(fp, X + _loRight[0], _loLeft[2]);
194   writeRaphaelPointXY(fp, X + _hiRight[0], _hiRight[2]);
195   writeRaphaelPointXY(fp, X + _hiLeft[0], _hiLeft[2]);
196 
197   fprintf(fp, " DIEL=%g ;\n", diel->_epsilon);
198 }
writeRaphaelDielPoly3D(FILE * fp,double X,double width,double length,extDielectric * diel)199 void extMasterConductor::writeRaphaelDielPoly3D(FILE* fp, double X,
200                                                 double width, double length,
201                                                 extDielectric* diel) {
202   fprintf(fp, "POLY3D NAME= %s; ", diel->_name);
203 
204   fprintf(fp, " COORD= ");
205 
206   writeRaphaelPointXY(fp, X + _loLeft[0], _loLeft[2]);
207   writeRaphaelPointXY(fp, X + _loRight[0], _loLeft[2]);
208   writeRaphaelPointXY(fp, X + _hiRight[0], _hiRight[2]);
209   writeRaphaelPointXY(fp, X + _hiLeft[0], _hiLeft[2]);
210 
211   fprintf(fp, "V1=0,0,0; HEIGHT=%g;", length);
212   fprintf(fp, " DIEL=%g ;\n", diel->_epsilon);
213 }
printDielBox(FILE * fp,double X,double width,extDielectric * diel,const char * width_name)214 void extMasterConductor::printDielBox(FILE* fp, double X, double width,
215                                       extDielectric* diel,
216                                       const char* width_name) {
217   // non conformal
218 
219   double thickness = _hiLeft[2] - _loLeft[2];
220   if (thickness == 0.0)
221     return;
222   if (width_name != NULL) {
223     double height = _loLeft[2];
224 
225     fprintf(fp, "BOX NAME=%-15s; CX=0; CY=%6.3f; W=%s; H= %.3f; DIEL= %g;\n",
226             diel->_name, height, width_name, thickness, diel->_epsilon);
227 
228     /*		fprintf(stdout, "BOX NAME=%-15s; CX=0; CY=%6.3f; W=%s; H= %.3f;
229        DIEL= %g;\n", diel->_name, height, width_name, thickness,
230        diel->_epsilon);
231     */
232     logger_->info(
233         RCX, 156,
234         "BOX NAME={:-15s}; CX=0; CY={:6.3f}; W={}; H= {:.3f}; DIEL= {};",
235         diel->_name, height, width_name, thickness, diel->_epsilon);
236   } else {
237     _loRight[0] = _loLeft[0] + width;
238     _hiRight[0] = _hiLeft[0] + width;
239 
240     writeRaphaelDielPoly(fp, X, width, diel);
241 
242     // writeRaphaelDielPoly(stdout, X, width, diel);
243   }
244 }
printDielBox3D(FILE * fp,double X,double width,double length,extDielectric * diel,const char * width_name)245 void extMasterConductor::printDielBox3D(FILE* fp, double X, double width,
246                                         double length, extDielectric* diel,
247                                         const char* width_name) {
248   // non conformal
249 
250   if (width_name != NULL) {
251     //                double height= _loLeft[2];
252     double thickness = _hiLeft[2] - _loLeft[2];
253 
254     fprintf(fp,
255             "BLOCK NAME=%-15s; V1=0,0,%6.3f; WIDTH=%s; LENGTH= %.3f; "
256             "HEIGHT=%6.3f; DIEL= %g;\n",
257             diel->_name, 0.5 * length, width_name, thickness, length,
258             diel->_epsilon);
259     /*        	fprintf(stdout, "BLOCK NAME=%-15s; V1=0,0,%6.3f; WIDTH=%s;
260        LENGTH= %.3f; HEIGHT=%6.3f; DIEL= %g;\n", diel->_name, 0.5*length,
261        width_name, thickness, length, diel->_epsilon);
262     */
263     logger_->info(
264         RCX, 157,
265         "BLOCK NAME={:-15s}; V1=0, 0,{:6.3f}; WIDTH={}; LENGTH= {.3f}; "
266         "HEIGHT={:6.3f}; DIEL= {:g};",
267         diel->_name, 0.5 * length, width_name, thickness, length,
268         diel->_epsilon);
269   } else {
270     _loRight[0] = _loLeft[0] + width;
271     _hiRight[0] = _hiLeft[0] + width;
272 
273     writeRaphaelDielPoly3D(fp, X, width, length, diel);
274   }
275 }
writeProcess(FILE * fp,char * gndName,float planeWidth,float planeThickness)276 void extProcess::writeProcess(FILE* fp, char* gndName, float planeWidth,
277                               float planeThickness) {
278   fprintf(fp, "WINDOW X1=%g; Y1=-1.0; X2=%g; Y2=%g; DIEL=1.0;\n",
279           -planeWidth * 0.5, planeWidth * 0.5, planeThickness);
280 
281   for (uint jj = 1; jj < _dielTable->getCnt(); jj++) {
282     extDielectric* diel = _dielTable->get(jj);
283     //		if (diel->_conformal)
284     diel->printDielectric(fp, planeWidth, planeThickness);
285   }
286   fprintf(fp, "BOX NAME=%s CX=0; CY=-0.5; W=%g; H=1.0; VOLT=0.0;\n", gndName,
287           planeWidth);
288 
289   fprintf(fp, "OPTIONS SET_GRID=10000;\n");
290 }
writeProcess3D(FILE * fp,char * gndName,float blockWidth,float blockThickness,float blockLength)291 void extProcess::writeProcess3D(FILE* fp, char* gndName, float blockWidth,
292                                 float blockThickness, float blockLength) {
293   fprintf(fp, "WINDOW3D V1=%g,0,0; V2=%g,%g,%g; DIEL=1.0;\n", -blockWidth * 0.5,
294           blockWidth * 0.5, blockThickness, blockLength);
295 
296   for (uint jj = 1; jj < _dielTable->getCnt(); jj++) {
297     extDielectric* diel = _dielTable->get(jj);
298     //                if (diel->_conformal)
299     diel->printDielectric3D(fp, blockWidth, blockThickness, blockLength);
300   }
301   fprintf(
302       fp,
303       "BLOCK NAME=%s; V1=0,-1,%g; LENGTH=1.0; WIDTH=%g, HEIGHT=%g; VOLT=0.0;\n",
304       gndName, blockLength * 0.5, blockWidth, blockLength);
305 
306   fprintf(fp, "OPTIONS SET_GRID=1000000;\n");
307 }
writeParam(FILE * fp,const char * name,double val)308 void extProcess::writeParam(FILE* fp, const char* name, double val) {
309   fprintf(fp, "param %s=%g;\n", name, val);
310 }
writeWindow(FILE * fp,const char * param_width_name,double y1,const char * param_thickness_name)311 void extProcess::writeWindow(FILE* fp, const char* param_width_name, double y1,
312                              const char* param_thickness_name) {
313   fprintf(fp, "\n$ Simulation window\n");
314   fprintf(fp, "WINDOW X1=-0.5*%s; Y1=%g; X2=0.5*%s; Y2=%s; DIEL=1.0;\n",
315           param_width_name, y1, param_width_name, param_thickness_name);
316 }
writeWindow3D(FILE * fp,const char * param_width_name,double y1,const char * param_thickness_name,const char * param_length_name)317 void extProcess::writeWindow3D(FILE* fp, const char* param_width_name,
318                                double y1, const char* param_thickness_name,
319                                const char* param_length_name) {
320   fprintf(fp, "\n$ Simulation window\n");
321   fprintf(fp, "WINDOW3D V1=-0.5*%s,%g,0; V2=0.5*%s,%s,%s; DIEL=1.0;\n",
322           param_width_name, y1, param_width_name, param_thickness_name,
323           param_length_name);
324 }
writeGround(FILE * fp,int met,const char * name,double width,double x1,double volt,bool diag)325 void extProcess::writeGround(FILE* fp, int met, const char* name, double width,
326                              double x1, double volt, bool diag) {
327   if (met < 0)
328     return;
329   if (!met && diag)
330     return;
331 
332   double y1 = -1.0;
333   double th = 1.0;
334   extMasterConductor* m;
335   if (met > 0 && !diag) {
336     m = getMasterConductor(met);
337     y1 = m->_loLeft[2];
338     th = m->_hiLeft[2] - y1;
339     m->writeRaphaelConformalGround(fp, x1, width, this);
340     fprintf(fp, "POLY NAME= M%d__%s; ", met, name);
341   } else {
342     fprintf(fp, "POLY NAME= M0__%s; ", name);
343   }
344 
345   fprintf(fp, " COORD= ");
346 
347   writeRaphaelPointXY(fp, x1, y1);
348   writeRaphaelPointXY(fp, x1 + width, y1);
349   writeRaphaelPointXY(fp, x1 + width, y1 + th);
350   writeRaphaelPointXY(fp, x1, y1 + th);
351 
352   fprintf(fp, " VOLT=%g ;\n", volt);
353 
354   fprintf(fp, "OPTIONS SET_GRID=10000;\n\n");
355 }
writeGround3D(FILE * fp,int met,const char * name,double width,double length,double x1,double volt,bool diag)356 void extProcess::writeGround3D(FILE* fp, int met, const char* name,
357                                double width, double length, double x1,
358                                double volt, bool diag) {
359   if (met < 0)
360     return;
361 
362   double y1 = -1.0;
363   double th = 1.0;
364   if (!met || diag) {
365     if (diag)
366       fprintf(fp, "POLY3D NAME= M0__w0; ");
367     else
368       fprintf(fp, "POLY3D NAME= M%d__w0; ", met);
369     fprintf(fp, " COORD= ");
370     writeRaphaelPointXY(fp, x1, y1);
371     writeRaphaelPointXY(fp, x1 + width, y1);
372     writeRaphaelPointXY(fp, x1 + width, y1 + th);
373     writeRaphaelPointXY(fp, x1, y1 + th);
374     fprintf(fp, " V1=0,0,0; HEIGHT=%g;", length);
375     fprintf(fp, " VOLT=%g ;\n", volt);
376     fprintf(fp, "OPTIONS SET_GRID=1000000;\n\n");
377     return;
378   }
379 
380   double w, s, p;
381   if (met > 0) {
382     extMasterConductor* m = getMasterConductor(met);
383     y1 = m->_loLeft[2];
384     th = m->_hiLeft[2] - y1;
385     w = getConductor(met)->_min_width;
386     s = getConductor(met)->_min_spacing;
387     p = w + s;
388   }
389 
390   double l = 2 * p;
391   double end = length - 2 * p;
392   while (l <= end) {
393     fprintf(fp, "POLY3D NAME= M%d__w0; ", met);
394     fprintf(fp, " COORD= ");
395     writeRaphaelPointXY(fp, x1, y1);
396     writeRaphaelPointXY(fp, x1 + width, y1);
397     writeRaphaelPointXY(fp, x1 + width, y1 + th);
398     writeRaphaelPointXY(fp, x1, y1 + th);
399 
400     fprintf(fp, " V1=0,0,%g; HEIGHT=%g;", l, w);
401     fprintf(fp, " VOLT=%g ;\n", volt);
402     l += p;
403   }
404 
405   fprintf(fp, "OPTIONS SET_GRID=1000000;\n\n");
406 }
writeGround(FILE * fp,int met,const char * name,const char * param_width_name,double x1,double volt)407 void extProcess::writeGround(FILE* fp, int met, const char* name,
408                              const char* param_width_name, double x1,
409                              double volt) {
410   if (met < 0)
411     return;
412 
413   double y1 = -0.5;
414   double th = 1.0;
415   if (met > 0) {
416     extMasterConductor* m = getMasterConductor(met);
417     y1 = m->_loLeft[2];
418     th = m->_hiLeft[2] - y1;
419   }
420   fprintf(fp, "BOX NAME=M%d__%s CX=%g; CY=%g; W=%s; H=%g; VOLT=%g;\n", met,
421           name, x1, y1, param_width_name, th, volt);
422 
423   fprintf(fp, "OPTIONS SET_GRID=10000;\n\n");
424 }
writeFullProcess(FILE * fp,double X,double width,char * width_name)425 void extProcess::writeFullProcess(FILE* fp, double X, double width,
426                                   char* width_name) {
427   for (uint jj = 1; jj < _masterDielectricTable->getCnt(); jj++) {
428     extMasterConductor* m = _masterDielectricTable->get(jj);
429     extDielectric* diel = _dielTable->get(m->_condId);
430 
431     // if (diel->_conformal)
432     m->printDielBox(fp, X, width, diel, width_name);
433   }
434 }
writeFullProcess3D(FILE * fp,double X,double width,double length,char * width_name)435 void extProcess::writeFullProcess3D(FILE* fp, double X, double width,
436                                     double length, char* width_name) {
437   for (uint jj = 1; jj < _masterDielectricTable->getCnt(); jj++) {
438     extMasterConductor* m = _masterDielectricTable->get(jj);
439     extDielectric* diel = _dielTable->get(m->_condId);
440 
441     // if (diel->_conformal)
442     m->printDielBox3D(fp, X, width, length, diel, width_name);
443   }
444 }
writeFullProcess(FILE * fp,char * gndName,double planeWidth,double planeThickness)445 void extProcess::writeFullProcess(FILE* fp, char* gndName, double planeWidth,
446                                   double planeThickness) {
447   fprintf(fp, "param plane_width=%g;\n", planeWidth);
448 
449   fprintf(fp, "WINDOW X1=%g; Y1=-1.0; X2=%g; Y2=%g; DIEL=1.0;\n",
450           -planeWidth * 0.5, planeWidth * 0.5, planeThickness);
451 
452   for (uint jj = 1; jj < _masterDielectricTable->getCnt(); jj++) {
453     extMasterConductor* m = _masterDielectricTable->get(jj);
454     extDielectric* diel = _dielTable->get(m->_condId);
455 
456     // if (diel->_conformal)
457     m->printDielBox(fp, 0.0, planeWidth, diel, "plane_width");
458   }
459   fprintf(fp, "\nBOX NAME=%s CX=0; CY=-0.5; W=%g; H=1.0; VOLT=0.0;\n", gndName,
460           planeWidth);
461 
462   fprintf(fp, "OPTIONS SET_GRID=10000;\n\n");
463 }
464 
writeProcessAndGround(FILE * wfp,const char * gndName,int underMet,int overMet,double X,double width,double thickness,bool diag)465 void extProcess::writeProcessAndGround(FILE* wfp, const char* gndName,
466                                        int underMet, int overMet, double X,
467                                        double width, double thickness,
468                                        bool diag) {
469   const char* widthName = "window_width";
470   const char* thicknessName = "window_thichness";
471 
472   writeParam(wfp, widthName, width);
473   writeParam(wfp, thicknessName, thickness);
474 
475   // CX,CY bug : writeFullProcess(wfp, X, width, widthName);
476   writeFullProcess(wfp, X, width, NULL);
477 
478   double y1 = 0.0;
479   writeWindow(wfp, widthName, y1, thicknessName);
480 
481   fprintf(wfp, "\n$ Ground Plane(s)\n");
482   //	writeGround(wfp, underMet, gndName, widthName, 0.0, 0.0);
483   //	writeGround(wfp, overMet, gndName, widthName, 0.0, 0.0);
484 
485   writeGround(wfp, underMet, gndName, width, -0.5 * width, 0.0, diag);
486   writeGround(wfp, overMet, gndName, width, -0.5 * width, 0.0, diag);
487 }
writeProcessAndGround3D(FILE * wfp,const char * gndName,int underMet,int overMet,double X,double width,double length,double thickness,double W,bool diag)488 void extProcess::writeProcessAndGround3D(FILE* wfp, const char* gndName,
489                                          int underMet, int overMet, double X,
490                                          double width, double length,
491                                          double thickness, double W,
492                                          bool diag) {
493   double wid, x;
494   if (width > W) {
495     wid = width;
496     x = X;
497   } else {
498     wid = W + 10.0;
499     x = -wid * 0.5;
500   }
501   const char* widthName = "window_width";
502   const char* thicknessName = "window_thichness";
503   const char* lengthName = "window_length";
504 
505   writeParam(wfp, widthName, wid);
506   writeParam(wfp, thicknessName, thickness);
507   writeParam(wfp, lengthName, length);
508 
509   // CX,CY bug : writeFullProcess(wfp, X, width, widthName);
510   writeFullProcess3D(wfp, x, width, length, NULL);
511 
512   double y1 = 0.0;
513   writeWindow3D(wfp, widthName, y1, thicknessName, lengthName);
514 
515   fprintf(wfp, "\n$ Ground Plane(s)\n");
516 
517   writeGround3D(wfp, 0, gndName, wid, length, -0.5 * wid, 0.0);
518 
519   double w, s, offset;
520 
521   if (underMet > 0) {
522     w = getConductor(underMet)->_min_width;
523     s = getConductor(underMet)->_min_spacing;
524     offset = w + s;
525     wid = W + 2 * offset;
526     writeGround3D(wfp, underMet, gndName, wid, length, -0.5 * wid, 0.0);
527   }
528   if (overMet > 0) {
529     w = getConductor(overMet)->_min_width;
530     s = getConductor(overMet)->_min_spacing;
531     offset = w + s;
532     wid = W + 2 * offset;
533     writeGround3D(wfp, overMet, gndName, wid, length, -0.5 * wid, 0.0);
534   }
535 }
readDielectric(Ath__parser * parser)536 bool extDielectric::readDielectric(Ath__parser* parser) {
537   if (strcmp("non_conformal_metal", parser->get(0)) == 0) {
538     strcpy(_non_conformal_metal, parser->get(1));
539     _conformal = false;
540     _trench = false;
541     return true;
542   } else if (strcmp("conformal", parser->get(0)) == 0) {
543     _conformal = true;
544     return true;
545   } else if (strcmp("trench", parser->get(0)) == 0) {
546     _trench = true;
547     return true;
548   } else if (parser->setDoubleVal("epsilon", 1, _epsilon))
549     return true;
550   else if (parser->setDoubleVal("distance", 1, _distance))
551     return true;
552   else if (parser->setIntVal("met", 1, _met))
553     return true;
554   else if (parser->setIntVal("next_met", 1, _nextMet))
555     return true;
556   else if (parser->setDoubleVal("height", 1, _height))
557     return true;
558   else if (parser->setDoubleVal("thickness", 1, _thickness))
559     return true;
560   else if (parser->setDoubleVal("bottom_thickness", 1, _bottom_thickness))
561     return true;
562   else if (parser->setDoubleVal("top_thickness", 1, _top_thickness))
563     return true;
564   else if (parser->setDoubleVal("left_thickness", 1, _left_thickness))
565     return true;
566   else if (parser->setDoubleVal("right_thickness", 1, _right_thickness))
567     return true;
568   else if (parser->setDoubleVal("bottom_ext", 1, _bottom_ext))
569     return true;
570   else if (parser->setDoubleVal("slope", 1, _slope))
571     return true;
572 
573   return false;
574 }
extMasterConductor(uint condId,extConductor * cond,double prevHeight,Logger * logger)575 extMasterConductor::extMasterConductor(uint condId, extConductor* cond,
576                                        double prevHeight, Logger* logger) {
577   _condId = condId;
578   logger_ = logger;
579   // X coordinates
580 
581   double min_width = cond->_min_width;
582   if (cond->_bottom_right_x - cond->_bottom_left_x > 0) {
583     _loLeft[0] = cond->_bottom_left_x;
584     _loRight[0] = cond->_bottom_right_x;
585   } else {
586     if (cond->_bot_ext == 0.0)
587       _loLeft[0] = 0;
588     else
589       _loLeft[0] = -cond->_bot_ext;
590     if (!(min_width > 0)) {
591       /*			fprintf(stdout, "Cannot determine Bottom Width
592          for Conductor <%s>\n", cond->_name);
593       */
594       logger_->warn(RCX, 158, "Can't determine Bottom Width for Conductor <{}>",
595                     cond->_name);
596       exit(0);
597     }
598     if (cond->_bot_ext == 0.0)
599       _loRight[0] = min_width;
600     else
601       _loRight[0] = min_width + cond->_bot_ext;
602   }
603   _hiLeft[0] = cond->_top_left_x;
604   _hiRight[0] = cond->_top_right_x;
605 
606   if (cond->_top_right_x - cond->_top_left_x > 0) {
607     _hiLeft[0] = cond->_top_left_x;
608     _hiRight[0] = cond->_top_right_x;
609   } else {
610     if (cond->_top_ext == 0.0)
611       _hiLeft[0] = 0;
612     else
613       _hiLeft[0] = -cond->_top_ext;
614     if (!(min_width > 0)) {
615       /*			fprintf(stdout, "Cannot determine Top Width for
616          Conductor <%s>\n", cond->_name);
617       */
618       logger_->warn(RCX, 152, "Can't determine Top Width for Conductor <{}>",
619                     cond->_name);
620       exit(0);
621     }
622     if (cond->_top_ext == 0.0)
623       _hiRight[0] = min_width;
624     else
625       _hiRight[0] = min_width + cond->_top_ext;
626   }
627 
628   // Y coordinates
629   _loLeft[1] = 0;
630   _loRight[1] = 0;
631   _hiLeft[1] = 0;
632   _hiRight[1] = 0;
633 
634   // Z coordinates
635   double height = cond->_height;
636   if (height <= 0) {
637     height += prevHeight + cond->_distance;
638     cond->_height = height;
639   }
640 
641   _loLeft[2] = height;
642   _loRight[2] = height;
643 
644   double thickness = cond->_thickness;
645   if (!(thickness > 0)) {
646     /*		fprintf(stdout, "Cannot determine thickness for Conductor
647        <%s>\n", cond->_name);
648     */
649     logger_->warn(RCX, 153, "Can't determine thickness for Conductor <{}>",
650                   cond->_name);
651     exit(0);
652   }
653   _hiLeft[2] = height + thickness;
654   _hiRight[2] = height + thickness;
655 
656   _dy = 0;
657   _e = 0.0;
658   for (uint i = 0; i < 3; i++)
659     _conformalId[i] = 0;
660 }
resetThicknessHeight(double height,double thickness)661 void extMasterConductor::resetThicknessHeight(double height, double thickness) {
662   _hiLeft[2] = height + thickness;
663   _hiRight[2] = height + thickness;
664   _loLeft[2] = _hiLeft[2] - thickness;
665   _loRight[2] = _loLeft[2];
666 }
resetWidth(double top_width,double bottom_width)667 void extMasterConductor::resetWidth(double top_width, double bottom_width) {
668   _loLeft[0] = -bottom_width / 2;
669   _loRight[0] = bottom_width / 2;
670 
671   _hiLeft[0] = -top_width / 2;
672   _hiRight[0] = top_width / 2;
673 }
reset(double height,double top_width,double bottom_width,double thickness)674 void extMasterConductor::reset(double height, double top_width,
675                                double bottom_width, double thickness) {
676   _loLeft[0] = -bottom_width / 2;
677   _loRight[0] = bottom_width / 2;
678 
679   _hiLeft[0] = -top_width / 2;
680   _hiRight[0] = top_width / 2;
681 
682   // Y coordinates
683   _loLeft[1] = 0;
684   _loRight[1] = 0;
685   _hiLeft[1] = 0;
686   _hiRight[1] = 0;
687 
688   // Z coordinates
689   // assume target height and thickness were set
690 
691   _hiLeft[2] = height + thickness;
692   _hiRight[2] = height + thickness;
693   _loLeft[2] = _hiLeft[2] - thickness;
694   _loRight[2] = _loLeft[2];
695 
696   //_hiLeft[2]= height + thickness;
697   //_hiRight[2]= height + thickness;
698 
699   //_loLeft[2]= height;
700   //_loRight[2]= height;
701 }
writeRaphaelBox(FILE * fp,uint wireNum,double width,double X,double volt)702 double extMasterConductor::writeRaphaelBox(FILE* fp, uint wireNum, double width,
703                                            double X, double volt) {
704   return writeRaphaelPoly(fp, wireNum, width, X, volt);
705 
706   fprintf(fp, "BOX NAME=");
707   writeBoxName(fp, wireNum);
708 
709   fprintf(fp, " CX=%g; CY=%g; W=%g; H=%g; VOLT=%g\n", X, _loLeft[2], width,
710           _hiLeft[2] - _loLeft[2], volt);
711 
712   return X + width;
713 }
writeRaphaelPointXY(FILE * fp,double X,double Y)714 void extMasterConductor::writeRaphaelPointXY(FILE* fp, double X, double Y) {
715   fprintf(fp, "  %6.3f,%6.3f ; ", X, Y);
716 }
writeRaphaelPointXY(FILE * fp,double X,double Y)717 void extProcess::writeRaphaelPointXY(FILE* fp, double X, double Y) {
718   fprintf(fp, "  %6.3f,%6.3f ; ", X, Y);
719 }
writeRaphaelPoly(FILE * fp,uint wireNum,double X,double volt)720 void extMasterConductor::writeRaphaelPoly(FILE* fp, uint wireNum, double X,
721                                           double volt) {
722   fprintf(fp, "POLY NAME=");
723   writeBoxName(fp, wireNum);
724 
725   fprintf(fp, " COORD= ");
726 
727   writeRaphaelPointXY(fp, X + _loLeft[0], _loLeft[2]);
728   writeRaphaelPointXY(fp, X + _loRight[0], _loLeft[2]);
729   writeRaphaelPointXY(fp, X + _hiRight[0], _hiRight[2]);
730   writeRaphaelPointXY(fp, X + _hiLeft[0], _hiLeft[2]);
731 
732   fprintf(fp, " VOLT=%g\n", volt);
733 }
writeRaphaelConformalPoly(FILE * fp,double width,double X,extProcess * p)734 void extMasterConductor::writeRaphaelConformalPoly(FILE* fp, double width,
735                                                    double X, extProcess* p) {
736   double height[3];
737   double thickness[3];
738   double bottom_ext[3];
739   double slope[3];
740   double e[3];
741   bool trench = false;
742   uint cnt = 0;
743   uint start = 0;
744   double h = _loLeft[2];
745   for (uint i = 0; i < 3; i++) {
746     uint j = 2 - i;
747     if (!_conformalId[j])
748       continue;
749     if (!start)
750       start = i;
751     extDielectric* d = p->getDielectric(_conformalId[j]);
752     // assuming conformal and trench will not show up at the same time. Also
753     // height for the trench layer is negative.
754     trench = d->_trench;
755     height[i] = d->_height;
756     thickness[i] = d->_thickness;
757     bottom_ext[i] = d->_bottom_ext;
758     slope[i] = d->_slope;
759     e[i] = d->_epsilon;
760     h += d->_thickness;
761     cnt++;
762   }
763   if (!cnt)
764     return;
765   if (trench) {
766     for (uint j = start; j < start + cnt; j++) {
767       fprintf(fp, "POLY NAME=");
768       fprintf(fp, "M%d_Trench%d;", _condId, 2 - j);
769       if (width == 0.0) {
770         writeRaphaelPointXY(fp, X + _loLeft[0] - bottom_ext[j],
771                             _hiRight[2] + height[j]);
772         writeRaphaelPointXY(fp, X + _loRight[0] + bottom_ext[j],
773                             _hiRight[2] + height[j]);
774         writeRaphaelPointXY(fp, X + _hiRight[0] + bottom_ext[j], _hiRight[2]);
775         writeRaphaelPointXY(fp, X + _hiLeft[0] - bottom_ext[j], _hiRight[2]);
776         fprintf(fp, " DIEL=%g\n", e[j]);
777       } else {
778         writeRaphaelPointXY(fp, X - bottom_ext[j], _hiRight[2] + height[j]);
779         writeRaphaelPointXY(fp, X + width + bottom_ext[j],
780                             _hiRight[2] + height[j]);
781         writeRaphaelPointXY(fp, X + width + bottom_ext[j], _hiRight[2]);
782         writeRaphaelPointXY(fp, X - bottom_ext[j], _hiRight[2]);
783         fprintf(fp, " DIEL=%g\n", e[j]);
784       }
785     }
786     return;
787   }
788   double dx;
789   for (uint j = start; j < start + cnt; j++) {
790     fprintf(fp, "POLY NAME=");
791     fprintf(fp, "M%d_Conformal%d;", _condId, 2 - j);
792     if (width == 0.0) {
793       if (slope[j])
794         dx = (height[j] - thickness[j]) / slope[j];
795       else
796         dx = bottom_ext[j];
797       writeRaphaelPointXY(fp, X + _loLeft[0] - bottom_ext[j], h);
798       writeRaphaelPointXY(fp, X + _loRight[0] + bottom_ext[j], h);
799       h -= thickness[j];
800       writeRaphaelPointXY(fp, X + _hiRight[0] + bottom_ext[j] - dx,
801                           h + height[j]);
802       writeRaphaelPointXY(fp, X + _hiLeft[0] - bottom_ext[j] + dx,
803                           h + height[j]);
804       fprintf(fp, " DIEL=%g\n", e[j]);
805     } else {
806       if (slope[j])
807         dx = (height[j] - thickness[j]) / slope[j];
808       else
809         dx = bottom_ext[j];
810       writeRaphaelPointXY(fp, X - bottom_ext[j], h);
811       writeRaphaelPointXY(fp, X + width + bottom_ext[j], h);
812       h -= thickness[j];
813       writeRaphaelPointXY(fp, X + width + bottom_ext[j] - dx, h + height[j]);
814       writeRaphaelPointXY(fp, X - bottom_ext[j] + dx, h + height[j]);
815       fprintf(fp, " DIEL=%g\n", e[j]);
816     }
817   }
818 }
writeRaphaelConformalGround(FILE * fp,double X,double width,extProcess * p)819 void extMasterConductor::writeRaphaelConformalGround(FILE* fp, double X,
820                                                      double width,
821                                                      extProcess* p) {
822   double height[3];
823   double thickness[3];
824   double bottom_ext[3];
825   double slope[3];
826   double e[3];
827   bool trench = false;
828   uint cnt = 0;
829   uint start = 0;
830   double h = _loLeft[2];
831   for (uint i = 0; i < 3; i++) {
832     uint j = 2 - i;
833     if (!_conformalId[j])
834       continue;
835     if (!start)
836       start = i;
837     extDielectric* d = p->getDielectric(_conformalId[j]);
838     // assuming conformal and trench will not show up at the same time. Also
839     // height for the trench layer is negative.
840     trench = d->_trench;
841     height[i] = d->_height;
842     thickness[i] = d->_thickness;
843     bottom_ext[i] = d->_bottom_ext;
844     slope[i] = d->_slope;
845     e[i] = d->_epsilon;
846     h += d->_thickness;
847     cnt++;
848   }
849   if (!cnt)
850     return;
851   if (trench) {
852     for (uint j = start; j < start + cnt; j++) {
853       fprintf(fp, "POLY NAME=");
854       fprintf(fp, "M%d_Trench%d;", _condId, 2 - j);
855 
856       writeRaphaelPointXY(fp, X, _hiRight[2] + height[j]);
857       writeRaphaelPointXY(fp, X + width, _hiRight[2] + height[j]);
858       writeRaphaelPointXY(fp, X + width, _hiRight[2]);
859       writeRaphaelPointXY(fp, X, _hiRight[2]);
860       fprintf(fp, " DIEL=%g\n", e[j]);
861     }
862     return;
863   }
864   for (uint j = start; j < start + cnt; j++) {
865     fprintf(fp, "POLY NAME=");
866     fprintf(fp, "M%d_Conformal%d;", _condId, 2 - j);
867 
868     h -= thickness[j];
869     writeRaphaelPointXY(fp, X, h);
870     writeRaphaelPointXY(fp, X + width, h);
871     writeRaphaelPointXY(fp, X + width, h + height[j]);
872     writeRaphaelPointXY(fp, X, h + height[j]);
873     fprintf(fp, " DIEL=%g\n", e[j]);
874   }
875 }
writeRaphaelPoly3D(FILE * fp,uint wireNum,double X,double length,double volt)876 void extMasterConductor::writeRaphaelPoly3D(FILE* fp, uint wireNum, double X,
877                                             double length, double volt) {
878   fprintf(fp, "POLY3D NAME=");
879   writeBoxName(fp, wireNum);
880 
881   fprintf(fp, " COORD= ");
882 
883   writeRaphaelPointXY(fp, X + _loLeft[0], _loLeft[2]);
884   writeRaphaelPointXY(fp, X + _loRight[0], _loLeft[2]);
885   writeRaphaelPointXY(fp, X + _hiRight[0], _hiRight[2]);
886   writeRaphaelPointXY(fp, X + _hiLeft[0], _hiLeft[2]);
887 
888   fprintf(fp, "V1=0,0,0; HEIGHT=%g;", length);
889 
890   fprintf(fp, " VOLT=%g\n", volt);
891 }
writeRaphaelPoly(FILE * fp,uint wireNum,double width,double X,double volt,extProcess * p)892 double extMasterConductor::writeRaphaelPoly(FILE* fp, uint wireNum,
893                                             double width, double X, double volt,
894                                             extProcess* p) {
895   fprintf(fp, "POLY NAME=");
896   writeBoxName(fp, wireNum);
897 
898   fprintf(fp, " COORD= ");
899 
900   extConductor* cond = p->getConductor(_condId);
901   double top_ext = cond->_top_ext;
902   double bot_ext = cond->_bot_ext;
903 
904   writeRaphaelPointXY(fp, X - bot_ext, _loLeft[2]);
905   writeRaphaelPointXY(fp, X + width + bot_ext, _loLeft[2]);
906   writeRaphaelPointXY(fp, X + width + top_ext, _hiRight[2]);
907   writeRaphaelPointXY(fp, X - top_ext, _hiLeft[2]);
908 
909   fprintf(fp, " VOLT=%g\n", volt);
910   return X + width;
911 }
writeRaphaelPoly3D(FILE * fp,uint wireNum,double width,double length,double X,double volt)912 double extMasterConductor::writeRaphaelPoly3D(FILE* fp, uint wireNum,
913                                               double width, double length,
914                                               double X, double volt) {
915   fprintf(fp, "POLY3D NAME=");
916   writeBoxName(fp, wireNum);
917 
918   fprintf(fp, " COORD= ");
919 
920   writeRaphaelPointXY(fp, X, _loLeft[2]);
921   writeRaphaelPointXY(fp, X + width, _loLeft[2]);
922   writeRaphaelPointXY(fp, X + width, _hiRight[2]);
923   writeRaphaelPointXY(fp, X, _hiLeft[2]);
924 
925   fprintf(fp, " V1=0,0,0; HEIGHT=%g;", length);
926   fprintf(fp, " VOLT=%g\n", volt);
927   return X + width;
928 }
writeBoxName(FILE * fp,uint wireNum)929 void extMasterConductor::writeBoxName(FILE* fp, uint wireNum) {
930   fprintf(fp, "M%d_w%d;", _condId, wireNum);
931 }
extMasterConductor(uint dielId,extDielectric * diel,double xlo,double dx1,double xhi,double dx2,double h,double th,Logger * logger)932 extMasterConductor::extMasterConductor(uint dielId, extDielectric* diel,
933                                        double xlo, double dx1, double xhi,
934                                        double dx2, double h, double th,
935                                        Logger* logger) {
936   _condId = dielId;
937   logger_ = logger;
938 
939   // X coordinates
940   _loLeft[0] = xlo;
941   _loRight[0] = xlo + dx1;
942   _hiLeft[0] = xhi;
943   _hiRight[0] = xhi + dx2;
944 
945   // Y coordinates
946   _loLeft[1] = 0;
947   _loRight[1] = 0;
948   _hiLeft[1] = 0;
949   _hiRight[1] = 0;
950 
951   // Z coordinates
952 
953   _loLeft[2] = h;
954   _loRight[2] = h;
955 
956   if (!(th > 0)) {
957     /*		fprintf(stdout, "Cannot determine thickness for Diel <%s>\n",
958                             diel->_name);
959     */
960     logger_->warn(RCX, 154, "Can't determine thickness for Diel <{}>",
961                   diel->_name);
962     //		exit(0);
963   }
964   _hiLeft[2] = h + th;
965   _hiRight[2] = h + th;
966 
967   _dy = 0;
968   _e = diel->_epsilon;
969   for (uint i = 0; i < 3; i++)
970     _conformalId[i] = 0;
971 }
openFile(const char * filename,const char * permissions)972 FILE* extProcess::openFile(const char* filename, const char* permissions) {
973   FILE* fp = fopen(filename, permissions);
974   if (fp == NULL) {
975     logger_->error(RCX, 159, "Can't open file {} with permissions <{}>",
976                    filename, permissions);
977     // exit(0);
978   }
979   return fp;
980 }
adjustMasterLayersForHeight(uint met,double thickness)981 double extProcess::adjustMasterLayersForHeight(uint met, double thickness) {
982   double condThickness = _condTable->get(met)->_thickness;
983   double dth = (thickness - condThickness) / condThickness;
984 
985   double h = 0.0;
986   for (uint ii = 1; ii < _masterConductorTable->getCnt(); ii++) {
987     extConductor* cond = _condTable->get(ii);
988     extMasterConductor* m = _masterConductorTable->get(ii);
989 
990     if (_thickVarFlag)
991       h += cond->_distance * (1 + dth);
992     else
993       h += cond->_distance;
994 
995     double th = cond->_thickness;
996     if (_thickVarFlag)
997       th *= (1 + dth);
998     else if (ii == met)
999       th = thickness;
1000 
1001     m->resetThicknessHeight(h, th);
1002     h += th;
1003   }
1004   return dth;
1005 }
adjustMasterDielectricsForHeight(uint met,double dth)1006 double extProcess::adjustMasterDielectricsForHeight(uint met, double dth) {
1007   double h = 0.0;
1008   for (uint ii = 1; ii < _masterDielectricTable->getCnt(); ii++) {
1009     extDielectric* diel = _dielTable->get(ii);
1010     extMasterConductor* m = _masterDielectricTable->get(ii);
1011 
1012     double th = diel->_thickness;
1013     if (_thickVarFlag)
1014       th *= (1 + dth);
1015     else if (diel->_met == (int)met)
1016       th *= (1 + dth);
1017 
1018     m->resetThicknessHeight(h, th);
1019     h += th;
1020   }
1021   return h;
1022 }
createMasterLayers()1023 void extProcess::createMasterLayers() {
1024   double upperCondHeight = 0;
1025   for (uint ii = 1; ii < _condTable->getCnt(); ii++) {
1026     extConductor* cond = _condTable->get(ii);
1027     extMasterConductor* m =
1028         new extMasterConductor(ii, cond, upperCondHeight, logger_);
1029     _masterConductorTable->add(m);
1030     upperCondHeight = cond->_height + cond->_thickness;
1031   }
1032   double h = 0.0;
1033   for (uint jj = 1; jj < _dielTable->getCnt(); jj++) {
1034     extDielectric* diel = _dielTable->get(jj);
1035     if ((diel->_conformal || diel->_trench) && diel->_met) {
1036       extMasterConductor* mm = _masterConductorTable->get(diel->_met);
1037       for (uint i = 0; i < 3; i++) {
1038         if (!mm->_conformalId[i]) {
1039           mm->_conformalId[i] = jj;
1040           break;
1041         }
1042       }
1043     }
1044 
1045     //		if (diel->_conformal) {
1046     extMasterConductor* m = new extMasterConductor(jj, diel, 0, 0, 0, 0, h,
1047                                                    diel->_thickness, logger_);
1048     h += diel->_thickness;
1049 
1050     _masterDielectricTable->add(m);
1051     /*		}
1052                     else {
1053                             extMasterConductor *m=
1054                                     new extMasterConductor(jj, diel, 0, 0, 0, 0,
1055        0, 0);
1056 
1057                             _masterDielectricTable->add(m);
1058                     }
1059     */
1060   }
1061 }
getConductor(uint ii)1062 extConductor* extProcess::getConductor(uint ii) { return _condTable->get(ii); }
getMasterConductor(uint ii)1063 extMasterConductor* extProcess::getMasterConductor(uint ii) {
1064   return _masterConductorTable->get(ii);
1065 }
getDielectric(uint ii)1066 extDielectric* extProcess::getDielectric(uint ii) {
1067   return _dielTable->get(ii);
1068 }
getWidthTable(uint met)1069 Ath__array1D<double>* extProcess::getWidthTable(uint met) {
1070   double min_width = getConductor(met)->_min_width;
1071 
1072   //	const double wTable[7]= {1.0, 1.5, 2.0, 2.5, 3, 3.5, 4};
1073   // const double wTable[3]= {1.0, 1.5, 2.0 };
1074   const double wTable[8] = {1.0, 1.5, 2.0, 2.5, 3, 4, 5, 10};
1075 
1076   //	Ath__array1D<double>* A= new Ath__array1D<double>(8);
1077   Ath__array1D<double>* A = new Ath__array1D<double>(11);
1078   //	for (uint ii= 0; ii<7; ii++) {
1079   // for (uint ii= 0; ii<3; ii++) {
1080   for (uint ii = 0; ii < 8; ii++) {
1081     double w = wTable[ii] * min_width;
1082     A->add(w);
1083   }
1084 
1085   return A;
1086 }
getSpaceTable(uint met)1087 Ath__array1D<double>* extProcess::getSpaceTable(uint met) {
1088   double min_spacing = getConductor(met)->_min_spacing;
1089 
1090   //	const double sTable[18]= {1.0, 1.2, 1.5, 1.7, 2.0, 2.25, 2.5, 2.75,
1091   // 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10};
1092   const double sTable[8] = {1.0, 1.5, 2.0, 2.5, 3, 4, 5, 10};
1093   // const double sTable[3]= {1.0, 1.5, 2.0};
1094 
1095   Ath__array1D<double>* A = new Ath__array1D<double>(8);
1096   for (uint ii = 0; ii < 8; ii++) {
1097     // for (uint ii= 0; ii<3; ii++) {
1098 
1099     double s = sTable[ii] * min_spacing;
1100     A->add(s);
1101   }
1102 
1103   return A;
1104 }
getDiagSpaceTable(uint met)1105 Ath__array1D<double>* extProcess::getDiagSpaceTable(uint met) {
1106   double min_spacing = getConductor(met)->_min_spacing;
1107   double min_width = getConductor(met)->_min_width;
1108   double p = min_spacing + min_width;
1109 
1110   const double sTable[7] = {0, 0.2, 0.5, 0.7, 1.0, 2.0, 3};
1111   //	const double sTable[3]= {0, 0.5, 1.0};
1112 
1113   Ath__array1D<double>* A = new Ath__array1D<double>(8);
1114   for (uint ii = 0; ii < 7; ii++) {
1115     //	for (uint ii= 0; ii<3; ii++) {
1116 
1117     double s = sTable[ii] * p;
1118     A->add(s);
1119   }
1120 
1121   return A;
1122 }
getDataRateTable(uint met)1123 Ath__array1D<double>* extProcess::getDataRateTable(uint met) {
1124   if (_dataRateTable)
1125     return _dataRateTable;
1126   Ath__array1D<double>* A = new Ath__array1D<double>(8);
1127   A->add(0.0);
1128   return A;
1129 }
readDataRateTable(Ath__parser * parser,const char * keyword)1130 void extProcess::readDataRateTable(Ath__parser* parser, const char* keyword) {
1131   if ((keyword != NULL) && (strcmp(keyword, parser->get(0)) != 0))
1132     return;
1133 
1134   if (parser->getWordCnt() < 1)
1135     return;
1136   Ath__array1D<double>* A = new Ath__array1D<double>(parser->getWordCnt() + 1);
1137   A->add(0.0);
1138   parser->getDoubleArray(A, 1);
1139   _dataRateTable = A;
1140   _thickVarFlag = true;
1141 }
getMaxMinFlag()1142 bool extProcess::getMaxMinFlag() { return _maxMinFlag; }
getThickVarFlag()1143 bool extProcess::getThickVarFlag() { return _thickVarFlag; }
getMasterConductor(uint met,uint wIndex,uint sIndex,double & w,double & s)1144 extMasterConductor* extProcess::getMasterConductor(uint met, uint wIndex,
1145                                                    uint sIndex, double& w,
1146                                                    double& s) {
1147   const double wTable[7] = {1.0, 1.5, 2.0, 2.5, 3, 3.5, 4};
1148   const double sTable[14] = {1.0,  1.2, 1.5, 1.7, 2.0, 2.25, 2.5,
1149                              2.75, 3,   3.5, 4,   4.5, 5,    6};
1150 
1151   extMasterConductor* m = getMasterConductor(met);
1152 
1153   w = wTable[wIndex] * getConductor(met)->_min_width;
1154   s = sTable[sIndex] * getConductor(met)->_min_spacing;
1155 
1156   return m;
1157 }
getVariation(uint met)1158 extVariation* extProcess::getVariation(uint met) {
1159   extConductor* m = getConductor(met);
1160 
1161   extVariation* v = NULL;
1162   if (m->_var_table_index > 0)
1163     v = _varTable->get(m->_var_table_index);
1164 
1165   return v;
1166 }
interpolate(double w,Ath__array1D<double> * X,Ath__array1D<double> * Y)1167 double extVariation::interpolate(double w, Ath__array1D<double>* X,
1168                                  Ath__array1D<double>* Y) {
1169   if (X->getCnt() < 2)
1170     return w;
1171 
1172   int jj = X->findNextBiggestIndex(w);
1173 
1174   if (jj >= (int)X->getCnt() - 1)
1175     jj = X->getCnt() - 2;
1176   else if (jj < 0)
1177     jj = 0;
1178 
1179   double w1 = X->get(jj);
1180   double w2 = X->get(jj + 1);
1181 
1182   double v1 = Y->get(jj);
1183   double v2 = Y->get(jj + 1);
1184 
1185   double slope = (v2 - v1) / (w2 - w1);
1186 
1187   double retVal = v2 - slope * (w2 - w);
1188 
1189   return retVal;
1190 }
getThickness(double w,uint dIndex)1191 double extVariation::getThickness(double w, uint dIndex) {
1192   return interpolate(w, _thicknessC->_width, _thicknessC->_vTable[dIndex]);
1193 }
getThicknessR(double w,uint dIndex)1194 double extVariation::getThicknessR(double w, uint dIndex) {
1195   return interpolate(w, _thicknessR->_width, _thicknessR->_vTable[dIndex]);
1196 }
getBottomWidth(double w,uint dIndex)1197 double extVariation::getBottomWidth(double w, uint dIndex) {
1198   return interpolate(w, _loWidthC->_width, _loWidthC->_vTable[dIndex]);
1199 }
getBottomWidthR(double w,uint dIndex)1200 double extVariation::getBottomWidthR(double w, uint dIndex) {
1201   return interpolate(w, _loWidthR->_width, _loWidthR->_vTable[dIndex]);
1202 }
getTopWidth(uint ii,uint jj)1203 double extVariation::getTopWidth(uint ii, uint jj) {
1204   return _hiWidthC->getVal(ii, jj);
1205 }
getTopWidthR(uint ii,uint jj)1206 double extVariation::getTopWidthR(uint ii, uint jj) {
1207   return _hiWidthR->getVal(ii, jj);
1208 }
getWidthTable()1209 Ath__array1D<double>* extVariation::getWidthTable() {
1210   return _hiWidthC->_width;
1211 }
getSpaceTable()1212 Ath__array1D<double>* extVariation::getSpaceTable() {
1213   return _hiWidthC->_space;
1214 }
getDataRateTable()1215 Ath__array1D<double>* extVariation::getDataRateTable() {
1216   return _loWidthC->_density;
1217 }
getPTable()1218 Ath__array1D<double>* extVariation::getPTable() {
1219   if (_p == NULL)
1220     return NULL;
1221   return _p->_p;
1222 }
getP(double w)1223 double extVariation::getP(double w) {
1224   if (_p == NULL)
1225     return 0;
1226   return interpolate(w, _p->_width, _p->_p);
1227 }
writeProcess(const char * filename)1228 void extProcess::writeProcess(const char* filename) {
1229   FILE* fp = openFile(filename, "w");
1230   Ath__parser parse;
1231 
1232   for (uint kk = 1; kk < _varTable->getCnt(); kk++) {
1233     _varTable->get(kk)->printVariation(fp, kk);
1234   }
1235 
1236   for (uint ii = 1; ii < _condTable->getCnt(); ii++) {
1237     extConductor* cond = _condTable->get(ii);
1238     cond->printConductor(fp, &parse);
1239   }
1240   for (uint jj = 1; jj < _dielTable->getCnt(); jj++) {
1241     extDielectric* diel = _dielTable->get(jj);
1242     diel->printDielectric(fp, &parse);
1243   }
1244   fclose(fp);
1245 }
readDoubleArray(Ath__parser * parser,const char * keyword)1246 Ath__array1D<double>* extVarTable::readDoubleArray(Ath__parser* parser,
1247                                                    const char* keyword) {
1248   if ((keyword != NULL) && (strcmp(keyword, parser->get(0)) != 0))
1249     return NULL;
1250 
1251   if (parser->getWordCnt() < 1)
1252     return NULL;
1253 
1254   Ath__array1D<double>* A = new Ath__array1D<double>(parser->getWordCnt());
1255   uint start = 0;
1256   if (keyword != NULL)
1257     start = 1;
1258   parser->getDoubleArray(A, start);
1259   return A;
1260 }
printOneLine(FILE * fp,Ath__array1D<double> * A,const char * header,const char * trail)1261 void extVarTable::printOneLine(FILE* fp, Ath__array1D<double>* A,
1262                                const char* header, const char* trail) {
1263   if (A == NULL)
1264     return;
1265 
1266   if (header != NULL)
1267     fprintf(fp, "%s ", header);
1268 
1269   for (uint ii = 0; ii < A->getCnt(); ii++)
1270     fprintf(fp, "%g ", A->get(ii));
1271 
1272   fprintf(fp, "%s", trail);
1273 }
readWidthSpacing2D(Ath__parser * parser,const char * keyword1,const char * keyword2,const char * keyword3,const char * key4)1274 int extVarTable::readWidthSpacing2D(Ath__parser* parser, const char* keyword1,
1275                                     const char* keyword2, const char* keyword3,
1276                                     const char* key4) {
1277   uint debug = 0;
1278 
1279   if (strcmp("}", parser->get(0)) == 0)
1280     return -1;
1281   _width = readDoubleArray(parser, keyword1);
1282 
1283   if (debug > 0)
1284     printOneLine(stdout, _width, keyword1, "\n");
1285 
1286   if (!(parser->parseNextLine() > 0))
1287     return -1;
1288 
1289   if (strcmp("Spacing", keyword2) == 0) {
1290     _space = readDoubleArray(parser, keyword2);
1291   } else if (strcmp("Deff", keyword2) == 0) {
1292     _density = readDoubleArray(parser, keyword2);
1293     for (uint jj = 0; jj < _density->getCnt(); jj++)
1294       _vTable[jj] = new Ath__array1D<double>(_width->getCnt());
1295     if (debug > 0) {
1296       printOneLine(stdout, _space, keyword2, "\n");
1297       printOneLine(stdout, _density, keyword2, "\n");
1298     }
1299   } else if (strcmp("P", keyword2) == 0) {
1300     _p = readDoubleArray(parser, keyword2);
1301     _rowCnt = 1;
1302     if (debug > 0)
1303       printOneLine(stdout, _p, keyword2, "\n");
1304   }
1305 
1306   if (!(parser->parseNextLine() > 0))
1307     return -1;
1308   if (strcmp("}", keyword3) == 0) {
1309     return 1;
1310   } else if (strcmp(keyword3, parser->get(0)) != 0) {
1311     return -1;
1312   }
1313 
1314   uint ii = 0;
1315   while (parser->parseNextLine() > 0) {
1316     if (strcmp(key4, parser->get(0)) == 0) {
1317       break;
1318     }
1319     if (strcmp("}", parser->get(0)) == 0)
1320       break;
1321     if (_space != NULL) {
1322       _vTable[ii++] = readDoubleArray(parser, NULL);
1323       if (debug > 0)
1324         printOneLine(stdout, _vTable[ii - 1], NULL, "\n");
1325     } else {
1326       ii++;
1327       for (int jj = 0; jj < parser->getWordCnt(); jj++)
1328         _vTable[jj]->add(parser->getDouble(jj));
1329     }
1330   }
1331   if (debug > 0) {
1332     if (_density != NULL) {
1333       for (uint jj = 0; jj < _density->getCnt(); jj++)
1334         printOneLine(stdout, _vTable[jj], NULL, "\n");
1335     }
1336   }
1337 
1338   if (_space != NULL)
1339     _rowCnt = ii;
1340   else
1341     _rowCnt = _density->getCnt();
1342 
1343   return ii;
1344 }
printTable(FILE * fp,const char * valKey)1345 void extVarTable::printTable(FILE* fp, const char* valKey) {
1346   printOneLine(fp, _width, "Width", "\n");
1347 
1348   if (_space != NULL)
1349     printOneLine(fp, _space, "Spacing", "\n");
1350   else if (_density != NULL)
1351     printOneLine(fp, _space, "Deff", "\n");
1352   else {
1353     printOneLine(fp, _p, "P", "\n");
1354     return;
1355   }
1356 
1357   fprintf(fp, "%s\n", valKey);
1358 
1359   for (uint ii = 0; ii < _rowCnt; ii++)
1360     printOneLine(fp, _vTable[ii], NULL, "\n");
1361 }
printVariation(FILE * fp,uint n)1362 void extVariation::printVariation(FILE* fp, uint n) {
1363   fprintf(fp, "VAR_TABLE %d {\n", n);
1364 
1365   _hiWidthC->printTable(fp, "hi_cWidth_eff");
1366   _loWidthC->printTable(fp, "lo_cWidth_delta");
1367   _thicknessC->printTable(fp, "c_thickness_eff");
1368 
1369   _hiWidthR->printTable(fp, "hi_rWidth_eff");
1370   _loWidthR->printTable(fp, "lo_rWidth_delta");
1371   _thicknessR->printTable(fp, "r_thickness_eff");
1372   if (_p != NULL)
1373     _p->printTable(fp, "P");
1374 
1375   fprintf(fp, "}\n");
1376 }
readVarTable(Ath__parser * parser,const char * key1,const char * key2,const char * key3,const char * endKey)1377 extVarTable* extVariation::readVarTable(Ath__parser* parser, const char* key1,
1378                                         const char* key2, const char* key3,
1379                                         const char* endKey) {
1380   extVarTable* V = new extVarTable(20);  // TODO
1381   if (V->readWidthSpacing2D(parser, key1, key2, key3, endKey) < 1) {
1382     //		fprintf(stdout, "Cannot read VarTable section: <%s>", key3);
1383     logger_->warn(RCX, 155, "Can't read VarTable section: <{}>", key3);
1384     delete V;
1385     return NULL;
1386   }
1387 
1388   return V;
1389 }
readVariation(Ath__parser * parser)1390 int extVariation::readVariation(Ath__parser* parser) {
1391   _hiWidthC =
1392       readVarTable(parser, "Width", "Spacing", "hi_cWidth_eff", "Width");
1393   _loWidthC = readVarTable(parser, "Width", "Deff", "lo_cWidth_delta", "Width");
1394   _thicknessC =
1395       readVarTable(parser, "Width", "Deff", "c_thickness_eff", "Width");
1396 
1397   _hiWidthR =
1398       readVarTable(parser, "Width", "Spacing", "hi_rWidth_eff", "Width");
1399   _loWidthR = readVarTable(parser, "Width", "Deff", "lo_rWidth_delta", "Width");
1400   _thicknessR =
1401       readVarTable(parser, "Width", "Deff", "r_thickness_eff", "Width");
1402   if (strcmp("}", parser->get(0)) == 0)
1403     return 0;
1404   _p = readVarTable(parser, "Width", "P", "}", "");
1405 
1406   return 0;
1407 }
readProcess(const char * name,char * filename)1408 uint extProcess::readProcess(const char* name, char* filename) {
1409   uint debug = 0;
1410   // create process object
1411 
1412   // read process numbers
1413   Ath__parser parser;
1414   parser.addSeparator("\r");
1415   parser.openFile(filename);
1416 
1417   while (parser.parseNextLine() > 0) {
1418     if (strcmp("PROCESS", parser.get(0)) == 0) {
1419       while (parser.parseNextLine() > 0) {
1420         if (strcmp("}", parser.get(0)) == 0)
1421           break;
1422       }
1423     } else if (strcmp("THICKNESS_VARIATION", parser.get(0)) == 0) {
1424       readDataRateTable(&parser, "THICKNESS_VARIATION");
1425     } else if (strcmp("VAR_TABLE", parser.get(0)) == 0) {
1426       parser.setDbg(debug);
1427       parser.getInt(1);
1428 
1429       extVariation* extVar = new extVariation();
1430       extVar->setLogger(logger_);
1431 
1432       while (parser.parseNextLine() > 0) {
1433         if (strcmp("}", parser.get(0)) == 0)
1434           break;
1435         extVar->readVariation(&parser);
1436 
1437         parser.setDbg(0);
1438 
1439         if (strcmp("}", parser.get(0)) == 0)
1440           break;
1441       }
1442       _varTable->add(extVar);
1443     } else if (strcmp("CONDUCTOR", parser.get(0)) == 0) {
1444       extConductor* cond = new extConductor(logger_);
1445       strcpy(cond->_name, parser.get(1));
1446 
1447       while (parser.parseNextLine() > 0) {
1448         if (strcmp("}", parser.get(0)) == 0)
1449           break;
1450 
1451         cond->readConductor(&parser);
1452       }
1453       _condTable->add(cond);
1454     } else if (strcmp("DIELECTRIC", parser.get(0)) == 0) {
1455       extDielectric* diel = new extDielectric(logger_);
1456       if (parser.getWordCnt() > 2)
1457         strcpy(diel->_name, parser.get(1));
1458 
1459       while (parser.parseNextLine() > 0) {
1460         if (strcmp("}", parser.get(0)) == 0)
1461           break;
1462 
1463         diel->readDielectric(&parser);
1464       }
1465       _dielTable->add(diel);
1466     } else if (strcmp("SETMAXMINFLAG", parser.get(0)) == 0) {
1467       _maxMinFlag = true;
1468     }
1469   }
1470   createMasterLayers();
1471 
1472   // create dielectric "planes"
1473 
1474   //	uint layerCnt= 8;
1475   //	extRCModel *m= new extRCModel(layerCnt, (char *) name);
1476   //	_modelTable->add(m);
1477 
1478   return 0;
1479 }
extProcess(uint condCnt,uint dielCnt,Logger * logger)1480 extProcess::extProcess(uint condCnt, uint dielCnt, Logger* logger) {
1481   logger_ = logger;
1482   _condTable = new Ath__array1D<extConductor*>(condCnt);
1483   _condTable->add(NULL);
1484   _maxMinFlag = false;
1485   _dielTable = new Ath__array1D<extDielectric*>(dielCnt);
1486   _dielTable->add(NULL);
1487   _masterConductorTable = new Ath__array1D<extMasterConductor*>(condCnt);
1488   _masterConductorTable->add(NULL);
1489   _masterDielectricTable = new Ath__array1D<extMasterConductor*>(dielCnt);
1490   _masterDielectricTable->add(NULL);
1491 
1492   _varTable = new Ath__array1D<extVariation*>(condCnt);
1493   _varTable->add(NULL);
1494   _dataRateTable = NULL;
1495   _thickVarFlag = false;
1496 }
extVarTable(uint rowCnt)1497 extVarTable::extVarTable(uint rowCnt) {
1498   _rowCnt = rowCnt;
1499   _vTable = new Ath__array1D<double>* [rowCnt];
1500   _density = NULL;
1501   _space = NULL;
1502   _width = NULL;
1503   _p = NULL;
1504 }
~extVarTable()1505 extVarTable::~extVarTable() {
1506   for (uint ii = 0; ii < _rowCnt; ii++) {
1507     if (_vTable[ii] != NULL)
1508       delete _vTable[ii];
1509   }
1510   delete[] _vTable;
1511 
1512   if (_density != NULL)
1513     delete _density;
1514   if (_space != NULL)
1515     delete _space;
1516   if (_width != NULL)
1517     delete _width;
1518   if (_p != NULL)
1519     delete _p;
1520   _p = NULL;
1521   _density = NULL;
1522   _space = NULL;
1523   _width = NULL;
1524 }
1525 
1526 }  // namespace rcx
1527