Example #1
0
    def test_obstruction(self) -> None:
        d = {
            "type": "obstruction",
            "path": "path/to/placement",
            "x": Decimal(4),
            "y": Decimal(6),
            "width": Decimal(10),
            "height": Decimal(20),
            "orientation": "mx"
        }
        with self.assertRaises(ValueError):
            # This should assert because we are missing obs_types
            tc = PlacementConstraint.from_dict(d)

        d.update({"obs_types": ["place"]})
        tc = PlacementConstraint.from_dict(d)
        self.assertEqual(tc.type, PlacementConstraintType.Obstruction)
        self.assertEqual(tc.path, "path/to/placement")
        self.assertEqual(tc.x, Decimal(4))
        self.assertEqual(tc.y, Decimal(6))
        self.assertEqual(tc.width, Decimal(10))
        self.assertEqual(tc.height, Decimal(20))
        self.assertEqual(tc.orientation, "mx")
        with self.assertRaises(ValueError):
            m = {"margins": Margins.empty().to_dict()}
            # This should assert because margins are not allowed
            tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #2
0
 def action_map(self) -> Dict[str, CLIActionType]:
     """Return the mapping of valid actions -> functions for each action of the command-line driver."""
     return add_dicts({
         "dump": self.dump_action,
         "dump-macrosizes": self.dump_macrosizes_action,
         "dump_macrosizes": self.dump_macrosizes_action,
         "sram-generator": self.sram_generator_action,
         "sram_generator": self.sram_generator_action,
         "synthesis": self.synthesis_action,
         "syn": self.synthesis_action,
         "par": self.par_action,
         "synthesis_to_par": self.synthesis_to_par_action,
         "synthesis-to-par": self.synthesis_to_par_action,
         "syn_to_par": self.synthesis_to_par_action,
         "syn-to-par": self.synthesis_to_par_action,
         "synthesis_par": self.synthesis_par_action,
         "synthesis-par": self.synthesis_par_action,
         "syn_par": self.synthesis_par_action,
         "syn-par": self.synthesis_par_action,
         "hier_par_to_syn": self.hier_par_to_syn_action,
         "hier-par-to-syn": self.hier_par_to_syn_action,
         "par_to_drc": self.par_to_drc_action,
         "par-to-drc": self.par_to_drc_action,
         "par_to_lvs": self.par_to_lvs_action,
         "par-to-lvs": self.par_to_lvs_action,
         "drc": self.drc_action,
         "lvs": self.lvs_action
     }, self.all_hierarchical_actions)
Example #3
0
 def test_hierarchical(self) -> None:
     d = {
         "type": "hierarchical",
         "path": "path/to/placement",
         "x": Decimal(4),
         "y": Decimal(6),
         "master": "foo",
         "orientation": "mx"
     }
     with self.assertRaises(ValueError):
         # This should assert because width and height are missing
         tc = PlacementConstraint.from_dict(d)
     d.update({"width": Decimal(10), "height": Decimal(20)})
     tc = PlacementConstraint.from_dict(d)
     self.assertEqual(tc.type, PlacementConstraintType.Hierarchical)
     self.assertEqual(tc.path, "path/to/placement")
     self.assertEqual(tc.x, Decimal(4))
     self.assertEqual(tc.y, Decimal(6))
     self.assertEqual(tc.width, Decimal(10))
     self.assertEqual(tc.height, Decimal(20))
     self.assertEqual(tc.master, "foo")
     self.assertEqual(tc.orientation, "mx")
     with self.assertRaises(ValueError):
         m = {"margins": Margins.empty().to_dict()}
         # This should assert because margins are not allowed
         tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #4
