From 9e1c8b44c7b073ad6b26cef01e746f03ad7f213a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 16 Oct 2019 18:59:38 +0200 Subject: [PATCH] Introducing cheats for LVS/device extraction/booleans --- src/drc/drc/built-in-macros/_drc_engine.rb | 102 +++++++++++++++++++++ src/lay/lay/doc/about/drc_ref_global.xml | 92 +++++++++++++++++++ src/lay/lay/doc/about/drc_ref_layer.xml | 70 ++++++++++++-- 3 files changed, 256 insertions(+), 8 deletions(-) diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 81c601bbc..1d5879673 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -1120,6 +1120,108 @@ module DRC @def_source = layout.clip(*args) nil end + + # %DRC% + # @name cheat + # @brief Hierarchy cheats + # @synopsis cheat(args) { block } + # + # Hierarchy cheats can be used in deep mode to shortcut hierarchy evaluation + # for certain cells and consider their local configuration only. + # Cheats are useful for example when dealing with memory arrays. Often + # such arrays are build from unit cells and those often overlap with their + # neighbors. Now, if the hierarchical engine encounters such a situation, it + # will first analyse all these interactions (which can be expensive) and then + # it may come to the conclusion that boundary instances need to be handled + # differently than inside instances. This in turn might lead to propagation of + # shapes and in an LVS context to device externalisation: because some devices + # might have different parameters for boundary cells than for inside cells, the + # device instances can no longer be kept inside the unit cell. Specifically for + # memory arrays, this is not desired as eventually this leads to flattening + # of the whole array. + # + # The solution is to cheat: provided the unit cell is fully fledged and neighbors + # do not disturb the unit cell's configuration in critical ways, the unit cell + # can be treated as being isolated and results are put together in the usual way. + # + # Cheats can be applied on layout operations - specifically booleans - and device + # extraction operations. Cheats are only effective in \deep mode. + # + # For booleans, a cheat means that the cheating cell's boolean results are computed + # locally and are combined afterwards. A cheat is introduced this way: + # + # @code + # deep + # + # l1 = input(1, 0) + # l2 = input(2, 0) + # + # # usual booleans + # l1and2 = l1 & l2 + # + # # will compute "UNIT_CELL" isolated and everything else in normal hierarchical mode: + # l1minus2 = cheat("UNIT_CELL) { l1 - l2 } + # @/code + # + # The cheat block can also be wrapped in do .. end statements and can return multiple + # layer objects: + # + # @code + # deep + # + # l1 = input(1, 0) + # l2 = input(2, 0) + # + # # computes both AND and NOT of l1 and l2 with cheating for "UNIT_CELL" + # l1and2, l1minus2 = cheat("UNIT_CELL) do + # [ l1 & l2, l1 - l2 ] + # end + # @/code + # + # (Technically, the cheat code block is a Ruby Proc and cannot create variables + # outside it's scope. Hence the results of this code block have to be passed + # through the "cheat" method). + # + # To apply cheats for device extraction, use the following scheme: + # + # @code + # deep + # + # poly = input(1, 0) + # active = input(2, 0) + # + # sd = active - poly + # gate = active & poly + # + # # device extraction with cheating for "UNIT_CELL": + # cheat("UNIT_CELL") do + # extract_devices(mos3("NMOS"), { "SD" => sd, "G" => gate, "tS" => sd, "tD" => sd, "tG" => poly } + # end + # @/code + # + # The argument to the cheat method is a list of cell name pattern (glob-style + # pattern). For example: + # + # @code + # cheat("UNIT_CELL*") { ... } + # cheat("UNIT_CELL1", "UNIT_CELL2") { ... } + # cheat("UNIT_CELL{1,2}") { ... } + # @/code + # + # For LVS applications, it's usually sufficient to cheat in the device extraction step. + # Cheats have been introduced in version 0.26.1. + + def cheat(*args, &block) + if _dss + _dss.push_state + args.flatten.each { |a| _dss.add_breakout_cells(a.to_s) } + ret = block.call + _dss.pop_state + else + ret = block.call + end + ret + end # make some DRCLayer methods available as functions # for the engine diff --git a/src/lay/lay/doc/about/drc_ref_global.xml b/src/lay/lay/doc/about/drc_ref_global.xml index ef89cacdd..623d30d1e 100644 --- a/src/lay/lay/doc/about/drc_ref_global.xml +++ b/src/lay/lay/doc/about/drc_ref_global.xml @@ -92,6 +92,98 @@ cell("MACRO") l1 = input(1, 0)

