/ test / unit / technology / mask.py
mask.py
  1  # SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-or-later OR CERN-OHL-S-2.0+ OR Apache-2.0
  2  # type: ignore
  3  import unittest
  4  
  5  from pdkmaster.technology import mask as _msk
  6  
  7  
  8  class MaskTest(unittest.TestCase):
  9      def test_error(self):
 10          class WrongCond(_msk._MultiMaskCondition):
 11              pass
 12  
 13          with self.assertRaises(AttributeError):
 14              WrongCond(
 15                  mask=_msk.DesignMask(name="MyMask"),
 16                  others=_msk.DesignMask(name="Other"),
 17              )
 18  
 19          mask = _msk.DesignMask(name="mask")
 20  
 21          with self.assertRaises(ValueError):
 22              _msk.Spacing(mask1=mask, mask2=mask)
 23  
 24          # No value given for .remove()
 25          with self.assertRaises(ValueError):
 26              mask.remove(())
 27  
 28      def test_mask(self):
 29          # We use DesignMask object to also cover code for _Mask and other
 30          # classes
 31          mask = _msk.DesignMask(name="MyMask")
 32          mask2 = _msk.DesignMask(name="MyMask2")
 33          mask3 = _msk.DesignMask(name="MyMask3")
 34          
 35          alias = mask.alias("Alias")
 36          samenet = mask.same_net
 37  
 38          cond = mask.width >= 1.0
 39          cond2 = mask2.length <= 2.0
 40  
 41          self.assertEqual(mask.width, _msk._MaskProperty(mask=mask, name="width"))
 42          self.assertEqual(
 43              str(alias), "MyMask.alias(Alias)",
 44          )
 45          self.assertNotEqual(mask.width, mask.length)
 46          self.assertEqual(
 47              mask.extend_over(other=mask2),
 48              _msk._DualMaskProperty(
 49                  mask1=mask, mask2=mask2, name="extend_over", commutative=False,
 50              ),
 51          )
 52          self.assertNotEqual(
 53              mask.extend_over(other=mask2),
 54              _msk._DualMaskProperty(
 55                  mask1=mask, mask2=mask3, name="extend_over", commutative=False,
 56              ),
 57          )
 58          self.assertEqual(
 59              mask.enclosed_by(other=mask2),
 60              _msk._DualMaskEnclosureProperty(
 61                  mask1=mask, mask2=mask2, name="enclosed_by",
 62              ),
 63          )
 64          self.assertEqual(
 65              mask.is_inside(mask2, mask3),
 66              _msk._InsideCondition(mask=mask, others=(mask3, mask2)),
 67          )
 68          self.assertEqual(
 69              mask.is_outside(mask2),
 70              _msk._OutsideCondition(mask=mask, others=(mask2)),
 71          )
 72          self.assertEqual(
 73              mask.parts_with(cond),
 74              _msk._PartsWith(mask=mask, condition=cond),
 75          )
 76          with self.assertRaises(TypeError):
 77              mask.parts_with(cond2)
 78          self.assertEqual(
 79              mask.remove(mask2),
 80              _msk._MaskRemove(from_=mask, what=mask2),
 81          )
 82          self.assertEqual(
 83              mask.remove(mask2, mask3),
 84              _msk._MaskRemove(from_=mask, what=_msk.Join(mask2, mask3))
 85          )
 86          self.assertEqual(
 87              alias, _msk._MaskAlias(mask=mask, name="Alias"),
 88          )
 89          self.assertEqual(samenet, _msk._SameNet(mask))
 90  
 91          self.assertNotEqual(alias, "")
 92          self.assertNotEqual(samenet, "")
 93          self.assertNotEqual(mask.extend_over(other=mask2), "")
 94          self.assertNotEqual(mask.enclosed_by(other=mask2), "")
 95          self.assertNotEqual(mask.is_inside(mask2, mask3), "")
 96          self.assertNotEqual(mask.is_outside(mask2), "")
 97          self.assertNotEqual(mask.parts_with(cond), "")
 98          self.assertNotEqual(mask.remove(mask2), "")
 99          self.assertNotEqual(_msk.Join((mask, mask2)), "")
