parameters: (self, params, placedb)
docstring: @brief initialization
          @param params parameter
          @param placedb placement database
function: def __init__(self, params, placedb):
          """
          @brief initialization
          @param params parameter
          @param placedb placement database
          """
          torch.manual_seed(params.random_seed)
          super(BasicPlace, self).__init__()
  
          tt = time.time()
          self.init_pos = np.zeros(placedb.num_nodes * 2, dtype=placedb.dtype)
          # x position
          self.init_pos[0:placedb.num_physical_nodes] = placedb.node_x
          if params.global_place_flag and params.random_center_init_flag:  # move to center of layout
              logging.info(
                  "move cells to the center of layout with random noise")
              self.init_pos[0:placedb.num_movable_nodes] = np.random.normal(
                  loc=(placedb.xl * 1.0 + placedb.xh * 1.0) / 2,
                  scale=(placedb.xh - placedb.xl) * 0.001,
                  size=placedb.num_movable_nodes)
  
          # y position
          self.init_pos[placedb.num_nodes:placedb.num_nodes +
                        placedb.num_physical_nodes] = placedb.node_y
          if params.global_place_flag and params.random_center_init_flag:  # move to center of layout
              self.init_pos[placedb.num_nodes:placedb.num_nodes +
                            placedb.num_movable_nodes] = np.random.normal(
                                loc=(placedb.yl * 1.0 + placedb.yh * 1.0) / 2,
                                scale=(placedb.yh - placedb.yl) * 0.001,
                                size=placedb.num_movable_nodes)
  
          if placedb.num_filler_nodes:  # uniformly distribute filler cells in the layout
              if len(placedb.regions) > 0:
                  ### uniformly spread fillers in fence region
                  ### for cells in the fence region
                  for i, region in enumerate(placedb.regions):
                      filler_beg, filler_end = placedb.filler_start_map[i : i + 2]
                      subregion_areas = (region[:, 2] - region[:, 0]) * (region[:, 3] - region[:, 1])
                      total_area = np.sum(subregion_areas)
                      subregion_area_ratio = subregion_areas / total_area
                      subregion_num_filler = np.round((filler_end - filler_beg) * subregion_area_ratio)
                      subregion_num_filler[-1] = (filler_end - filler_beg) - np.sum(subregion_num_filler[:-1])
                      subregion_num_filler_start_map = np.concatenate(
                          [np.zeros([1]), np.cumsum(subregion_num_filler)], 0
                      ).astype(np.int32)
                      for j, subregion in enumerate(region):
                          sub_filler_beg, sub_filler_end = subregion_num_filler_start_map[j : j + 2]
                          self.init_pos[
                              placedb.num_physical_nodes
                              + filler_beg
                              + sub_filler_beg : placedb.num_physical_nodes
                              + filler_beg
                              + sub_filler_end
                          ] = np.random.uniform(
                              low=subregion[0],
                              high=subregion[2] - placedb.filler_size_x_fence_region[i],
                              size=sub_filler_end - sub_filler_beg,
                          )
                          self.init_pos[
                              placedb.num_nodes
                              + placedb.num_physical_nodes
                              + filler_beg
                              + sub_filler_beg : placedb.num_nodes
                              + placedb.num_physical_nodes
                              + filler_beg
                              + sub_filler_end
                          ] = np.random.uniform(
                              low=subregion[1],
                              high=subregion[3] - placedb.filler_size_y_fence_region[i],
                              size=sub_filler_end - sub_filler_beg,
                          )
  
                  ### for cells outside fence region
                  filler_beg, filler_end = placedb.filler_start_map[-2:]
                  self.init_pos[
                      placedb.num_physical_nodes + filler_beg : placedb.num_physical_nodes + filler_end
                  ] = np.random.uniform(
                      low=placedb.xl,
                      high=placedb.xh - placedb.filler_size_x_fence_region[-1],
                      size=filler_end - filler_beg,
                  )
                  self.init_pos[
                      placedb.num_nodes
                      + placedb.num_physical_nodes
                      + filler_beg : placedb.num_nodes
                      + placedb.num_physical_nodes
                      + filler_end
                  ] = np.random.uniform(
                      low=placedb.yl,
                      high=placedb.yh - placedb.filler_size_y_fence_region[-1],
                      size=filler_end - filler_beg,
                  )
  
              else:
                  self.init_pos[placedb.num_physical_nodes : placedb.num_nodes] = np.random.uniform(
                      low=placedb.xl,
                      high=placedb.xh - placedb.node_size_x[-placedb.num_filler_nodes],
                      size=placedb.num_filler_nodes,
                  )
                  self.init_pos[
                      placedb.num_nodes + placedb.num_physical_nodes : placedb.num_nodes * 2
                  ] = np.random.uniform(
                      low=placedb.yl,
                      high=placedb.yh - placedb.node_size_y[-placedb.num_filler_nodes],
                      size=placedb.num_filler_nodes,
                  )
  
          logging.debug("prepare init_pos takes %.2f seconds" %
                        (time.time() - tt))
  
          self.device = torch.device("cuda" if params.gpu else "cpu")
  
          # position should be parameter
          # must be defined in BasicPlace
          tt = time.time()
          self.pos = nn.ParameterList(
              [nn.Parameter(torch.from_numpy(self.init_pos).to(self.device))])
          logging.debug("build pos takes %.2f seconds" % (time.time() - tt))
          # shared data on device for building ops
          # I do not want to construct the data from placedb again and again for each op
          tt = time.time()
          self.data_collections = PlaceDataCollection(self.pos, params, placedb,
                                                      self.device)
          logging.debug("build data_collections takes %.2f seconds" %
                        (time.time() - tt))
  
          # similarly I wrap all ops
          tt = time.time()
          self.op_collections = PlaceOpCollection()
          logging.debug("build op_collections takes %.2f seconds" %
                        (time.time() - tt))
  
          tt = time.time()
          # position to pin position
          self.op_collections.pin_pos_op = self.build_pin_pos(
              params, placedb, self.data_collections, self.device)
          # bound nodes to layout region
          self.op_collections.move_boundary_op = self.build_move_boundary(
              params, placedb, self.data_collections, self.device)
          # hpwl and density overflow ops for evaluation
          self.op_collections.hpwl_op = self.build_hpwl(
              params, placedb, self.data_collections,
              self.op_collections.pin_pos_op, self.device)
          # rectilinear minimum steiner tree wirelength from flute
          # can only be called once
          #self.op_collections.rmst_wl_op = self.build_rmst_wl(params, placedb, self.op_collections.pin_pos_op, torch.device("cpu"))
          # legality check
          self.op_collections.legality_check_op = self.build_legality_check(
              params, placedb, self.data_collections, self.device)
          # legalization
          if len(placedb.regions) > 0:
              self.op_collections.legalize_op, self.op_collections.individual_legalize_op = self.build_multi_fence_region_legalization(
              params, placedb, self.data_collections, self.device)
          else:
              self.op_collections.legalize_op = self.build_legalization(
              params, placedb, self.data_collections, self.device)
          # detailed placement
          self.op_collections.detailed_place_op = self.build_detailed_placement(
              params, placedb, self.data_collections, self.device)
          # draw placement
          self.op_collections.draw_place_op = self.build_draw_placement(
              params, placedb)
  
          # flag for rmst_wl_op
          # can only read once
          self.read_lut_flag = True
  
          logging.debug("build BasicPlace ops takes %.2f seconds" %
                        (time.time() - tt))