0
 def action_map(self) -> Dict[str, CLIActionType]:
     """Return the mapping of valid actions -> functions for each action of the command-line driver."""
     return add_dicts(
         {
             "dump": self.dump_action,
             "dump-macrosizes": self.dump_macrosizes_action,
             "dump_macrosizes": self.dump_macrosizes_action,
             "sram-generator": self.sram_generator_action,
             "sram_generator": self.sram_generator_action,
             "synthesis": self.synthesis_action,
             "syn": self.synthesis_action,
             "par": self.par_action,
             "synthesis_to_par": self.synthesis_to_par_action,
             "synthesis-to-par": self.synthesis_to_par_action,
             "syn_to_par": self.synthesis_to_par_action,
             "syn-to-par": self.synthesis_to_par_action,
             "synthesis_par": self.synthesis_par_action,
             "synthesis-par": self.synthesis_par_action,
             "syn_par": self.synthesis_par_action,
             "syn-par": self.synthesis_par_action,
             "hier_par_to_syn": self.hier_par_to_syn_action,
             "hier-par-to-syn": self.hier_par_to_syn_action,
             "par_to_drc": self.par_to_drc_action,
             "par-to-drc": self.par_to_drc_action,
             "par_to_lvs": self.par_to_lvs_action,
             "par-to-lvs": self.par_to_lvs_action,
             "drc": self.drc_action,
             "lvs": self.lvs_action
         }, self.all_hierarchical_actions)
Example #5
0
 def test_hierarchical(self) -> None:
     d = {"type": "hierarchical",
          "path": "path/to/placement",
          "x": Decimal(4),
          "y": Decimal(6),
          "master": "foo",
          "orientation": "mx"}
     with self.assertRaises(ValueError):
         # This should assert because width and height are missing
         tc = PlacementConstraint.from_dict(d)
     d.update({
          "width": Decimal(10),
          "height": Decimal(20)})
     tc = PlacementConstraint.from_dict(d)
     self.assertEqual(tc.type, PlacementConstraintType.Hierarchical)
     self.assertEqual(tc.path, "path/to/placement")
     self.assertEqual(tc.x, Decimal(4))
     self.assertEqual(tc.y, Decimal(6))
     self.assertEqual(tc.width, Decimal(10))
     self.assertEqual(tc.height, Decimal(20))
     self.assertEqual(tc.master, "foo")
     self.assertEqual(tc.orientation, "mx")
     with self.assertRaises(ValueError):
         m = {"margins": Margins.empty().to_dict()}
         # This should assert because margins are not allowed
         tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #6
0
    def test_obstruction(self) -> None:
        d = {"type": "obstruction",
             "path": "path/to/placement",
             "x": Decimal(4),
             "y": Decimal(6),
             "width": Decimal(10),
             "height": Decimal(20),
             "orientation": "mx"}
        with self.assertRaises(ValueError):
            # This should assert because we are missing obs_types
            tc = PlacementConstraint.from_dict(d)

        d.update({"obs_types": ["place"]})
        tc = PlacementConstraint.from_dict(d)
        self.assertEqual(tc.type, PlacementConstraintType.Obstruction)
        self.assertEqual(tc.path, "path/to/placement")
        self.assertEqual(tc.x, Decimal(4))
        self.assertEqual(tc.y, Decimal(6))
        self.assertEqual(tc.width, Decimal(10))
        self.assertEqual(tc.height, Decimal(20))
        self.assertEqual(tc.orientation, "mx")
        with self.assertRaises(ValueError):
            m = {"margins": Margins.empty().to_dict()}
            # This should assert because margins are not allowed
            tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #7
0
 def action_map(self) -> Dict[str, CLIActionType]:
     """Return the mapping of valid actions -> functions for each action of the command-line driver."""
     return add_dicts(
         {
             "synthesis": self.synthesis_action,
             "syn": self.synthesis_action,
             "par": self.par_action,
             "synthesis_to_par": self.synthesis_to_par_action,
             "synthesis-to-par": self.synthesis_to_par_action,
             "syn_to_par": self.synthesis_to_par_action,
             "syn-to-par": self.synthesis_to_par_action,
             "synthesis_par": self.synthesis_par_action,
             "synthesis-par": self.synthesis_par_action,
             "syn_par": self.synthesis_par_action,
             "syn-par": self.synthesis_par_action
         }, self.all_hierarchical_actions)
Example #8
0
 def test_hardmacro(self) -> None:
     d = {"type": "hardmacro",
          "path": "path/to/placement",
          "x": Decimal(4),
          "y": Decimal(6),
          "width": Decimal(10),
          "height": Decimal(20),
          "orientation": "mx"}
     tc = PlacementConstraint.from_dict(d)
     self.assertEqual(tc.type, PlacementConstraintType.HardMacro)
     self.assertEqual(tc.path, "path/to/placement")
     self.assertEqual(tc.x, Decimal(4))
     self.assertEqual(tc.y, Decimal(6))
     self.assertEqual(tc.width, Decimal(10))
     self.assertEqual(tc.height, Decimal(20))
     self.assertEqual(tc.orientation, "mx")
     with self.assertRaises(ValueError):
         m = {"margins": Margins.empty().to_dict()}
         # This should assert because margins are not allowed
         tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #9