100          self.assertNotEqual(_msk.Intersect((mask, mask3)), "")
101  
102          self.assertEqual(tuple(mask.designmasks), (mask,))
103          self.assertEqual(samenet.designmasks, (mask,))
104          self.assertEqual(set(mask.parts_with(cond).designmasks), {mask})
105          self.assertEqual(set(mask.remove(mask2).designmasks), {mask, mask2})
106          self.assertEqual(set(_msk.Join((mask, mask2)).designmasks), {mask, mask2})
107          self.assertEqual(
108              set(_msk.Intersect((mask, mask2, mask3)).designmasks),
109              {mask, mask2, mask3},
110          )
111  
112          self.assertEqual(_msk.Join((mask, mask2)), _msk.Join((mask2, mask)))
113          self.assertEqual(_msk.Intersect((mask, mask2)), _msk.Intersect((mask2, mask)))
114  
115          self.assertEqual(
116              mask.parts_with(cond).name, 
117              f"{mask.name}.parts_with({cond})",
118          )
119          self.assertEqual(
120              mask.remove(mask2).name,
121              f"{mask.name}.remove({mask2.name})",
122          )
123          self.assertEqual(
124              _msk.Join((mask, mask2)).name,
125              f"join({mask.name},{mask2.name})"
126          )
127          self.assertEqual(
128              _msk.Intersect((mask, mask2, mask3)).name,
129              f"intersect({mask.name},{mask2.name},{mask3.name})"
130          )
131  
132          self.assertEqual(hash(alias), hash(alias.name))
133          self.assertEqual(hash(samenet), hash(samenet.name))
134          self.assertEqual(
135              hash(mask.is_inside(mask2, mask3)),
136              hash(_msk._InsideCondition(mask=mask, others=(mask3, mask2))),
137          )
138          self.assertEqual(
139              hash(mask.parts_with(cond)), 
140              hash(f"{mask.name}.parts_with({cond})"),
141          )
142          self.assertEqual(
143              hash(mask.remove(mask2)),
144              hash((mask, mask2)),
145          )
146          self.assertEqual(
147              hash(mask.remove(_msk.Join((mask2, mask3)))),
148              hash(mask.remove(_msk.Join((mask3, mask2)))),
149          )
150          self.assertEqual(
151              hash(_msk.Join((mask, mask2))),
152              hash(_msk.Join((mask2, mask))),
153          )
154          self.assertEqual(
155              hash(_msk.Intersect((mask, mask2))),
156              hash(_msk.Intersect((mask2, mask))),
157          )
158  
159          self.assertEqual(
160              mask.parts_with(cond).name, 
161              f"{mask.parts_with(cond)!r}", 
162          )
163          self.assertEqual(
164              f"{mask.is_inside(mask2)!r}",
165              f"{mask!r}.is_inside({mask2!r})",
166          )
167  
168      def test_connect(self):
169          mask = _msk.DesignMask(name="mask")
170          mask2 = _msk.DesignMask(name="mask2")
171          mask3 = _msk.DesignMask(name="mask3")
172  
173          conn = _msk.Connect(mask, mask2)
174          conn2 = _msk.Connect(mask2, mask)
175          conn3 = _msk.Connect(mask, (mask2, mask3))
176          conn4 = _msk.Connect((mask3, mask2), mask)
177  
178          self.assertNotEqual(conn, False)
179          self.assertEqual(str(conn), "connect(mask,mask2)")
180  
181          self.assertEqual(conn, conn2)
182          self.assertEqual(conn3, conn4)
183  
184          self.assertEqual(hash(conn), hash(conn2))
185          self.assertEqual(hash(conn3), hash(conn4))