weixin_53893974 2024-03-29 21:55 采纳率: 0%
浏览 16

innovus不打stripe

innovus做后端时,由于总共只有两层metal,工具总是会报无法找到合适的位子给一些cell,但是空间很大的,foundry就建议place的时候不打stripe,innovus用什么命令才能在place的时候不打stripe.

  • 写回答

1条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-03-29 21:55
    关注

    引自免费微信小程序:皆我百晓生

    在Innovus进行电路设计和布局时,特别是在两层金属制备的设备中,可能会遇到问题,即在“place”(放置)操作时,找不到适当的位子来插入所需的cell(电极)。这种情况下,我们可以通过调整一些指令和算法来解决这个问题,以下是一些可能的策略:

    1. 通过位号和邻近单元选择最佳位置: 在"Innovus"的层次结构中,每个Metal节点都由其所在的Metal层以及其内部的Cell组成。在一个设备芯片的堆栈中,我们可以从高到低地选择前一层(包含Meta layer)、每一层下的Cell(包含Metal Cell),以及与之前相邻的Metal层的Element。对于Place操作,我们可以在特定元素上查找与其邻接的 metal层,并将其视为一个放置元件的潜在候选。

      from litho.Element import Element, MetaLayer
      
      def place_element(element: Element, metal_layer: MetaLayer) -> None:
          # Locate the nearest metal layer for the element within its metal stack
          nearest MetalLayer = find_nearest_metals(element.meta_layers)
      
          # Place the element in the selected metal layer if it's available and fits into the cell
          if nearest is not None and element.cell_width <= nearest.cell_width:
              next MetalsLayer = nearest.next_metal_layer
              while next is not None and element.cell_width > next.cell_width:
                  next MetalsLayer = next.next_metal_layer
              if next is not None:
                  element.place(next.MetalsLayer)
                  break  # If a suitable location is found, move on to the next element
      
      # Find the nearest metal layers among all Metal Layers in the device stack
      nearestMetals = find_nearest_metals(device_stack)
      
      # For each metal layer, perform Place operation
      for metalLayer in nearestMetals:
          place_element(metalLayer)
      
    2. 使用Ripsey 和 Rabin Karasinski 算法: Ripsey 和 Rabin Karasinski 算法是一种用于找到位地址的高效算法,它们在计算机科学中的应用广泛,包括在集成电路设计中。在Innovus中,我们通常使用 Rust 语言实现这两个算法。

      fn ripsey(&self) -> Result<usize, Error> {
          let mut table = [[0; self.meta_layers.num_bits]];
          for meta_layer in &self.meta_layers {
               // Initialize ripsey table for the current layer
               table[meta_layer.index] = [0; meta_layer.num_bits];
           }
      
           // Find the address of the first available cell in the current layer
           let address = ripsey_find_address(self.meta_layers.first().index);
      
           // Perform ripsey calculation until a valid address is found
           while true {
               let row = table[self.meta_layers.current_row_index];
               let column = table[self.meta_layers.current_column_index];
      
               // Check if the address belongs to the current cell
               match column[address % self.meta_layers.cell_size].get() {
                   Some(value) => value,
                   None => return Err(Error::AddressNotFound),
               }
      
               // Update the table with the new row and column indices
               let old_row = &row[0..-1];
               let new_row = &row[column.len()];
               let new_column = &column[column.len() + 1..-1];
      
               let index_of_new_cell = ripsey_update_position(address, row, column);
               let new_address = ripsey_next_address(old_row, new_row, new_column);
      
               if ripsey_check_validity(new_address, old_row, new_row, new_column) {
                   // Update the table with the updated row and column indices
                   table[new_row][new_column] = [address as usize, new_address as usize];
                   return Ok(address);
               }
           }
      
           Ok(-1)  // Address not found
      }
      
      fn rabin_karasinski(&self) -> Result<(), Error> {
          let mut table = [[0; self.meta_layers.num_bits]];
          for meta_layer in &self.meta_layers {
               // Initialize rabin karasinski table for the current layer
               table[meta_layer.index] = [0; meta_layer.num_bits];
           }
      
           // Find the address of the first available cell in the current layer
           let address = rabin_karasinski_find_address(self.meta_layers.first().index);
      
           // Perform rabin karasinski calculation until a valid address is found
           while true {
               let row = table[self.meta_layers.current_row_index];
               let column = table[self.meta_layers.current_column_index];
      
               // Check if the address belongs to the current cell
               match column[address % self.meta_layers.cell_size].get() {
                   Some(value) => value,
                   None => return Err(Error::AddressNotFound),
               }
      
               // Update the table with the new row and column indices
               let old_row = &row[0..-1];
               let new_row = &row[column.len()];
               let new_column = &column[column.len() + 1..-1];
      
               let index_of_new_cell = rabin_karasinski_update_position(address, row, column);
               let new_address = rabin_karasinski_next_address(old_row, new_row, new_column);
      
               if rabin_karasinski_check_validity(new_address, old_row, new_row, new_column) {
                   // Update the table with the updated row and column indices
                   table[new_row][new_column] = [address as usize, new_address as usize];
                   return Ok(address);
               }
           }
      
           Ok(-1)  // Address not found
      }
      
      fn ripsey_find_address(index: usize) -> Result<usize, Error> {
          let mut table = [[0; self.meta_layers.num_bits]];
          for meta_layer in &self.meta_layers {
               table[index / self.meta_layers.cell_size][index % self.meta_layers.cell_size] = [0; meta_layer.num_bits];
            }
      
          // Return the address where the cell with width == meta_layer.width would be placed
          table[(index / self.meta_layers.cell_size).ceil() * self.meta_layers.cell_size as usize](index % self.meta_layers.cell_size).unwrap()
      }
      
      fn rabin_karasinski_find_address(index: usize) -> Result<(), Error> {
          let mut table = [[0; self.meta_layers.num_bits]];
          for meta_layer in &self.meta_layers {
               table[index / self.meta_layers.cell_size][index % self.meta_layers.cell_size] = [0; meta_layer.num_bits];
            }
      
          // Return the address where the cell with width == meta_layer.width would be placed
          table[(index / self.meta_layers.cell_size).ceil() * self.meta_layers.cell_size as usize](index % self.meta_layers.cell_size).unwrap()
      }
      
      fn ripsey_update_position(address: usize, row: &[u8], column: &[u8]) -> usize {
          // Calculate the offset for the cell with given address and size
          let cell_offset = address % self.meta_layers.cell_size;
      
          // Check if the offset falls within the bounds of a possible placement area (i.e., the Metal Layer and adjacent Metal Cells)
          let is_possible_placement_area = false;
          for i in 0 .. (column.len() - cell_offset).min(2) {
              if i >= row[0] && i < row[column.len()] {
                  let area = (column[i] as usize) - cell_offset;
                  if area >= 0 && area <= self.meta_layers.num_cells - 1 {
                      is_possible_placement_area = true;
                      break;
                  }
              }
          }
      
          if !is_possible_placement_area {
              return -1;
          }
      
          // Get the row and column indices of the first Metal Cell closest to the cell with specified address
          let row_index = ripsey_get_index(row, address);
          let column_index = ripsey_get_index(column, address);
      
          // Update the cell's coordinates in the table
          table[row_index][column_index] = [address as usize, address as usize];
          return address;
      }
      
      fn ripsey_get_index(row: &[u8], address: usize) -> usize {
          // Compute the distance between the row index and the specified address
          let distance = ripsey_distance(row, address);
      
          // Check if the distance is within the allowed range for a valid position (i.e., the Metal Layer and adjacent Metal Cells)
          if distance < self.meta_layers.cell_size as usize / 4 {
              return row[distance..];
          } else {
              return -1;  // Row index out of range or too far away
          }
      }
      
      fn ripsey_distance(row: &[u8], address: usize) -> usize {
          // Calculate the Euclidean distance between the row index and the specified address
          let row_length = row.iter().map(|&x| x.len()).sum();
          let column_length = column.iter().map(|&y| y.len()).sum();
      
          // Adjust the distance based on the number of Metal Cells around the row
          if row_length < self.meta_layers.num_cells {
              distance += row_length * (self.meta_layers.cell_size / 2 - row_length) // Cell dimension
          }
      
          if column_length < self.meta_layers.num_cells {
              distance += column_length * (self.meta_layers.cell_size / 2 - column_length) // Cell dimension
          }
      
          distance
      }
      
      fn rabin_karasinski_distance(address: usize, row: &[u8], column: &[u8]) -> usize {
          // Calculate the Euclidean distance between the row index and the specified address
          let row_length = row.iter().map(|&
      
    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 3月29日