+

"cheat" - Hierarchy cheats

+ +

Usage:

+
    +
  • cheat(args) { block }
  • +
+

+Hierarchy cheats can be used in deep mode to shortcut hierarchy evaluation +for certain cells and consider their local configuration only. +Cheats are useful for example when dealing with memory arrays. Often +such arrays are build from unit cells and those often overlap with their +neighbors. Now, if the hierarchical engine encounters such a situation, it +will first analyse all these interactions (which can be expensive) and then +it may come to the conclusion that boundary instances need to be handled +differently than inside instances. This in turn might lead to propagation of +shapes and in an LVS context to device externalisation: because some devices +might have different parameters for boundary cells than for inside cells, the +device instances can no longer be kept inside the unit cell. Specifically for +memory arrays, this is not desired as eventually this leads to flattening +of the whole array. +

+The solution is to cheat: provided the unit cell is fully fledged and neighbors +do not disturb the unit cell's configuration in critical ways, the unit cell +can be treated as being isolated and results are put together in the usual way. +

+Cheats can be applied on layout operations - specifically booleans - and device +extraction operations. Cheats are only effective in deep mode. +

+For booleans, a cheat means that the cheating cell's boolean results are computed +locally and are combined afterwards. A cheat is introduced this way: +

+

+deep
+
+l1 = input(1, 0)
+l2 = input(2, 0)
+
+# usual booleans
+l1and2 = l1 & l2
+
+# will compute "UNIT_CELL" isolated and everything else in normal hierarchical mode:
+l1minus2 = cheat("UNIT_CELL) { l1 - l2 }
+
+

+The cheat block can also be wrapped in do .. end statements and can return multiple +layer objects: +

+

+deep
+
+l1 = input(1, 0)
+l2 = input(2, 0)
+
+# computes both AND and NOT of l1 and l2 with cheating for "UNIT_CELL"
+l1and2, l1minus2 = cheat("UNIT_CELL) do
+[ l1 & l2, l1 - l2 ]
+end
+
+

+(Technically, the check code block is a Ruby Proc and cannot create variables +outside it's scope. Hence the results of this code block have to be passed +through the "cheat" method). +

+To apply cheats for device extraction, use the following scheme: +

+

+deep
+
+poly = input(1, 0)
+active = input(2, 0)
+
+sd = active - poly
+gate = active & poly
+
+# device extraction with cheating for "UNIT_CELL":
+cheat("UNIT_CELL") do
+extract_devices(mos3("NMOS"), { "SD" => sd, "G" => gate, "tS" => sd, "tD" => sd, "tG" => poly }
+end
+
+

+The argument to the cheat method is a list of cell name pattern (glob-style +pattern). For example: +

+

+cheat("UNIT_CELL*") { ... }
+cheat("UNIT_CELL1", "UNIT_CELL2") { ... }
+cheat("UNIT_CELL{1,2}") { ... }
+
+

+For LVS applications, it's usually sufficient to cheat in the device extraction step. +Cheats have been introduced in version 0.26.1. +

"clear_connections" - Clears all connections stored so far

Usage:

diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml index f996764b9..fb9d591c5 100644 --- a/src/lay/lay/doc/about/drc_ref_layer.xml +++ b/src/lay/lay/doc/about/drc_ref_layer.xml @@ -735,7 +735,7 @@ This method is available for edge layers. The argument must be a polygon layer.

This method selects all shapes or regions from self which touch or overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It returns a new layer containing the selected shapes. A version which modifies self is select_interacting. @@ -1085,7 +1085,7 @@ The following image shows the effect of the "not_inside" method (input1: red, in

This method selects all shapes or regions from self which do not touch or overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It returns a new layer containing the selected shapes. A version which modifies self is select_not_interacting. @@ -1134,7 +1134,7 @@ The following image shows the effect of the "not_outside" method (input1: red, i

This method selects all shapes or regions from self which do not overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected.

The "not_overlapping" method is equivalent to the outside method. It is provided @@ -1322,7 +1322,7 @@ The following images show the effect of the overlap check (layer1: red, layer2:

This method selects all shapes or regions from self which overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It returns a new layer containing the selected shapes. A version which modifies self is select_overlapping. @@ -1372,6 +1372,60 @@ parameter is 0, special edge pairs with an area of 0 will be dropped.

  • layer.polygons?
+

"pull_inside" - Selects shapes or regions of other which are inside polygons from the this region

+ +

Usage:

+
    +
  • layer.pull_inside(other)
  • +
+

+This method selects all shapes or regions from other which are inside polygons from this +region. Unless other is in raw mode (see raw), coherent regions are selected from other, +otherwise individual shapes are selected. +

+The functionality is similar to select_inside, but chosing shapes from other rather +than from self. Because in deep mode the hierarchy reference comes from self, this method +provides a way to pull shapes from other to the hierarchy to self. +

+This method is available for polygon layers. Other needs to be a polygon layer too. +

+

"pull_interacting" - Selects shapes or edges of other which touch or overlap shapes from the this region

+ +

Usage:

+
    +
  • layer.pull_interacting(other)
  • +
+

+This method selects all shapes or regions from other which touch or overlap shapes from this +region. Unless other is in raw mode (see raw), coherent regions are selected from other, +otherwise individual shapes are selected. +

+The functionality is similar to select_interacting, but chosing shapes from other rather +than from self. Because in deep mode the hierarchy reference comes from self, this method +provides a way to pull shapes from other to the hierarchy to self. +

+This method will neither modify self nor other. +

+This method is available for polygon layers. Other can be an edge or polygon layer. +Edges or polygons can be selected with respect to polygons of self. +

+

"pull_overlapping" - Selects shapes or regions of other which overlap shapes from the this region

+ +

Usage:

+
    +
  • layer.pull_overlapping(other)
  • +
+

+This method selects all shapes or regions from other which overlap shapes from this +region. Unless other is in raw mode (see raw), coherent regions are selected from other, +otherwise individual shapes are selected. +

+The functionality is similar to select_overlapping, but chosing shapes from other rather +than from self. Because in deep mode the hierarchy reference comes from self, this method +provides a way to pull shapes from other to the hierarchy to self. +

+This method is available for polygon layers. Other needs to be a polygon layer too. +

"raw" - Marks a layer as raw

Usage:

@@ -1562,7 +1616,7 @@ This method is available for polygon layers.

This method selects all shapes or regions from self which touch or overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It modifies self to contain the selected shapes. A version which does not modify self is interacting. @@ -1595,7 +1649,7 @@ This method is available for polygon layers.

This method selects all shapes or regions from self which do not touch or overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It modifies self to contain the selected shapes. A version which does not modify self is not_interacting. @@ -1628,7 +1682,7 @@ This method is available for polygon layers.

This method selects all shapes or regions from self which do not overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It modifies self to contain the selected shapes. A version which does not modify self is not_overlapping. @@ -1661,7 +1715,7 @@ This method is available for polygon layers.

This method selects all shapes or regions from self which overlap shapes from the other -region. If self is in raw mode (see raw), coherent regions are selected from self, +region. Unless self is in raw mode (see raw), coherent regions are selected from self, otherwise individual shapes are selected. It modifies self to contain the selected shapes. A version which does not modify self is overlapping.