0
    def test_toplevel(self) -> None:
        d = {"type": "toplevel",
             "path": "path/to/placement",
             "x": Decimal(0),
             "y": Decimal(0),
             "width": Decimal(1000),
             "height": Decimal(2000)}
        with self.assertRaises(ValueError):
            # This should assert because margins are required
            tc = PlacementConstraint.from_dict(d)

        # Add margins
        m = {"margins": Margins.empty().to_dict()}
        tc = PlacementConstraint.from_dict(add_dicts(d, m))
        self.assertEqual(tc.type, PlacementConstraintType.TopLevel)
        self.assertEqual(tc.path, "path/to/placement")
        self.assertEqual(tc.x, Decimal(0))
        self.assertEqual(tc.y, Decimal(0))
        self.assertEqual(tc.width, Decimal(1000))
        self.assertEqual(tc.height, Decimal(2000))
Example #10
0
 def test_hardmacro(self) -> None:
     d = {"type": "hardmacro",
          "path": "path/to/placement",
          "x": Decimal(4),
          "y": Decimal(6),
          "width": Decimal(10),
          "height": Decimal(20),
          "orientation": "mx"}
     tc = PlacementConstraint.from_dict(d)
     self.assertEqual(tc.type, PlacementConstraintType.HardMacro)
     self.assertEqual(tc.path, "path/to/placement")
     self.assertEqual(tc.x, Decimal(4))
     self.assertEqual(tc.y, Decimal(6))
     self.assertEqual(tc.width, Decimal(10))
     self.assertEqual(tc.height, Decimal(20))
     self.assertEqual(tc.orientation, "mx")
     with self.assertRaises(ValueError):
         m = {"margins": Margins.empty().to_dict()}
         # This should assert because margins are not allowed
         tc = PlacementConstraint.from_dict(add_dicts(d, m))
Example #11
0
    def test_toplevel(self) -> None:
        d = {"type": "toplevel",
             "path": "path/to/placement",
             "x": Decimal(0),
             "y": Decimal(0),
             "width": Decimal(1000),
             "height": Decimal(2000)}
        with self.assertRaises(ValueError):
            # This should assert because margins are required
            tc = PlacementConstraint.from_dict(d)

        # Add margins
        m = {"margins": Margins.empty().to_dict()}
        tc = PlacementConstraint.from_dict(add_dicts(d, m))
        self.assertEqual(tc.type, PlacementConstraintType.TopLevel)
        self.assertEqual(tc.path, "path/to/placement")
        self.assertEqual(tc.x, Decimal(0))
        self.assertEqual(tc.y, Decimal(0))
        self.assertEqual(tc.width, Decimal(1000))
        self.assertEqual(tc.height, Decimal(2000))
