gtl_tutorial.htm 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
  4. <title>Polygon Usage</title>
  5. </head>
  6. <body>
  7. <h1>Layout Versus Schematic Tutorial</h1>
  8. <p>In this tutorial we will implement a toy VLSI layout verification
  9. application.&nbsp; In VLSI CAD an important step of design is the sign off check
  10. that verifies that the physical layout as drawn by mask designers and automated
  11. tools implements the logical schematic specified by design engineers.&nbsp;
  12. Physical layout is modeled as polygons on layers that are used to print the
  13. layout to the silicon wafer during manufacture.&nbsp; It is much better to find
  14. physical design mistakes before spending millions of dollars to prepare
  15. lithography masks and run a test lot of wafers.</p>
  16. <p>Real layout file formats are binary and often compressed and represent a
  17. folded hierarchical model of layout where a group of polygons can be grouped
  18. into a cell and instantiated as a group into other cells.&nbsp; For this
  19. tutorial we assume a simplified ascii layout file format with no design
  20. hierarchy, which we would call &quot;flat&quot; in VLSI jargon.&nbsp; Similarly we assume
  21. a flat, ascii logical schematic net list file format.&nbsp; A net is a named
  22. electrical connection in a circuit design.&nbsp; The goal of the layout
  23. verification tutorial is to parse these two file formats, apply geometry
  24. operations provided by Boost.Polygon on the layout data to generate a logical
  25. schematic that represents what is implemented in the physical layout and then
  26. compare the input schematic with the generated schematic to determine whether
  27. they are the same.</p>
  28. <p>First let us define some objects that we will need in the design of our toy
  29. layout verification application:</p>
  30. <p>Layout Rectangle: An axis-parallel rectangle with a layer associated<br>
  31. Layout Pin: An axis-parallel rectangle with a layer and net (electrical signal)
  32. name associated<br>
  33. Layout Database: An associative container of layer name to polygon set<br>
  34. Connectivity Database: An associative container of net name to layout database<br>
  35. Physical Device: A specific geometric arrangement on several layers with one or
  36. more input net and one output net<br>
  37. Logical Net: A named graph node<br>
  38. Logical Device: An un-named graph node with a device type<br>
  39. Logical Pin: A special net that defines an input or output for the circuit<br>
  40. Schematic Database: A graph consisting of nets and logical
  41. devices</p>
  42. <p>Next let's define the sequence of operations performed by our toy
  43. layout versus schematic application:</p>
  44. <p>Parse Layout: Stream layout rectangles and polygons into a layout database
  45. and stream layout pins into a connectivity database<br>
  46. Extract Connectivity: Add polygons from layout database to connectivity database
  47. by physical touch or overlap relationship<br>
  48. Extract Devices: Populate a schematic database with logical devices based on
  49. physical devices identified within the layout geometry and extract their
  50. terminals from the
  51. connectivity database<br>
  52. Extract Net List: Complete graph represented in schematic database derived from
  53. layout<br>
  54. Parse Schematic: Stream logical nets, devices and pins into a schematic
  55. database<br>
  56. Compare Schematics: Evaluate whether extracted schematic database is equivalent
  57. to input schematic database and output result</p>
  58. <p>To test our application we will extract single logic gates.&nbsp; A logic
  59. gate is several transistors that work together to perform a specific logic
  60. function.&nbsp; Logic functions include the commonly understood Boolean logic
  61. operations such as Boolean AND, OR, XOR and INVERT.&nbsp; Also frequently used
  62. are NAND and NOR, which are respectively AND and OR operations followed by an
  63. INVERT operation.&nbsp; A NAND gate can be implemented in the CMOS circuit
  64. family with four transistors.&nbsp; The NAND gate has two inputs and one output.&nbsp;
  65. Each input goes to two transistors, one p-type transistor and one n-type
  66. transistor.&nbsp; The &quot;p&quot; stands for positive and the &quot;n&quot; stands for negative.&nbsp;
  67. When the p-type transistor is on
  68. it pulls the output up to the same voltage as the voltage source.&nbsp; When the
  69. n-type transistor is on it pulls the output down to the same voltage as the
  70. ground.&nbsp; The process of creating a p-type transistor begins by &quot;doping&quot; the silicon
  71. substrate to create n-type material.&nbsp; This area of n-type material will be
  72. called the NWELL layer in our test data.&nbsp; Within the area of NWELL a
  73. p-diffusion area is created by further doping the silicon to create p-type
  74. material.&nbsp; This area of p-type material will be called PDIFF in our test
  75. data.&nbsp; Through the middle of a PDIFF area bars of poly-silicon are grown
  76. that create conductive lines over the diffusion area.&nbsp; The area of
  77. poly-silicon material will be called POLY in our test data.&nbsp; Under some of these
  78. poly-silicon lines a thin layer of silicon-oxide provides insulation but allows
  79. the voltage field of the poly-silicon to interact with the diffusion.&nbsp; Each
  80. of these insulated poly-silicon lines is the &quot;gate&quot; of a transistor.&nbsp;
  81. The gate area will be called GATE in our test data.&nbsp; When the
  82. voltage at the gate is the same as the ground voltage the p-type transistor is
  83. &quot;on&quot; and can pass current from the voltage source to the output .&nbsp; The
  84. poly-silicon lines that are not insulated create electrical connections to the
  85. transistor for output signals and source voltage.&nbsp; The n-type transistor
  86. differs from the p-type in that its diffusion is n-type material outside of NWELL area.&nbsp; Current can pass from the output to the ground when the
  87. voltage at the gate of the n-type transistor is at the source voltage level.&nbsp;
  88. Above the poly-silicon layer is a layer of silicon-oxide insulator with holes
  89. cut out of it that get filled in with metal.&nbsp; These metal filled holes are
  90. called vias and we will refer to this layer as VIA0 in our test data.&nbsp; On
  91. top of VIA0 is a layer of metal polygons with silicon oxide insulator between
  92. them.&nbsp; These metal polygons are wires and we will call them METAL1 in our
  93. test data.&nbsp; The Layout Pins in our test data will be on METAL1.&nbsp; In a
  94. NAND gate the two n-type transistors are configured in series, meaning that the
  95. output of one is the input voltage source of the other.&nbsp; Only if both
  96. n-type transistors of a NAND gate are &quot;on&quot; will the output be connected to
  97. ground, signifying a logical &quot;false&quot;.&nbsp; The two p-type transistors in a NAND
  98. gate are configured in parallel.&nbsp; If either input to the NAND gate is a
  99. logical &quot;false&quot; the p-type transistor it is connected to will be &quot;on&quot; and the
  100. output of the gate will be a logical &quot;true&quot; because the transistor will connect
  101. it to the voltage supply.&nbsp; The diagram below is an example of how a NAND
  102. gate might be laid out and is not drawn to scale for any real process
  103. technology.&nbsp; The diffusion material is intended to be cut away under the
  104. gate material by a Boolean NOT operation and is represented as solid bars under
  105. the gates of transistors only for convenience of drawing.</p>
  106. <p>
  107. <img border="0" src="images/NAND.PNG" width="602" height="387"></p>
  108. <p>The following is the input layout file for the above NAND gate layout,
  109. rectangle format is XL XH YL YH:</p>
  110. <p><font face="Courier New" size="2">Rectangle 0 60 24 48 NWELL<br>
  111. Rectangle 3 57 32 43 PDIFF<br>
  112. Rectangle 3 57 5 16 NDIFF<br>
  113. Rectangle 5 7 0 17 POLY<br>
  114. Rectangle 5 7 22 45 POLY<br>
  115. Rectangle 17 19 3 45 POLY<br>
  116. Rectangle 29 31 31 48 POLY<br>
  117. Rectangle 41 43 3 45 POLY<br>
  118. Rectangle 53 55 3 45 POLY<br>
  119. Rectangle 17 19 4 17 GATE<br>
  120. Rectangle 17 19 31 44 GATE<br>
  121. Rectangle 41 43 4 17 GATE<br>
  122. Rectangle 41 43 31 44 GATE<br>
  123. Rectangle 5 7 0 2 VIA0<br>
  124. Rectangle 5 7 23 25 VIA0<br>
  125. Rectangle 17 19 28 30 VIA0<br>
  126. Rectangle 29 31 46 48 VIA0<br>
  127. Rectangle 41 43 18 20 VIA0<br>
  128. Rectangle 53 55 23 25 VIA0<br>
  129. Rectangle 0 60 0 2 METAL1<br>
  130. Rectangle 3 57 28 30 METAL1<br>
  131. Rectangle 0 60 46 48 METAL1<br>
  132. Rectangle 3 57 18 20 METAL1<br>
  133. Rectangle 3 57 23 25 METAL1<br>
  134. Pin 29 31 0 2 METAL1 GND<br>
  135. Pin 29 31 23 25 METAL1 OUTPUT</font><font face="Courier New" size="2"><br>
  136. Pin 29 31 28 30 METAL1 INPUT1</font><font face="Courier New" size="2"><br>
  137. Pin 29 31 46 48 METAL1 VDD<br>
  138. Pin 29 31 18 20 METAL1 INPUT2</font></p>
  139. <p>
  140. <img border="0" src="images/nands.PNG" width="421" height="402"></p>
  141. <p>The following is the logic schematic net list file for the above NAND gate
  142. schematic:</p>
  143. <p><font face="Courier New" size="2">Pin OUTPUT<br>Pin INPUT1<br>Pin INPUT2<br>
  144. Pin VDD<br>Pin GND<br>Device PTRANS VDD INPUT1 OUTPUT<br>Device PTRANS VDD
  145. INPUT2 OUTPUT<br>Device NTRANS GND INPUT1 NET1<br>Device NTRANS NET1 INPUT2
  146. OUTPUT</font></p>
  147. <p>A human can look at this schematic and compare it to the drawn layout of the
  148. NAND gate above to verify that the drawn layout matches what the schematic says
  149. in a few seconds.&nbsp; If you do that now you will probably find the p and
  150. n-type transistors and trace the connectivity of the inputs and power to the
  151. terminals of the transistors and then to the output.&nbsp; Since there are on
  152. the order of one billion transistors on a single chip these days we need to go a
  153. lot faster than humans can inspect layout and make fewer mistakes.&nbsp; Using polygon set operations
  154. and polygon connectivity extraction provided by Boost.Polygon we will automate
  155. the identification of transistors and the tracing of connectivity.&nbsp; Based
  156. on this
  157. <a href="analysis.htm">analysis</a> of Boost.Polygon performance we can expect
  158. this methodology to easily scale up to million gate blocks on standard
  159. workstations and arbitrarily large designs given sufficient system memory.&nbsp;
  160. let's start
  161. by implementing some data structures for our application.</p>
  162. <p><font face="Courier New" size="2">struct layout_rectangle {<br>
  163. &nbsp; int xl, yl, xh, yh;<br>
  164. &nbsp; std::string layer;<br>
  165. };</font></p>
  166. <p>Our layout rectangle is nice and minimal, just enough to store its data.&nbsp;
  167. It is defined in <a href="tutorial/layout_rectangle.hpp">layout_rectangle.hpp</a>. Next
  168. let's implement the layout
  169. pin in a similar way.</p>
  170. <p><font face="Courier New" size="2">struct layout_pin {<br>
  171. &nbsp; int xl, yl, xh, yh;<br>
  172. &nbsp; std::string layer;<br>
  173. &nbsp; std::string net;<br>
  174. };</font></p>
  175. <p>Our layout pin is defined in <a href="tutorial/layout_pin.hpp">layout_pin.hpp</a>.&nbsp; Now
  176. let's define a layout database object and populate it from our parsed
  177. layout data in in <a href="tutorial/layout_database.hpp">layout_database.hpp</a>.</p>
  178. <p><font face="Courier New" size="2">typedef std::map&lt;std::string,
  179. boost::polygon::polygon_90_set_data&lt;int&gt; &gt; layout_database;<br>
  180. <br>
  181. //map the layout rectangle data type to the boost::polygon::rectangle_concept<br>
  182. namespace boost { namespace polygon{<br>
  183. &nbsp; template &lt;&gt;<br>
  184. &nbsp; struct rectangle_traits&lt;layout_rectangle&gt; {<br>
  185. &nbsp;&nbsp;&nbsp; typedef int coordinate_type;<br>
  186. &nbsp;&nbsp;&nbsp; typedef interval_data&lt;int&gt; interval_type;<br>
  187. &nbsp;&nbsp;&nbsp; static inline interval_type get(const layout_rectangle&amp;
  188. rectangle, orientation_2d orient) {<br>
  189. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(orient == HORIZONTAL)<br>
  190. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return interval_type(rectangle.xl,
  191. rectangle.xh);<br>
  192. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return interval_type(rectangle.yl, rectangle.yh);<br>
  193. &nbsp;&nbsp;&nbsp; }<br>
  194. &nbsp; };<br>
  195. <br>
  196. &nbsp; template &lt;&gt;<br>
  197. &nbsp; struct geometry_concept&lt;layout_rectangle&gt; { typedef rectangle_concept
  198. type; };<br>
  199. }}<br>
  200. <br>
  201. //insert layout rectangles into a layout database<br>
  202. inline void populate_layout_database(layout_database&amp; layout, std::vector&lt;layout_rectangle&gt;&amp;
  203. rects) {<br>
  204. &nbsp; for(std::size_t i = 0; i &lt; rects.size(); ++i) {<br>
  205. &nbsp;&nbsp;&nbsp; layout[rects[i].layer].insert(rects[i]);<br>
  206. &nbsp; }<br>
  207. }</font></p>
  208. <p>We don't need to insert pins into the layout database because it doesn't know
  209. anything about connectivity, just geometry.&nbsp; However, we do need to know
  210. something about connectivity to compare a schematic to a layout, so we need to
  211. define our connectivity database and some logical objects.&nbsp; First we define
  212. an object for a logical device in <a href="tutorial/device.hpp">device.hpp</a>.&nbsp;
  213. Since we are lazy this object does double duty as a pin and both types of
  214. transistor.&nbsp; A traditional object oriented design might declare a base
  215. class with virtual destructor and derive every device from that.&nbsp; Since we
  216. aren't paid by the line of code let's just keep things simple.</p>
  217. <p><font face="Courier New" size="2">struct device {<br>
  218. &nbsp; std::string type;<br>
  219. &nbsp; std::vector&lt;std::string&gt; terminals;<br>
  220. };</font></p>
  221. <p>Now let's define a schematic database object in
  222. <a href="tutorial/schematic_database.hpp">schematic_database.hpp</a> and populate it from our parsed
  223. schematic data.</p>
  224. <p><font face="Courier New"><font size="2">struct schematic_database{<br>
  225. &nbsp; std::vector&lt;device&gt; devices;<br>
  226. &nbsp; std::map&lt;std::string, std::set&lt;std::size_t&gt; &gt; nets;<br>
  227. };<br>
  228. <br>
  229. //given a vector of devices populate the map of net name to set of device index<br>
  230. inline void extract_netlist(std::map&lt;std::string, std::set&lt;std::size_t&gt; &gt;&amp; nets,<br>
  231. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  232. std::vector&lt;device&gt;&amp; devices) {<br>
  233. &nbsp; for(std::size_t i = 0; i &lt; devices.size(); ++i) {<br>
  234. &nbsp;&nbsp;&nbsp; for(std::size_t j = 0; j &lt; devices[i].terminals.size(); ++j)
  235. {<br>
  236. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //create association between net name and device
  237. id<br>
  238. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  239. nets[devices[i].terminals[j]].insert(nets[devices[i].terminals[j]].end(), i);<br>
  240. &nbsp;&nbsp;&nbsp; }<br>
  241. &nbsp; }<br>
  242. }</font></font></p>
  243. <p>Our schematic database is just a vector of devices, which are associated to
  244. nets by name through their terminals and a map of net name to set of device
  245. index into the vector, which completes the graph by associating nets with their
  246. devices.&nbsp; Given the devices and their terminal nets we easily build the
  247. mapping from nets to devices with the extract_netlist operation.&nbsp; Now we
  248. are ready to start working on extracting our layout to a derived schematic
  249. database.&nbsp; However, first we need to build a physical connectivity database
  250. with geometry in it before we can build a logical connectivity database from the
  251. layout.&nbsp; We define a simple connectivity database in
  252. <a href="tutorial/connectivity_database.hpp">connectivity_database.hpp</a> as a
  253. map of net name to layout database of geometry connected to that net and
  254. populate it with the layout database and pin data.</p>
  255. <p><font size="2" face="Courier New">typedef std::map&lt;std::string,
  256. layout_database &gt; connectivity_database;<br>
  257. <br>
  258. //map layout pin data type to boost::polygon::rectangle_concept<br>
  259. namespace boost { namespace polygon{<br>
  260. &nbsp; template &lt;&gt;<br>
  261. &nbsp; struct rectangle_traits&lt;layout_pin&gt; {<br>
  262. &nbsp;&nbsp;&nbsp; typedef int coordinate_type;<br>
  263. &nbsp;&nbsp;&nbsp; typedef interval_data&lt;int&gt; interval_type;<br>
  264. &nbsp;&nbsp;&nbsp; static inline interval_type get(const layout_pin&amp; pin,
  265. orientation_2d orient) {<br>
  266. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(orient == HORIZONTAL)<br>
  267. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return interval_type(pin.xl, pin.xh);<br>
  268. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return interval_type(pin.yl, pin.yh);<br>
  269. &nbsp;&nbsp;&nbsp; }<br>
  270. &nbsp; };<br>
  271. <br>
  272. &nbsp; template &lt;&gt;<br>
  273. &nbsp; struct geometry_concept&lt;layout_pin&gt; { typedef rectangle_concept type; };<br>
  274. }}</font></p>
  275. <p><font size="2" face="Courier New">//given a layout_database we populate a
  276. connectivity database<br>
  277. inline void populate_connectivity_database(connectivity_database&amp; connectivity,<br>
  278. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  279. std::vector&lt;layout_pin&gt;&amp; pins, layout_database&amp; layout) {<br>
  280. &nbsp; using namespace boost::polygon;<br>
  281. &nbsp; using namespace boost::polygon::operators;<br>
  282. &nbsp; for(std::size_t i = 0; i &lt; pins.size(); ++i) {<br>
  283. &nbsp;&nbsp;&nbsp; connectivity[pins[i].net][pins[i].layer].insert(pins[i]);<br>
  284. &nbsp; }<br>
  285. &nbsp; int internal_net_suffix = 0;<br>
  286. &nbsp; //connect metal1 layout to pins which were on metal1<br>
  287. &nbsp; connect_layout_to_layer(connectivity, layout[&quot;METAL1&quot;], &quot;METAL1&quot;, <br>
  288. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  289. &quot;METAL1&quot;, &quot;__internal_net_&quot;, internal_net_suffix);<br>
  290. &nbsp; //connect via0 layout to metal1<br>
  291. &nbsp; connect_layout_to_layer(connectivity, layout[&quot;VIA0&quot;], &quot;VIA0&quot;, <br>
  292. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  293. &quot;METAL1&quot;, &quot;__internal_net_&quot;, internal_net_suffix);<br>
  294. &nbsp; //poly needs to have gates subtracted from it to prevent shorting through
  295. transistors<br>
  296. &nbsp; polygon_set poly_not_gate = layout[&quot;POLY&quot;] - layout[&quot;GATE&quot;];<br>
  297. &nbsp; //connect poly minus gate to via0<br>
  298. &nbsp; connect_layout_to_layer(connectivity, poly_not_gate, &quot;POLY&quot;, <br>
  299. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  300. &quot;VIA0&quot;, &quot;__internal_net_&quot;, internal_net_suffix);<br>
  301. &nbsp; //we don't want to short signals through transistors so we subtract the
  302. gate regions<br>
  303. &nbsp; //from the diffusions<br>
  304. &nbsp; polygon_set diff_not_gate = (layout[&quot;PDIFF&quot;] + layout[&quot;NDIFF&quot;]) -
  305. layout[&quot;GATE&quot;];<br>
  306. &nbsp; //connect diffusion minus gate to poly<br>
  307. &nbsp; //Note that I made up the DIFF layer name for combined P and NDIFF<br>
  308. &nbsp; connect_layout_to_layer(connectivity, diff_not_gate, &quot;DIFF&quot;, <br>
  309. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  310. &quot;POLY&quot;, &quot;__internal_net_&quot;, internal_net_suffix);<br>
  311. &nbsp; //connect gate to poly to make connections through gates on poly<br>
  312. &nbsp; connect_layout_to_layer(connectivity, layout[&quot;GATE&quot;], &quot;GATE&quot;, <br>
  313. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  314. &quot;POLY&quot;, &quot;__internal_net_&quot;, internal_net_suffix);<br>
  315. &nbsp; //now we have traced connectivity of the layout down to the transistor
  316. level<br>
  317. &nbsp; //any polygons not connected to pins have been assigned internal net
  318. names<br>
  319. }</font></p>
  320. <p>This populate connectivity database function is our first real use of
  321. Boost.Polygon in our application.&nbsp; Here we are doing Boolean (polygon set)
  322. operations on layout layers to merge together the PDIFF and NDIFF layers and cut
  323. away the GATE layer from the result, for example.&nbsp; We connect up the layout
  324. starting from the pins and working our way down the layer stack to the
  325. transistor level.&nbsp; It would work equally well to work our way up the layer
  326. stack, or connect things up in any order, really, but this way produces fewer
  327. internal temporary nets that need to be merged when connections between them are
  328. discovered later.&nbsp; The connect layout to layer function used above needs to
  329. be implemented before we can populate our connectivity database.</p>
  330. <p><font size="2" face="Courier New">inline void
  331. connect_layout_to_layer(connectivity_database&amp; connectivity, polygon_set&amp;
  332. layout, <br>
  333. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  334. std::string layout_layer, std::string layer,<br>
  335. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  336. std::string net_prefix, int&amp; net_suffix) {<br>
  337. &nbsp; if(layout_layer.empty())<br>
  338. &nbsp;&nbsp;&nbsp; return;<br>
  339. &nbsp; boost::polygon::connectivity_extraction_90&lt;int&gt; ce;<br>
  340. &nbsp; std::vector&lt;std::string&gt; net_ids;<br>
  341. &nbsp; for(connectivity_database::iterator itr = connectivity.begin(); itr !=
  342. connectivity.end(); ++itr) {<br>
  343. &nbsp;&nbsp;&nbsp; net_ids.push_back((*itr).first);<br>
  344. &nbsp;&nbsp;&nbsp; ce.insert((*itr).second[layer]);<br>
  345. &nbsp; }<br>
  346. &nbsp; std::vector&lt;polygon&gt; polygons;<br>
  347. &nbsp; layout.get_polygons(polygons);<br>
  348. &nbsp; std::size_t polygon_id_offset = net_ids.size();<br>
  349. &nbsp; for(std::size_t i = 0; i &lt; polygons.size(); ++i) {<br>
  350. &nbsp;&nbsp;&nbsp; ce.insert(polygons[i]);<br>
  351. &nbsp; }<br>
  352. &nbsp; std::vector&lt;std::set&lt;int&gt; &gt; graph(polygons.size() + net_ids.size(),
  353. std::set&lt;int&gt;());<br>
  354. &nbsp; ce.extract(graph);<br>
  355. &nbsp; std::vector&lt;int&gt; polygon_color(polygons.size() + net_ids.size(), 0);<br>
  356. &nbsp; //for each net in net_ids populate connected component with net<br>
  357. &nbsp; for(std::size_t node_id = 0; node_id &lt; net_ids.size(); ++node_id) {<br>
  358. &nbsp;&nbsp;&nbsp; populate_connected_component(connectivity, polygons,
  359. polygon_color, graph, node_id, <br>
  360. &nbsp;&nbsp;&nbsp; polygon_id_offset, net_ids[node_id], net_ids, <br>
  361. &nbsp;&nbsp;&nbsp; net_prefix, layout_layer);<br>
  362. &nbsp; }<br>
  363. &nbsp; //for each polygon_color that is zero populate connected component with
  364. net_prefix + net_suffix++<br>
  365. &nbsp; for(std::size_t i = 0; i &lt; polygons.size(); ++i) {<br>
  366. &nbsp;&nbsp;&nbsp; if(polygon_color[i + polygon_id_offset] == 0) {<br>
  367. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::stringstream ss(std::stringstream::in |
  368. std::stringstream::out);<br>
  369. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ss &lt;&lt; net_prefix &lt;&lt; net_suffix++;<br>
  370. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::string internal_net; <br>
  371. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ss &gt;&gt; internal_net;<br>
  372. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; populate_connected_component(connectivity,
  373. polygons, polygon_color, graph, <br>
  374. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i + polygon_id_offset, <br>
  375. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; polygon_id_offset, internal_net, net_ids, <br>
  376. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; net_prefix, layout_layer);<br>
  377. &nbsp;&nbsp;&nbsp; }<br>
  378. &nbsp; }<br>
  379. }</font></p>
  380. <p>The connect layout to layer function uses the connectivity extraction feature
  381. of Boost.Polyon to build a connectivity graph for polygons on the input polygon
  382. set and in the connectivity database on the specified layer.&nbsp; It then finds
  383. polygons associated with existing nets in the connectivity database through
  384. graph traversal and inserts them into the connectivity database.&nbsp; Finally,
  385. polygons that weren't connected to existing nets are inserted into the
  386. connectivity database on auto-generated internal net names.&nbsp; The insertion
  387. of a connected component into the connectivity database is handled by the
  388. recursive traversal of the connectivity graph that we implement next.</p>
  389. <p><font size="2" face="Courier New">inline void populate_connected_component<br>
  390. (connectivity_database&amp; connectivity, std::vector&lt;polygon&gt;&amp; polygons, <br>
  391. &nbsp;std::vector&lt;int&gt; polygon_color, std::vector&lt;std::set&lt;int&gt; &gt;&amp; graph, <br>
  392. &nbsp;std::size_t node_id, std::size_t polygon_id_offset, std::string&amp; net, <br>
  393. &nbsp;std::vector&lt;std::string&gt;&amp; net_ids, std::string net_prefix,<br>
  394. &nbsp;std::string&amp; layout_layer) {<br>
  395. &nbsp; if(polygon_color[node_id] == 1)<br>
  396. &nbsp;&nbsp;&nbsp; return;<br>
  397. &nbsp; polygon_color[node_id] = 1;<br>
  398. &nbsp; if(node_id &lt; polygon_id_offset &amp;&amp; net_ids[node_id] != net) {<br>
  399. &nbsp;&nbsp;&nbsp; //merge nets in connectivity database<br>
  400. &nbsp;&nbsp;&nbsp; //if one of the nets is internal net merge it into the other<br>
  401. &nbsp;&nbsp;&nbsp; std::string net1 = net_ids[node_id];<br>
  402. &nbsp;&nbsp;&nbsp; std::string net2 = net;<br>
  403. &nbsp;&nbsp;&nbsp; if(net.compare(0, net_prefix.length(), net_prefix) == 0) {<br>
  404. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; net = net1;<br>
  405. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::swap(net1, net2);<br>
  406. &nbsp;&nbsp;&nbsp; } else {<br>
  407. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; net_ids[node_id] = net;<br>
  408. &nbsp;&nbsp;&nbsp; }<br>
  409. &nbsp;&nbsp;&nbsp; connectivity_database::iterator itr =
  410. connectivity.find(net1);<br>
  411. &nbsp;&nbsp;&nbsp; if(itr != connectivity.end()) {<br>
  412. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(layout_database::iterator itr2 = (*itr).second.begin();<br>
  413. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; itr2 != (*itr).second.end();
  414. ++itr2) {<br>
  415. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectivity[net2][(*itr2).first].insert((*itr2).second);<br>
  416. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
  417. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectivity.erase(itr);<br>
  418. &nbsp;&nbsp;&nbsp; }<br>
  419. &nbsp; }<br>
  420. &nbsp; if(node_id &gt;= polygon_id_offset)<br>
  421. &nbsp; connectivity[net][layout_layer].insert(polygons[node_id -
  422. polygon_id_offset]);<br>
  423. &nbsp; for(std::set&lt;int&gt;::iterator itr = graph[node_id].begin();<br>
  424. &nbsp; itr != graph[node_id].end(); ++itr) {<br>
  425. &nbsp;&nbsp;&nbsp; populate_connected_component(connectivity, polygons,
  426. polygon_color, graph, <br>
  427. &nbsp;&nbsp;&nbsp; *itr, polygon_id_offset, net, net_ids, net_prefix,
  428. layout_layer);<br>
  429. &nbsp; }<br>
  430. }<br>
  431. <br>
  432. </font>We want to merge internally generated nets into pin nets, which is the
  433. most complicated part of this simple procedure.&nbsp; Now that we have our
  434. connectivity database extracted from pins down to transistors we need to extract
  435. our transistors and establish the relationship between transistor terminals and
  436. nets in our connectivity database.&nbsp; First let's extract transistors with
  437. the functions defined in defined in <a href="tutorial/extract_devices.hpp">
  438. extract_devices.hpp</a>.</p>
  439. <p><font size="2" face="Courier New">typedef boost::polygon::connectivity_extraction_90&lt;int&gt;
  440. connectivity_extraction;<br>
  441. inline std::vector&lt;std::set&lt;int&gt; &gt;<br>
  442. extract_layer(connectivity_extraction&amp; ce, std::vector&lt;std::string&gt;&amp; net_ids,<br>
  443. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  444. connectivity_database&amp; connectivity, polygon_set&amp; layout,<br>
  445. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  446. std::string layer) {<br>
  447. &nbsp; for(connectivity_database::iterator itr = connectivity.begin(); itr !=
  448. connectivity.end(); ++itr) {<br>
  449. &nbsp;&nbsp;&nbsp; net_ids.push_back((*itr).first);<br>
  450. &nbsp;&nbsp;&nbsp; ce.insert((*itr).second[layer]);<br>
  451. &nbsp; }<br>
  452. &nbsp; std::vector&lt;polygon&gt; polygons;<br>
  453. &nbsp; layout.get_polygons(polygons);<br>
  454. &nbsp; for(std::size_t i = 0; i &lt; polygons.size(); ++i) {<br>
  455. &nbsp;&nbsp;&nbsp; ce.insert(polygons[i]);<br>
  456. &nbsp; }<br>
  457. &nbsp; std::vector&lt;std::set&lt;int&gt; &gt; graph(polygons.size() + net_ids.size(),
  458. std::set&lt;int&gt;());<br>
  459. &nbsp; ce.extract(graph);<br>
  460. &nbsp; return graph;<br>
  461. }</font></p>
  462. <p>This extract layer algorithm constructs a connectivity graph between polygons
  463. in the input polygon set and polygons in the given layer of the connectivity
  464. database.&nbsp; It is used to form the association between transistors and their
  465. terminal nets in the function for extracting a specific transistor type.</p>
  466. <p><font size="2" face="Courier New">inline void extract_device_type(std::vector&lt;device&gt;&amp;
  467. devices, connectivity_database&amp; connectivity,<br>
  468. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  469. polygon_set&amp; layout, std::string type) {<br>
  470. &nbsp; //recall that P and NDIFF were merged into one DIFF layer in the
  471. connectivity database<br>
  472. &nbsp; //find the two nets on the DIFF layer that interact with each transistor<br>
  473. &nbsp; //and then find the net on the poly layer that interacts with each
  474. transistor<br>
  475. &nbsp; boost::polygon::connectivity_extraction_90&lt;int&gt; cediff;<br>
  476. &nbsp; std::vector&lt;std::string&gt; net_ids_diff;<br>
  477. &nbsp; std::vector&lt;std::set&lt;int&gt; &gt; graph_diff =<br>
  478. &nbsp;&nbsp;&nbsp; extract_layer(cediff, net_ids_diff, connectivity, layout,
  479. &quot;DIFF&quot;);<br>
  480. &nbsp; boost::polygon::connectivity_extraction_90&lt;int&gt; cepoly;<br>
  481. &nbsp; std::vector&lt;std::string&gt; net_ids_poly;<br>
  482. &nbsp; std::vector&lt;std::set&lt;int&gt; &gt; graph_poly =<br>
  483. &nbsp;&nbsp;&nbsp; extract_layer(cepoly, net_ids_poly, connectivity, layout,
  484. &quot;POLY&quot;);<br>
  485. &nbsp; std::vector&lt;device&gt; tmp_devices(graph_diff.size() - net_ids_poly.size());<br>
  486. &nbsp; for(std::size_t i = net_ids_poly.size(); i &lt; graph_diff.size(); ++i) {<br>
  487. &nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].type = type;<br>
  488. &nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].terminals = std::vector&lt;std::string&gt;(3,
  489. std::string());<br>
  490. &nbsp;&nbsp;&nbsp; std::size_t j = 0;<br>
  491. &nbsp;&nbsp;&nbsp; for(std::set&lt;int&gt;::iterator itr = graph_diff[i].begin();<br>
  492. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; itr != graph_diff[i].end(); ++itr,
  493. ++j) {<br>
  494. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(j == 0) {<br>
  495. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].terminals[0]
  496. = net_ids_diff[*itr];<br>
  497. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if(j == 1) {<br>
  498. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].terminals[2]
  499. = net_ids_diff[*itr];<br>
  500. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
  501. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //error, too many diff connections<br>
  502. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].terminals
  503. = std::vector&lt;std::string&gt;(3, std::string());<br>
  504. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
  505. &nbsp;&nbsp;&nbsp; }<br>
  506. &nbsp;&nbsp;&nbsp; j = 0;<br>
  507. &nbsp;&nbsp;&nbsp; for(std::set&lt;int&gt;::iterator itr = graph_poly[i].begin();<br>
  508. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; itr != graph_poly[i].end(); ++itr,
  509. ++j) {<br>
  510. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(j == 0) {<br>
  511. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_diff.size()].terminals[1]
  512. = net_ids_poly[*itr];<br>
  513. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
  514. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //error, too many poly connections<br>
  515. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_devices[i - net_ids_poly.size()].terminals
  516. = std::vector&lt;std::string&gt;(3, std::string());<br>
  517. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
  518. &nbsp;&nbsp;&nbsp; }<br>
  519. &nbsp; }<br>
  520. <br>
  521. &nbsp; devices.insert(devices.end(), tmp_devices.begin(), tmp_devices.end());<br>
  522. }</font></p>
  523. <p>We append transistors onto the vector of devices with their terminals
  524. populated with net names extracted from the connectivity database.&nbsp;
  525. Transistors' terminals are connected through the POLY and DIFF layers where DIFF
  526. contains both PDIFF and NDIFF.&nbsp; The connection to POLY layer is the gate of
  527. the transistor while the connections to DIFF on either side of the channel of
  528. the transistor are the source and drain.&nbsp; We can use this to extract are p
  529. and n-type transistors. <font size="2" face="Courier New"><br>
  530. <br>
  531. //populates vector of devices based on connectivity and layout data<br>
  532. inline void extract_devices(std::vector&lt;device&gt;&amp; devices, connectivity_database&amp;
  533. connectivity,<br>
  534. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  535. layout_database&amp; layout) {<br>
  536. &nbsp; using namespace boost::polygon::operators;<br>
  537. &nbsp; //p-type transistors are gate that interact with p diffusion and nwell<br>
  538. &nbsp; polygon_set ptransistors = layout[&quot;GATE&quot;];<br>
  539. &nbsp; ptransistors.interact(layout[&quot;PDIFF&quot;]);<br>
  540. &nbsp; ptransistors.interact(layout[&quot;NWELL&quot;]);<br>
  541. &nbsp; //n-type transistors are gate that interact with n diffusion and not
  542. nwell<br>
  543. &nbsp; polygon_set ntransistors = layout[&quot;GATE&quot;];<br>
  544. &nbsp; ntransistors.interact(layout[&quot;NDIFF&quot;]);<br>
  545. &nbsp; polygon_set not_ntransistors = ntransistors;<br>
  546. &nbsp; not_ntransistors.interact(layout[&quot;NWELL&quot;]);<br>
  547. &nbsp; ntransistors -= not_ntransistors;<br>
  548. &nbsp; extract_device_type(devices, connectivity, ptransistors, &quot;PTRANS&quot;);<br>
  549. &nbsp; extract_device_type(devices, connectivity, ntransistors, &quot;NTRANS&quot;);<br>
  550. }</font></p>
  551. <p>The extract devices procedure makes some more use of Boost.Polygon Boolean
  552. operations on the layout data when we exclude GATE material over NDIFF that
  553. isn't also over NWELL to extract our n-type transistors.&nbsp; We also are using
  554. the &quot;interact&quot; operation on polygon gets, which is implemented in terms of
  555. connectivity extraction and retains all polygons of a polygon set that touch or
  556. overlap polygons from another polygon set.&nbsp; Now that we have a vector of
  557. devices we can build a schematic database by calling the extract_netlist
  558. function.&nbsp; We can then compare the extracted schematic from the schematic
  559. read in from file with the functions defined in
  560. <a href="tutorial/compare_schematics.hpp">compare_schematics.hpp</a>.&nbsp;
  561. Since comparing two schematics has no geometric aspect we won't go into that
  562. procedure here in the tutorial and will skip to the integration of all these
  563. procedures in defined in <a href="tutorial/extract.cpp">extract.cpp</a> to build
  564. the layout to schematic comparison algorithm.</p>
  565. <p><font size="2" face="Courier New">bool compare_files(std::string layout_file,
  566. std::string schematic_file) {<br>
  567. &nbsp; std::ifstream sin(schematic_file.c_str());<br>
  568. &nbsp; std::ifstream lin(layout_file.c_str());<br>
  569. <br>
  570. &nbsp; std::vector&lt;layout_rectangle&gt; rects;<br>
  571. &nbsp; std::vector&lt;layout_pin&gt; pins;<br>
  572. &nbsp; parse_layout(rects, pins, lin);<br>
  573. <br>
  574. &nbsp; schematic_database reference_schematic;<br>
  575. &nbsp; parse_schematic_database(reference_schematic, sin);<br>
  576. <br>
  577. &nbsp; layout_database layout;<br>
  578. &nbsp; populate_layout_database(layout, rects);<br>
  579. <br>
  580. &nbsp; connectivity_database connectivity;<br>
  581. &nbsp; populate_connectivity_database(connectivity, pins, layout);<br>
  582. <br>
  583. &nbsp; schematic_database schematic;<br>
  584. &nbsp; std::vector&lt;device&gt;&amp; devices = schematic.devices;<br>
  585. &nbsp; for(std::size_t i = 0; i &lt; pins.size(); ++i) {<br>
  586. &nbsp;&nbsp;&nbsp; devices.push_back(device());<br>
  587. &nbsp;&nbsp;&nbsp; devices.back().type = &quot;PIN&quot;;<br>
  588. &nbsp;&nbsp;&nbsp; devices.back().terminals.push_back(pins[i].net);<br>
  589. &nbsp; }<br>
  590. &nbsp; extract_devices(devices, connectivity, layout);<br>
  591. &nbsp; extract_netlist(schematic.nets, devices);<br>
  592. &nbsp; return compare_schematics(reference_schematic, schematic);<br>
  593. }</font></p>
  594. <p><font face="Courier New" size="2">int main(int argc, char **argv) {<br>
  595. &nbsp; if(argc &lt; 3) {<br>
  596. &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;usage: &quot; &lt;&lt; argv[0] &lt;&lt; &quot; &lt;layout_file&gt; &lt;schematic_file&gt;&quot;
  597. &lt;&lt; std::endl;<br>
  598. &nbsp;&nbsp;&nbsp; return -1;<br>
  599. &nbsp; }<br>
  600. &nbsp; bool result = compare_files(argv[1], argv[2]);<br>
  601. &nbsp; if(result == false) {<br>
  602. &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;Layout does not match schematic.&quot; &lt;&lt; std::endl;<br>
  603. &nbsp;&nbsp;&nbsp; return 1;<br>
  604. &nbsp; } <br>
  605. &nbsp; std::cout &lt;&lt; &quot;Layout does match schematic.&quot; &lt;&lt; std::endl;<br>
  606. &nbsp; return 0;<br>
  607. }<br>
  608. <br>
  609. </font>We test the program with two schematics and three layouts.&nbsp; These
  610. include a nand and a nor gate layout and schematic as well as an incorrect nand
  611. gate layout.&nbsp; The nand layout and schematic are the same as shown above.<font face="Courier New" size="2">
  612. </font></p>
  613. <p><font face="Courier New" size="2">&gt; lvs<br>
  614. usage: lvs &lt;layout_file&gt; &lt;schematic_file&gt;<br>
  615. &gt; lvs nand.layout nand.schematic <br>
  616. Layout does match schematic.<br>
  617. &gt; lvs nand_short.layout nand.schematic <br>
  618. Layout does not match schematic.<br>
  619. &gt; lvs nand.layout nor.schematic <br>
  620. Layout does not match schematic.<br>
  621. &gt; lvs nor.layout nor.schematic <br>
  622. Layout does match schematic.<br>
  623. &gt; lvs nor.layout nand.schematic <br>
  624. Layout does not match schematic.</font></p>
  625. <p>This concludes our tutorial on how to build a simple layout to schematic
  626. verification application based on Boost.Polygon library capabilities.&nbsp; The
  627. implementation of this application made many simplifying assumptions that are
  628. not valid in the real world and hard coded a lot of things that need to be
  629. configurable in a real layout verification application.&nbsp; However, it does
  630. give an idea of how to use Boost.Polygon to solve real problems and points in
  631. the direction of how a real application might use Boost.Polygon.</p>
  632. <table class="docinfo" rules="none" frame="void" id="table1">
  633. <colgroup>
  634. <col class="docinfo-name"><col class="docinfo-content">
  635. </colgroup>
  636. <tbody vAlign="top">
  637. <tr>
  638. <th class="docinfo-name">Copyright:</th>
  639. <td>Copyright © Intel Corporation 2008-2010.</td>
  640. </tr>
  641. <tr class="field">
  642. <th class="docinfo-name">License:</th>
  643. <td class="field-body">Distributed under the Boost Software License,
  644. Version 1.0. (See accompanying file <tt class="literal">
  645. <span class="pre">LICENSE_1_0.txt</span></tt> or copy at
  646. <a class="reference" target="_top" href="http://www.boost.org/LICENSE_1_0.txt">
  647. http://www.boost.org/LICENSE_1_0.txt</a>)</td>
  648. </tr>
  649. </table>
  650. </body>
  651. </html>