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