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))
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)
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))
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)
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))
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))
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)
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))
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))
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)
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)