function_tokens: def __init__ ( self , params , placedb ) : torch . manual_seed ( params . random_seed ) super ( BasicPlace , self ) . __init__ ( ) tt = time . time ( ) self . init_pos = np . zeros ( placedb . num_nodes * 2 , dtype = placedb . dtype ) # x position self . init_pos [ 0 : placedb . num_physical_nodes ] = placedb . node_x if params . global_place_flag and params . random_center_init_flag : # move to center of layout logging . info ( "move cells to the center of layout with random noise" ) self . init_pos [ 0 : placedb . num_movable_nodes ] = np . random . normal ( loc = ( placedb . xl * 1.0 + placedb . xh * 1.0 ) / 2 , scale = ( placedb . xh - placedb . xl ) * 0.001 , size = placedb . num_movable_nodes ) # y position self . init_pos [ placedb . num_nodes : placedb . num_nodes + placedb . num_physical_nodes ] = placedb . node_y if params . global_place_flag and params . random_center_init_flag : # move to center of layout self . init_pos [ placedb . num_nodes : placedb . num_nodes + placedb . num_movable_nodes ] = np . random . normal ( loc = ( placedb . yl * 1.0 + placedb . yh * 1.0 ) / 2 , scale = ( placedb . yh - placedb . yl ) * 0.001 , size = placedb . num_movable_nodes ) if placedb . num_filler_nodes : # uniformly distribute filler cells in the layout if len ( placedb . regions ) > 0 : ### uniformly spread fillers in fence region ### for cells in the fence region for i , region in enumerate ( placedb . regions ) : filler_beg , filler_end = placedb . filler_start_map [ i : i + 2 ] subregion_areas = ( region [ : , 2 ] - region [ : , 0 ] ) * ( region [ : , 3 ] - region [ : , 1 ] ) total_area = np . sum ( subregion_areas ) subregion_area_ratio = subregion_areas / total_area subregion_num_filler = np . round ( ( filler_end - filler_beg ) * subregion_area_ratio ) subregion_num_filler [ - 1 ] = ( filler_end - filler_beg ) - np . sum ( subregion_num_filler [ : - 1 ] ) subregion_num_filler_start_map = np . concatenate ( [ np . zeros ( [ 1 ] ) , np . cumsum ( subregion_num_filler ) ] , 0 ) . astype ( np . int32 ) for j , subregion in enumerate ( region ) : sub_filler_beg , sub_filler_end = subregion_num_filler_start_map [ j : j + 2 ] self . init_pos [ placedb . num_physical_nodes + filler_beg + sub_filler_beg : placedb . num_physical_nodes + filler_beg + sub_filler_end ] = np . random . uniform ( low = subregion [ 0 ] , high = subregion [ 2 ] - placedb . filler_size_x_fence_region [ i ] , size = sub_filler_end - sub_filler_beg , ) self . init_pos [ placedb . num_nodes + placedb . num_physical_nodes + filler_beg + sub_filler_beg : placedb . num_nodes + placedb . num_physical_nodes + filler_beg + sub_filler_end ] = np . random . uniform ( low = subregion [ 1 ] , high = subregion [ 3 ] - placedb . filler_size_y_fence_region [ i ] , size = sub_filler_end - sub_filler_beg , ) ### for cells outside fence region filler_beg , filler_end = placedb . filler_start_map [ - 2 : ] self . init_pos [ placedb . num_physical_nodes + filler_beg : placedb . num_physical_nodes + filler_end ] = np . random . uniform ( low = placedb . xl , high = placedb . xh - placedb . filler_size_x_fence_region [ - 1 ] , size = filler_end - filler_beg , ) self . init_pos [ placedb . num_nodes + placedb . num_physical_nodes + filler_beg : placedb . num_nodes + placedb . num_physical_nodes + filler_end ] = np . random . uniform ( low = placedb . yl , high = placedb . yh - placedb . filler_size_y_fence_region [ - 1 ] , size = filler_end - filler_beg , ) else : self . init_pos [ placedb . num_physical_nodes : placedb . num_nodes ] = np . random . uniform ( low = placedb . xl , high = placedb . xh - placedb . node_size_x [ - placedb . num_filler_nodes ] , size = placedb . num_filler_nodes , ) self . init_pos [ placedb . num_nodes + placedb . num_physical_nodes : placedb . num_nodes * 2 ] = np . random . uniform ( low = placedb . yl , high = placedb . yh - placedb . node_size_y [ - placedb . num_filler_nodes ] , size = placedb . num_filler_nodes , ) logging . debug ( "prepare init_pos takes %.2f seconds" % ( time . time ( ) - tt ) ) self . device = torch . device ( "cuda" if params . gpu else "cpu" ) # position should be parameter # must be defined in BasicPlace tt = time . time ( ) self . pos = nn . ParameterList ( [ nn . Parameter ( torch . from_numpy ( self . init_pos ) . to ( self . device ) ) ] ) logging . debug ( "build pos takes %.2f seconds" % ( time . time ( ) - tt ) ) # shared data on device for building ops # I do not want to construct the data from placedb again and again for each op tt = time . time ( ) self . data_collections = PlaceDataCollection ( self . pos , params , placedb , self . device ) logging . debug ( "build data_collections takes %.2f seconds" % ( time . time ( ) - tt ) ) # similarly I wrap all ops tt = time . time ( ) self . op_collections = PlaceOpCollection ( ) logging . debug ( "build op_collections takes %.2f seconds" % ( time . time ( ) - tt ) ) tt = time . time ( ) # position to pin position self . op_collections . pin_pos_op = self . build_pin_pos ( params , placedb , self . data_collections , self . device ) # bound nodes to layout region self . op_collections . move_boundary_op = self . build_move_boundary ( params , placedb , self . data_collections , self . device ) # hpwl and density overflow ops for evaluation self . op_collections . hpwl_op = self . build_hpwl ( params , placedb , self . data_collections , self . op_collections . pin_pos_op , self . device ) # rectilinear minimum steiner tree wirelength from flute # can only be called once #self.op_collections.rmst_wl_op = self.build_rmst_wl(params, placedb, self.op_collections.pin_pos_op, torch.device("cpu")) # legality check self . op_collections . legality_check_op = self . build_legality_check ( params , placedb , self . data_collections , self . device ) # legalization if len ( placedb . regions ) > 0 : self . op_collections . legalize_op , self . op_collections . individual_legalize_op = self . build_multi_fence_region_legalization ( params , placedb , self . data_collections , self . device ) else : self . op_collections . legalize_op = self . build_legalization ( params , placedb , self . data_collections , self . device ) # detailed placement self . op_collections . detailed_place_op = self . build_detailed_placement ( params , placedb , self . data_collections , self . device ) # draw placement self . op_collections . draw_place_op = self . build_draw_placement ( params , placedb ) # flag for rmst_wl_op # can only read once self . read_lut_flag = True logging . debug ( "build BasicPlace ops takes %.2f seconds" % ( time . time ( ) - tt ) )