bem_welement.itcl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. # --------------------------------------------------------------------
  2. #
  3. # mmtl_welement.itcl
  4. #
  5. # The class in this file can generate an HSPICE W-element
  6. # from the CSDL description, and MMTL results.
  7. #
  8. # General usage is to create a Welement object, and call
  9. # the welementString method. The method requires two
  10. # sources of data: first the file name containing the
  11. # MMTL results; and second the name of the Stackup object
  12. # which will be visited to get additional information.
  13. #
  14. # The MMTL results file provides electrostatic inductance
  15. # (B) and inductance (L) matrices.
  16. #
  17. # The Stackup object provides conductor areas and
  18. # conductivities which are used to compute DC and AC
  19. # resistance.
  20. #
  21. #
  22. # Bob Techentin
  23. # June 11, 2002
  24. #
  25. # Copyright 2002-2004 Mayo Foundation. All Rights Reserved.
  26. # $Id: bem_welement.itcl,v 1.6 2004/09/10 19:23:02 techenti Exp $
  27. #
  28. # --------------------------------------------------------------------
  29. # --------------------------------------------------------------------
  30. #
  31. # Like several other components of the MMTL simulation suite,
  32. # the Welement class acts as a visitor to the CSDL cross section
  33. # description.
  34. #
  35. # Much of the functionality is based on the Tcl script named
  36. # mmtl2hspicew or sim2hspicew, circa 1998.
  37. #
  38. # --------------------------------------------------------------------
  39. package provide bem 1.0
  40. # --------------------------------------------------------------------
  41. #
  42. # itcl::class Welement
  43. #
  44. # This class is a visitor to the CSDL structures. It can generate
  45. # an HSPICE W-element from an MMTL results file and a layer Stackup.
  46. #
  47. # --------------------------------------------------------------------
  48. itcl::class Welement {
  49. #inherit CSDLvisitor
  50. public variable welement
  51. public variable headerText
  52. public variable signalName
  53. public variable signalNames
  54. public variable conductorArea
  55. public variable conductorCircumference
  56. public variable conductorConductivity
  57. public variable N
  58. public variable L0
  59. public variable C0
  60. public variable R0
  61. public variable G0
  62. public variable Rs
  63. public variable Gd
  64. method dump {} {
  65. puts "welement: $welement"
  66. puts "headertext: $headerText"
  67. puts "signalnames: $signalNames"
  68. catch {parray conductorArea}
  69. catch {parray conductorCircumference}
  70. catch {parray conductorConductivity}
  71. puts "N: $N"
  72. catch {parray L0}
  73. catch {parray C0}
  74. catch {parray R0}
  75. catch {parray G0}
  76. catch {parray Rs}
  77. catch {parray Gd}
  78. }
  79. # Produce and return a W element description
  80. # (as a string)
  81. method welementString { mmtlResultsFile }
  82. # Helper methods
  83. private method addLine { string }
  84. private method addMatrix { string }
  85. private method warningMessage { msgText }
  86. private method initialize { }
  87. private method readMMTLfile { filename }
  88. private method computeLosses { }
  89. # HLCSDL - Stackup Structures
  90. method visitStackup { stackup x y }
  91. method visitGroundPlane { groundPlane x y }
  92. method visitDielectricLayer { dielectricLayer x y }
  93. method visitRectangleDielectric { rectangleDielectric x y }
  94. method visitRectangleConductors { rectangleConductors x y }
  95. method visitTrapezoidConductors { trapezoidConductors x y }
  96. method visitCircleConductors { circleConductors x y }
  97. # LLCSDO - low level structures
  98. method visitDielectric { dielectric x y }
  99. method visitConductor { conductor x y }
  100. method visitGround { ground x y }
  101. method visitRectangle { rectangle x y }
  102. method visitTrapezoid { trapezoid x y }
  103. method visitCircle { circle x y }
  104. method visitLayer { layer x y }
  105. }
  106. #-------------------------------------------------------------
  107. #
  108. # Helper Methods
  109. #
  110. #-------------------------------------------------------------
  111. #-------------------------------------------------------------
  112. #
  113. # NAME welementString
  114. #
  115. # DESCRIPTION
  116. #
  117. # Returns a string representing the W-element description
  118. # of the layer stackup described by the specified layer
  119. # stackup and MMTL results file.
  120. #
  121. #-------------------------------------------------------------
  122. itcl::body Welement::welementString {mmtlResultsFile} {
  123. initialize
  124. #-------------------------------------------------------------
  125. # read the MMTL results
  126. #-------------------------------------------------------------
  127. readMMTLfile $mmtlResultsFile
  128. #-------------------------------------------------------------
  129. # Add AC and DC resistance from the layer stackup
  130. #-------------------------------------------------------------
  131. computeLosses
  132. #-------------------------------------------------------------
  133. # Build the W-element string
  134. #-------------------------------------------------------------
  135. addLine "*--------------------------------------------"
  136. addLine "*"
  137. addLine "* RLCG parameters for W-Element"
  138. addLine "* frequency-dependent transmission line"
  139. addLine "*"
  140. addLine "*"
  141. addLine "* MMTL File Name: $mmtlResultsFile"
  142. addLine "* [clock format [clock seconds]]"
  143. addLine "*"
  144. addLine "*--------------------------------------------"
  145. addLine "*"
  146. foreach textLine $headerText {
  147. addLine "* | $textLine"
  148. }
  149. addLine "* |"
  150. addLine "* | Signal Names (in order):"
  151. foreach name $signalNames {
  152. addLine "* | $name"
  153. }
  154. addLine "*"
  155. addLine "*--------------------------------------------"
  156. addLine "*"
  157. addLine "* N = number of signal conductors"
  158. addLine "*"
  159. addLine "*--------------------------------------------"
  160. addLine "$N"
  161. foreach matrixName {L0 C0 R0 G0 Rs Gd} {
  162. addLine ""
  163. addLine "*--------------------------------------------"
  164. addLine "*"
  165. addLine "* $matrixName"
  166. addLine "*"
  167. addLine "*--------------------------------------------"
  168. addMatrix $matrixName
  169. }
  170. addLine ""
  171. }
  172. #-------------------------------------------------------------
  173. #
  174. # NAME addLine
  175. #
  176. # DESCRIPTION
  177. #
  178. # Adds a line to the W-element string, including a
  179. # newline. Just a helper function.
  180. #
  181. #-------------------------------------------------------------
  182. itcl::body Welement::addLine { string } {
  183. append welement "$string\n"
  184. }
  185. #-------------------------------------------------------------
  186. #
  187. # NAME addMatrix
  188. #
  189. # DESCRIPTION
  190. #
  191. # This proc formats the 2D matrix (really an array) by
  192. # indexing through i and j and appending to the
  193. # w-element text.
  194. #
  195. #-------------------------------------------------------------
  196. itcl::body Welement::addMatrix { matrixName } {
  197. upvar $matrixName m
  198. for {set i 0} {$i<$N} {incr i} {
  199. for {set j 0} {$j<=$i} {incr j} {
  200. append welement [format "%g\t" $m($i,$j)]
  201. }
  202. append welement "\n"
  203. }
  204. }
  205. #-------------------------------------------------------------
  206. #
  207. # NAME warningMessage
  208. #
  209. # DESCRIPTION
  210. #
  211. # This method formats and appends a warning message to
  212. # the "headerText", which is included in the W-element
  213. # RLCG output file.
  214. #
  215. #-------------------------------------------------------------
  216. itcl::body Welement::warningMessage { msgText } {
  217. set fullText "Warning: $msgText"
  218. lappend headerText $fullText
  219. }
  220. #-------------------------------------------------------------
  221. #
  222. # NAME Welement::initialize
  223. #
  224. # DESCRIPTION
  225. #
  226. # This method initializes the object's global data,
  227. # removing any previous data.
  228. #
  229. #-------------------------------------------------------------
  230. itcl::body Welement::initialize { } {
  231. #-------------------------------------------------------------
  232. # Initialize all variables
  233. #-------------------------------------------------------------
  234. set welement ""
  235. set headerText {}
  236. set signalNames {}
  237. array unset conductorArea *
  238. array unset conductorCircumference *
  239. array unset conductorConductivity *
  240. set N ""
  241. foreach name [array names L0] {
  242. unset L0($name)
  243. }
  244. foreach name [array names C0] {
  245. unset C0($name)
  246. }
  247. foreach name [array names R0] {
  248. unset R0($name)
  249. }
  250. foreach name [array names G0] {
  251. unset G0($name)
  252. }
  253. foreach name [array names Rs] {
  254. unset Rs($name)
  255. }
  256. foreach name [array names Gd] {
  257. unset Gd($name)
  258. }
  259. }
  260. #-------------------------------------------------------------
  261. #
  262. # NAME readMMTLfile
  263. #
  264. # DESCRIPTION
  265. #
  266. # This method reads the specified MMTL results file and
  267. # sets C0, L0, and R0 arrays. It copies leading text from
  268. # the SIM results into the headerText variable and defines
  269. # the number of conductors, N. This proc also sets default
  270. # values for all matrics, including G0, Rs, and Gd.
  271. #
  272. #-------------------------------------------------------------
  273. itcl::body Welement::readMMTLfile { filename } {
  274. #-------------------------------------------------------------
  275. # Set up header text
  276. #-------------------------------------------------------------
  277. lappend headerText " MMTL Simulation data from"
  278. lappend headerText " $filename"
  279. set readingHeader 1
  280. #-------------------------------------------------------------
  281. # Locate and open the MMTL results file
  282. #-------------------------------------------------------------
  283. if {! [file isfile $filename]} {
  284. error "Error: MMTL results file '$filename' does not exist"
  285. }
  286. if { [catch {open $filename "r"} inFile ] } {
  287. error "Error: cannot open MMTL results file '$filename'"
  288. }
  289. #-------------------------------------------------------------
  290. # Process the File Header
  291. #
  292. # Read and ignore everything up to the first "Mutual" line,
  293. # except that we capture number of signal lines.
  294. #-------------------------------------------------------------
  295. gets $inFile textLine
  296. while { ! [string match "Mutual*" $textLine] } {
  297. if { [eof $inFile] } {
  298. error "Error: Invalid MMTL results File '$filename'"
  299. }
  300. lappend headerText "$textLine"
  301. if {[regexp "Number of Signal Lines" $textLine]} {
  302. regsub ".*=" $textLine "" N
  303. }
  304. gets $inFile textLine
  305. }
  306. #-------------------------------------------------------------
  307. # Process remainder of MMTL file, searching for keywords
  308. # at the beginning of each matrix section. Each section
  309. # is led by a line like:
  310. # B(Active Signal, Passive Signal)
  311. # followed by NxN matrix entries.
  312. #
  313. # Note that the signal names are in order for generated
  314. # cross sections, but they could also be arbitrarily named,
  315. # so we save the signal names in the headerText. We also
  316. # store the order of the signal names so that we can later
  317. # reconstruct each signal's position in the matrix.
  318. #
  319. # Note that we could calculate capacitance matrix from the
  320. # electrostatic induction matrix, B, but the HSPICE W element
  321. # is really expecting the B matrix for C0. Self Capacitance
  322. # (diagonal elements) of the capacitance matrix would be
  323. # the sum of the row (e.g., C11=B11+B12), while mutual
  324. # capacitance (off-diagonal elements) would be the negative
  325. # of the corresponding induction value (e.g., C12=-B12).
  326. #-------------------------------------------------------------
  327. while {! [eof $inFile]} {
  328. regexp {[^[:space:]]*} $textLine token
  329. switch $token {
  330. "B(Active" {
  331. # Copy "B" matrix into C0
  332. for {set i 0} {$i<$N} {incr i} {
  333. for {set j 0} {$j<$N} {incr j} {
  334. gets $inFile textLine
  335. regsub ".*=" $textLine "" C0($i,$j)
  336. }
  337. # Capture the signal name, too.
  338. scan $textLine "B(%s" sigName
  339. lappend signalNames $sigName
  340. }
  341. }
  342. "L(Active" {
  343. # Copy "L" matrix into L0
  344. for {set i 0} {$i<$N} {incr i} {
  345. for {set j 0} {$j<$N} {incr j} {
  346. gets $inFile textLine
  347. regsub ".*=" $textLine "" L0($i,$j)
  348. }
  349. }
  350. }
  351. "Rdc(Active" {
  352. # Copy "Rdc" matrix into R0
  353. for {set i 0} {$i<$N} {incr i} {
  354. for {set j 0} {$j<$N} {incr j} {
  355. gets $inFile textLine
  356. regsub ".*=" $textLine "" R0($i,$j)
  357. }
  358. }
  359. }
  360. }
  361. # Read next line of file
  362. gets $inFile textLine
  363. } ;# end of while {! eof $inFile}
  364. #-------------------------------------------------------------
  365. # Done with the MMTL results file
  366. #-------------------------------------------------------------
  367. close $inFile
  368. #-------------------------------------------------------------
  369. # Set all missing matrix elements to default (0.0)
  370. #-------------------------------------------------------------
  371. for {set i 0} {$i<$N} {incr i} {
  372. for {set j 0} {$j<$N} {incr j} {
  373. if { ! [info exists L0($i,$j)] } { set L0($i,$j) 0.0 }
  374. if { ! [info exists R0($i,$j)] } { set R0($i,$j) 0.0 }
  375. if { ! [info exists G0($i,$j)] } { set G0($i,$j) 0.0 }
  376. if { ! [info exists Rs($i,$j)] } { set Rs($i,$j) 0.0 }
  377. if { ! [info exists Gd($i,$j)] } { set Gd($i,$j) 0.0 }
  378. }
  379. }
  380. }
  381. #-------------------------------------------------------------
  382. #
  383. # NAME Welement::computeLosses
  384. #
  385. # DESCRIPTION
  386. #
  387. # This method computes the loss factors for the MMTL
  388. # simulation results (which are loss free) by visiting
  389. # the specified layer stackup, and computing both DC and
  390. # AC losses from the conductor circumference, area
  391. # and conductivity.
  392. #
  393. # The loss values are stored in R0 and Rs.
  394. #
  395. #-------------------------------------------------------------
  396. itcl::body Welement::computeLosses { } {
  397. set PI 3.141592654
  398. set MU_0 1.25663706E-6
  399. #--------------------------------------------------------------
  400. # Visit the layer stackup to capture conductor
  401. # areas and conductivities
  402. #--------------------------------------------------------------
  403. ::Stackup::accept $this 0 0
  404. #--------------------------------------------------------------
  405. # Capture length units from stackup for conversion to SI
  406. #--------------------------------------------------------------
  407. set units $::Stackup::defaultLengthUnits
  408. #--------------------------------------------------------------
  409. # Iterate over all conductors.
  410. # Note that we're just computing the diagonal elements
  411. # of the R0 and Rs matrices, so we only have one loop.
  412. #--------------------------------------------------------------
  413. for {set i 0} {$i<$N} {incr i} {
  414. #--------------------------------------------------------------
  415. # Convert the MMTL signal name to the csdl signal name.
  416. # MMTL Signal names are of the form <name><type><num> where
  417. # <name> corresponds to the HLCSDL object name,
  418. # <type> is "R", "T", or "C" for the type of conductor, and
  419. # <num> is an increasing integer, just like $i here.
  420. #--------------------------------------------------------------
  421. set name [lindex $signalNames $i]
  422. puts -nonewline "changing conductor $i named $name"
  423. regsub {[RTC]\d+$} $name "" name
  424. puts " to $name"
  425. #--------------------------------------------------------------
  426. # Get usefull quantities
  427. #--------------------------------------------------------------
  428. set area $conductorArea($name)
  429. set circ $conductorCircumference($name)
  430. set cond $conductorConductivity($name)
  431. #--------------------------------------------------------------
  432. # Convert to SI units.
  433. # We know that area and circ are in default units and must
  434. # be converted. But we convert cond only if necessary.
  435. #--------------------------------------------------------------
  436. set area [units::convert "$area$units^2" "meters^2"]
  437. set circ [units::convert "$circ$units" "meters"]
  438. if { ! [string is double $cond] } {
  439. set cond [units::convert $cond "siemens/meter"]
  440. }
  441. #--------------------------------------------------------------
  442. # Compute values according to formulas
  443. #
  444. # Rdc = 1/(area*conductivity) ohms/meter
  445. # Rac = sqrt(PI*MU_0/conductivity)/(circumference) siemens/meter^2
  446. #--------------------------------------------------------------
  447. set rdc [expr {1.0/($area*$cond)}]
  448. set rac [expr {sqrt(($PI*$MU_0)/$cond)/($circ)}]
  449. #--------------------------------------------------------------
  450. # Check for disparity between newly computed Rdc value
  451. # and any value that might have come from MMTL (lossy version)
  452. # Generate a warning if there is a > 10% difference.
  453. #--------------------------------------------------------------
  454. if { [info exists R0($i,$i)] } {
  455. set ratio [expr {abs($R0($i,$i)/$rdc)}]
  456. if { ($ratio<0.9) || ($ratio>1.1) } {
  457. warningMessage "Using Formula for Rdc($i,$i)=$rdc, replacing MMTL value of $R0($i,$i)"
  458. }
  459. }
  460. #--------------------------------------------------------------
  461. # Assign values
  462. #--------------------------------------------------------------
  463. set R0($i,$i) $rdc
  464. set Rs($i,$i) $rac
  465. }
  466. #--------------------------------------------------------------
  467. # Set off-diagonals to zero
  468. #--------------------------------------------------------------
  469. for {set i 0} {$i<$N} {incr i} {
  470. for {set j 0} {$j<$N} {incr j} {
  471. if { $i != $j } {
  472. set R0($i,$j) 0.0
  473. set Rs($i,$j) 0.0
  474. }
  475. }
  476. }
  477. }
  478. #-------------------------------------------------------------
  479. #
  480. # NAME do_help
  481. #
  482. # DESCRIPTION
  483. #
  484. # Returns help text about the sim2hspicew utility.
  485. # This can be "put" on stdout, or displayed in a gui
  486. # window.
  487. #
  488. #-------------------------------------------------------------
  489. proc do_help { } {
  490. return {
  491. SIM 2 HSPICE W-Element Converter
  492. This script constructs an HSPICE W-Elelement model rlcg description
  493. based on the B, L, and Rdc matrices in SIM results files. It can
  494. read files of types:
  495. result BEM SIM (result) results
  496. electro_results_2dly 2DLY SIM results
  497. electro_results_2dlf 2DLF SIM results
  498. The capacitance matrix C0 is copied from SIM's Electrostatic
  499. Induction matrix B. (B is NOT converted into a capacitance matrix by
  500. summing the rows for the diagonal elements and changing the sign on
  501. the off-diagonal elements.) The inductance matrix L0 is copied
  502. directly from SIM's Inductance matrix, L. If the SIM results file
  503. contains Rdc (BEM SIM only), then these values are used for R0.
  504. If one of the cross section generating programs was used to generate
  505. the SIM data file (i.e. there is also an nsim_log file in the same
  506. directory), the script will read the geometry information and apply
  507. formulas for calculating R0 and Rs. If the formula value and the SIM
  508. value for R0 differ by more than 10%, a warning message is issued, but
  509. the formula values are always used.
  510. The formulas are:
  511. R0 = Rdc = 1 / (width * height) ohms/meter
  512. Rs = Rac = sqrt(PI * MU_0 / c) / (width + height) henrys/meter
  513. Where PI=3.141592654, MU_0=1.25663706E-6 henrys/meter (permeability of
  514. free-space), and c is the metal conductivity, which defaults to 5.92e7
  515. siemens/meter (copper).
  516. The W-element RLCG data is written (by default) the file hspice-w.rlcg
  517. in the same directory as the sim results. The rlcg file contains a
  518. header describing its origins and any warning messages that might have
  519. been generated during its construction.
  520. Command Line Swtiches
  521. -help - prints this message
  522. -c - generate output (rlcg file) on stdout
  523. -o filename - write the rlcg file to the specified file
  524. }
  525. # end of help text
  526. }
  527. # HLCSDL - Stackup Structures
  528. itcl::body Welement::visitStackup { stackup x y } {
  529. foreach struct $Stackup::structureList {
  530. $struct accept $this 0 0
  531. }
  532. }
  533. itcl::body Welement::visitGroundPlane { groundPlane x y } {}
  534. itcl::body Welement::visitDielectricLayer { dielectricLayer x y } {}
  535. itcl::body Welement::visitRectangleDielectric { rectangleDielectric x y } {}
  536. #---------------------------------------------------------------
  537. # Save the name of the HLCSDL object, as we'll need it
  538. # later to correlate with the signal names fromm the
  539. # MMTL results file.
  540. #---------------------------------------------------------------
  541. itcl::body Welement::visitRectangleConductors { rectangleConductors x y } {
  542. set signalName $rectangleConductors
  543. }
  544. itcl::body Welement::visitTrapezoidConductors { trapezoidConductors x y } {
  545. set signalName $trapezoidConductors
  546. }
  547. itcl::body Welement::visitCircleConductors { circleConductors x y } {
  548. set signalName $circleConductors
  549. }
  550. # LLCSDO - low level structures
  551. itcl::body Welement::visitDielectric { dielectric x y } {}
  552. #---------------------------------------------------------------
  553. #
  554. # Welement::visitConductor
  555. #
  556. # Each time we visit a conductor, store the conductor
  557. # area and conductivity for later AC/DC resistance
  558. # calculations. Store them based
  559. #
  560. #---------------------------------------------------------------
  561. itcl::body Welement::visitConductor { conductor x y } {
  562. # Save conductor values
  563. set shape [$conductor cget -shape]
  564. set conductorArea($signalName) [$shape area]
  565. set conductorCircumference($signalName) [$shape circumference]
  566. set conductorConductivity($signalName) [$conductor cget -conductivity]
  567. }
  568. itcl::body Welement::visitGround { ground x y} {}
  569. itcl::body Welement::visitRectangle { rectangle xp yp } {}
  570. itcl::body Welement::visitTrapezoid { trapezoid xp yp } {}
  571. itcl::body Welement::visitCircle { circle xp yp } {}
  572. itcl::body Welement::visitLayer { layer x y } {}