半导体cp测试简易处理方案

B站影视 日本电影 2025-09-12 17:26 1

摘要:最近,有研发的朋友遇到了一个难题:在晶圆做完cp测试后,在切割编带时,需要cp测试的map作为编带的依据,即符合cp测试标准#热问计划#的就编带,不符合cp测试标准的就留在切割完的晶圆上不编带。但是,cp标准是在probe上设定好的,导出的map图也都是根据p

最近,有研发的朋友遇到了一个难题:在晶圆做完cp测试后,在切割编带时,需要cp测试的map作为编带的依据,即符合cp测试标准#热问计划#的就编带,不符合cp测试标准的就留在切割完的晶圆上不编带。但是,cp标准是在probe上设定好的,导出的map图也都是根据probe上设定的标准来导出的,已经固定了,无法更改了。但是有时候又想对导出的数据修改测试标准(降低测试标准),来生成新的map图,这样更多的芯片能够符合标准而能够编带,那么出货的数量就可以增加很多。

问我有什么解决办法?我简单地了解了一下cp测试的数据结构。图1

如图,item列中是要测试的参数,有8项,分别是IL,Ripple,Atten_1,Atten_2,Atten_3,VSWR_1,VSWR_2,FC

而LL(dB),LU(dB)分别为参数的上下限,即测得的数据在这个上下限内就表示合格。 图2

这幅图表示:

No标签列下的1,2,3,...代表的是每一颗芯片。这里只展示了1-13颗芯片的的数据,总芯片数据有十几万粒,即No下数字最大数字为113981.
XY标签下代表的是这颗芯片在晶圆上的坐标,IL,Ripple,Atten_1,Atten_2,Atten_3,VSWR_1,VSWR_2,FC标签下的分别为其测得的性能数据。

soft bin标签下只有1和2.即当某颗芯片中的所有指标满足标准时,soft bin输出为1;有一项不满足标准即输出为2.

了解结构后,我大致知道了他的需求,即在图1中能够修改IL,Ripple,Atten_1,Atten_2,Atten_3,VSWR_1,VSWR_2,FC行中LL(dB),LU(dB)的数值,来改变IL,Ripple,Atten_1,Atten_2,Atten_3,VSWR_1,VSWR_2,FC的标准,即测试的标准。再通过比对每颗芯片测得的数据是否在这个标准中来输出soft bin的值,然后根据坐标与Soft bin值,来生成map图!图3

于是我利用python分为三步来解决这个问题:
1,我先写一个程序,将如图2得到的的测试数据依次在图1的测试标准中比对,得到整个excel中十几万粒芯片的的soft bin值。代码如下:

import pandas as pd
import os
import tkinter as tk
from tkinter import filedialog, ttk

def is_within_standard(value, min_value, max_value):
return min_value

def process_csv(file_path, progress_var, progress_win):
# Read the CSV
df = pd.read_csv(file_path, header=None)

# Extract the standards from the dataframe
standards = {
"IL": (float(df.iloc[5, 10]), float(df.iloc[5, 11])),
"Ripple": (float(df.iloc[6, 10]), float(df.iloc[6, 11])),
"Atten_1": (float(df.iloc[7, 10]), float(df.iloc[7, 11])),
"Atten_2": (float(df.iloc[8, 10]), float(df.iloc[8, 11])),
"Atten_3": (float(df.iloc[9, 10]), float(df.iloc[9, 11])),
"VSWR_1": (float(df.iloc[10, 10]), float(df.iloc[10, 11])),
"VSWR_2": (float(df.iloc[11, 10]), float(df.iloc[11, 11])),
"FC": (float(df.iloc[12, 8]), float(df.iloc[12, 9])),
}

data_rows = len(df) - 15
# Loop through each row in the dataframe to set Soft Bin values
for index in range(15, len(df)):
row = df.iloc[index]

all_within_standard = True # Start by assuming all values are within standard
for col, (min_val, max_val) in standards.items:
col_index = df.columns[df.iloc[14] == col][0]
if not is_within_standard(float(row[col_index]), min_val, max_val):
all_within_standard = False
break # If one value is outside standard, break out of loop