Example #12
0
    def from_masters_and_dict(masters: List[MacroSize], constraint: dict) -> "PlacementConstraint":
        """
        Create a PlacementConstraint tuple from a constraint dict and a list of masters. This method differs from from_dict by
        allowing the width and height to be auto-filled from a list of masters for the Hierarchical and HardMacro constraint types.

        :param masters: A list of MacroSize tuples containing cell macro definitions
        :param constraint: A dict containing information to be parsed into a PlacementConstraint tuple
        :return: A PlacementConstraint tuple
        """

        constraint_type = PlacementConstraintType.from_str(str(constraint["type"]))
        master = PlacementConstraint._get_master(constraint_type, constraint)

        checked_types = [PlacementConstraintType.Hierarchical, PlacementConstraintType.HardMacro]
        width_check = None  # type: Optional[Decimal]
        height_check = None  # type: Optional[Decimal]
        # Get the "Master" values
        if constraint_type == PlacementConstraintType.Hierarchical:
            # This should be true given the code above, but sanity check anyway
            assert master is not None
            matches = [x for x in masters if x.name == master]
            if len(matches) > 0:
                width_check = matches[0].width
                height_check = matches[0].height
            else:
                raise ValueError("Could not find a master for hierarchical cell {} in masters list.".format(master))
        elif constraint_type == PlacementConstraintType.HardMacro:
            # TODO(johnwright) for now we're allowing HardMacros to be flexible- checks are performed if the data exists, but otherwise
            # we will "trust" the provided width and height. They aren't actually used, so this is not super important at the moment.
            # ucb-bar/hammer#414
            if master is not None:
                matches = [x for x in masters if x.name == master]
                if len(matches) > 0:
                    width_check = matches[0].width
                    height_check = matches[0].height
        else:
            assert constraint_type not in checked_types, "Should not get here; update checked_types."

        width = None
        height = None

        if "width" in constraint:
            width = Decimal(str(constraint["width"]))
        else:
            width = width_check

        if "height" in constraint:
            height = Decimal(str(constraint["height"]))
        else:
            height = height_check

        # Perform the check
        if constraint_type in checked_types:
            if height != height_check and height_check is not None:
                raise ValueError("Optional height value {} must equal the master value {} for constraint: {}".format(height, height_check, constraint))
            if width != width_check and width_check is not None:
                raise ValueError("Optional width value {} must equal the master value {} for constraint: {}".format(width, width_check, constraint))

        updated_constraint = constraint
        if width is not None:
            updated_constraint = add_dicts(updated_constraint, {'width': width})
        if height is not None:
            updated_constraint = add_dicts(updated_constraint, {'height': height})

        return PlacementConstraint.from_dict(updated_constraint)
Example #13
0
    def from_masters_and_dict(masters: List[MacroSize],
                              constraint: dict) -> "PlacementConstraint":
        """
        Create a PlacementConstraint tuple from a constraint dict and a list of masters. This method differs from from_dict by
        allowing the width and height to be auto-filled from a list of masters for the Hierarchical and HardMacro constraint types.

        :param masters: A list of MacroSize tuples containing cell macro definitions
        :param constraint: A dict containing information to be parsed into a PlacementConstraint tuple
        :return: A PlacementConstraint tuple
        """

        constraint_type = PlacementConstraintType.from_str(
            str(constraint["type"]))
        master = PlacementConstraint._get_master(constraint_type, constraint)

        checked_types = [
            PlacementConstraintType.Hierarchical,
            PlacementConstraintType.HardMacro
        ]
        width_check = None  # type: Optional[Decimal]
        height_check = None  # type: Optional[Decimal]
        # Get the "Master" values
        if constraint_type == PlacementConstraintType.Hierarchical:
            # This should be true given the code above, but sanity check anyway
            assert master is not None
            matches = [x for x in masters if x.name == master]
            if len(matches) > 0:
                width_check = Decimal(str(matches[0].width))
                height_check = Decimal(str(matches[0].height))
            else:
                raise ValueError(
                    "Could not find a master for hierarchical cell {} in masters list."
                    .format(master))
        elif constraint_type == PlacementConstraintType.HardMacro:
            # TODO(johnwright) for now we're allowing HardMacros to be flexible- checks are performed if the data exists, but otherwise
            # we will "trust" the provided width and height. They aren't actually used, so this is not super important at the moment.
            # ucb-bar/hammer#414
            if master is not None:
                matches = [x for x in masters if x.name == master]
                if len(matches) > 0:
                    width_check = Decimal(str(matches[0].width))
                    height_check = Decimal(str(matches[0].height))
        else:
            assert constraint_type not in checked_types, "Should not get here; update checked_types."

        width = None
        height = None

        if "width" in constraint:
            width = Decimal(str(constraint["width"]))
        else:
            width = width_check

        if "height" in constraint:
            height = Decimal(str(constraint["height"]))
        else:
            height = height_check

        # Perform the check
        if constraint_type in checked_types:
            if height != height_check and height_check is not None:
                raise ValueError(
                    "Optional height value {} must equal the master value {} for constraint: {}"
                    .format(height, height_check, constraint))
            if width != width_check and width_check is not None:
                raise ValueError(
                    "Optional width value {} must equal the master value {} for constraint: {}"
                    .format(width, width_check, constraint))

        updated_constraint = constraint
        if width is not None:
            updated_constraint = add_dicts(updated_constraint,
                                           {'width': width})
        if height is not None:
            updated_constraint = add_dicts(updated_constraint,
                                           {'height': height})

        return PlacementConstraint.from_dict(updated_constraint)