# Set Soft Bin value

df.iloc[index, 11] = 1 if all_within_standard else 2# Update the progress bar
progress_var.set((index - 15) / data_rows * 100)
progress_win.update

# Save the modified dataframe to a new CSV file in the same directory
base_name = os.path.basename(file_path)
name, ext = os.path.splitext(base_name)
new_file_name = f"{name}_final_modified{ext}"
new_file_path = os.path.join(os.path.dirname(file_path), new_file_name)
df.to_csv(new_file_path, index=False, header=None)

progress_win.destroy
root.destroy
return new_file_path

# Ask the user to select the CSV file
root = tk.Tk
root.withdraw
file_path = filedialog.askopenfilename(title="Select the CSV file",
filetypes=[("CSV files", "*.CSV"), ("All files", "*.*")])

if file_path:
# Progress bar window
progress_win = tk.Toplevel(root)
progress_win.title("Processing CSV")

frame = ttk.Frame(progress_win)
frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

ttk.Label(frame, text="Processing...").pack(pady=10)

progress_var = tk.DoubleVar
progress_bar = ttk.Progressbar(frame, variable=progress_var, maximum=100)
progress_bar.pack(fill=tk.X, expand=True)

progress_win.after(100, process_csv, file_path, progress_var, progress_win) # Start processing after 100ms
progress_win.mainloop
else:
print("No file selected.")

生成的情况如下图:图4

只需看soft bin列,由于我修改了测试的标准,soft bin列数值明显与图1原标准的数值发生了变化,只截取了部分,那么整个晶圆上的所有芯片的soft bin数值就被我重新保存为一个新的csv文档。

2,上一个程序得到的Soft bin数值与芯片的XY标,是一列一列的,不便于编带机识别,于是我又写了一个程序把一列一列的soft bin值与XY坐标,转化为可视化更强的map图。map图每一个单元格里填上soft bin数值:1或2,类似于一个宽格式的二维图表。

代码如下:

import pandas as pd
import csv
from tkinter import filedialog
from tkinter import Tk

def extract_coordinates(coord_str):
try:
x_val = int(coord_str.split('Y')[0].split('X')[1])
y_val = int(coord_str.split('Y')[1])
return x_val, y_val
except Exception:
return None, None

create_visualization_map(input_file, output_file):
df = pd.read_csv(input_file, header=None, skiprows=13, usecols=[1, 11], dtype={1: str, 11: str})
df.dropna(inplace=True)

# Create a dictionary to store soft bin values against coordinates
xy_dict = {}
for _, row in df.iterrows:
x, y = extract_coordinates(row[1])
if x is not None and y is not None:
xy_dict[(x, y)] = row[11]

# Identify the min and max X, Y values to create a grid
all_x = [key[0] for key in xy_dict.keys]
all_y = [key[1] for key in xy_dict.keys]

min_x, max_x = min(all_x), max(all_x)
min_y, max_y = min(all_y), max(all_y)

# Create the grid and fill in the values
data =
for y in range(min_y, max_y + 1):
row = [''] * 8 # Adding 8 empty strings at the beginning of each row
for x in range(min_x, max_x + 1):
if (x, y) in xy_dict:
row.append(xy_dict[(x, y)])
else:
row.append('')
data.append(row)

# Write the data to the CSV file
with open(output_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerows(data)

def main:
root = Tk
root.withdraw # This just hides the main window
input_file = filedialog.askopenfilename(title="Select the modified CSV file")
output_file = filedialog.asksaveasfilename(title="Save the visualization map as", defaultextension=".csv", filetypes=[("CSV files", "*.csv")])

if not input_file or not output_file:
print("Operation cancelled.")
returncreate_visualization_map(input_file, output_file)

if __name__ == "__main__":
main

得到的map为:
3,将前两个程序合并为一个程序,封装为exe格式文件,就可以在window系统下运行了。

这个问题完美解决。今天的文章理解起来有些难,只是一个小插曲,后面的文章将继续回归芯片工艺!

来源:小象说科技

相关推荐