CPU được thiết kế và xây dựng như thế nào
- OFREZH EDITOR
- 13 thg 3
- 13 phút đọc

Chúng ta đều nghĩ CPU là "bộ não" của máy tính, nhưng điều đó thực sự có nghĩa là gì? Điều gì đang diễn ra bên trong hàng tỷ bóng bán dẫn giúp máy tính của bạn hoạt động? Trong loạt bài gồm bốn phần này, chúng ta sẽ tập trung vào thiết kế phần cứng máy tính, đề cập đến những điều cơ bản tạo nên chức năng của máy tính.
Chuỗi bài này sẽ đề cập đến kiến trúc máy tính, thiết kế mạch xử lý, VLSI (tích hợp quy mô rất lớn), chế tạo chip và xu hướng tương lai trong ngành điện toán. Nếu bạn luôn quan tâm đến chi tiết về cách bộ xử lý hoạt động bên trong, hãy theo dõi – đây là những thông tin bạn cần biết để bắt đầu.
Phần 1: Kiến trúc máy tính cơ bản(bộ hướng dẫn, bộ nhớ đệm, đường ống, siêu phân luồng)
Phần 2: Quy trình thiết kế CPU(sơ đồ, bóng bán dẫn, cổng logic, xung nhịp)
Phần 3: Bố trí và xây dựng Chip vật lý(pha tạp, nút xử lý, chế tạo silicon)
Phần 4: Xu hướng Chủ đề nóng trong tương lai về Kiến trúc máy tính(biển máy gia tốc, tích hợp 3D, ASIC, điện toán gần bộ nhớ)
CPU thực sự có chức năng gì?

Hãy bắt đầu ở cấp độ rất cao với những gì bộ xử lý làm và cách các khối xây dựng kết hợp với nhau trong một thiết kế hoạt động. Điều này bao gồm lõi bộ xử lý, hệ thống phân cấp bộ nhớ, dự đoán nhánh và nhiều hơn nữa. Trước tiên, chúng ta cần một định nghĩa cơ bản về những gì CPU làm.
Giải thích đơn giản nhất là CPU tuân theo một tập hợp các lệnh để thực hiện một số thao tác trên một tập hợp các đầu vào. Ví dụ, điều này có thể là đọc một giá trị từ bộ nhớ, thêm nó vào một giá trị khác và cuối cùng lưu trữ kết quả trở lại bộ nhớ ở một vị trí khác. Nó cũng có thể là một cái gì đó phức tạp hơn, như chia hai số nếu kết quả của phép tính trước đó lớn hơn không.
Khi bạn muốn chạy một chương trình như hệ điều hành hoặc trò chơi, bản thân chương trình là một chuỗi các lệnh để CPU thực thi. Các lệnh này được tải từ bộ nhớ và trên một bộ xử lý đơn giản, chúng được thực thi từng lệnh một cho đến khi chương trình hoàn tất. Trong khi các nhà phát triển phần mềm viết chương trình của họ bằng các ngôn ngữ cấp cao như C++ hoặc Python, chẳng hạn, bộ xử lý không thể hiểu được điều đó. Nó chỉ hiểu 1 và 0, vì vậy chúng ta cần một cách để biểu diễn mã theo định dạng này.

Những điều cơ bản về lệnh CPU
Các chương trình được biên dịch thành một tập hợp các lệnh cấp thấp được gọi là ngôn ngữ lắp ráp như một phần của Kiến trúc tập lệnh (ISA). Đây là tập hợp các lệnh mà CPU được xây dựng để hiểu và thực thi. Một số ISA phổ biến nhất là x86, MIPS, ARM, RISC-V và PowerPC. Giống như cú pháp để viết một hàm trong C++ khác với một hàm thực hiện cùng một việc trong Python, mỗi ISA có cú pháp riêng.
Các ISA này có thể được chia thành hai loại chính: độ dài cố định và độ dài thay đổi. RISC-V ISA sử dụng các lệnh có độ dài cố định, nghĩa là một số bit được xác định trước trong mỗi lệnh sẽ xác định loại lệnh đó là gì. Điều này khác với x86, sử dụng các lệnh có độ dài thay đổi. Trong x86, các lệnh có thể được mã hóa theo nhiều cách khác nhau và với số lượng bit khác nhau cho các phần khác nhau. Do tính phức tạp này, bộ giải mã lệnh trong CPU x86 thường là phần phức tạp nhất trong toàn bộ thiết kế.
Các lệnh có độ dài cố định cho phép giải mã dễ dàng hơn do cấu trúc thông thường của chúng nhưng giới hạn tổng số lệnh mà ISA có thể hỗ trợ. Trong khi các phiên bản phổ biến của kiến trúc RISC-V có khoảng 100 lệnh và là mã nguồn mở, x86 là độc quyền và không ai thực sự biết có bao nhiêu lệnh tồn tại. Mọi người thường tin rằng có một vài nghìn lệnh x86, nhưng con số chính xác không được công khai. Mặc dù có sự khác biệt giữa các ISA, nhưng tất cả chúng đều mang về cơ bản cùng một chức năng cốt lõi.

Ví dụ về một số lệnh RISC-V. Mã lệnh bên phải là 7 bit và xác định loại lệnh. Mỗi lệnh cũng chứa các bit cho các thanh ghi nào để sử dụng và các chức năng nào để thực hiện. Đây là cách các lệnh lắp ráp được chia nhỏ thành nhị phân để CPU có thể hiểu.
Bây giờ chúng ta đã sẵn sàng bật máy tính và bắt đầu chạy mọi thứ. Thực hiện một lệnh thực sự có một số phần cơ bản được chia nhỏ qua nhiều giai đoạn của bộ xử lý.
Lấy, Giải mã, Thực thi: Chu kỳ thực thi của CPU
Bước đầu tiên là lấy lệnh từ bộ nhớ vào CPU để bắt đầu thực thi. Ở bước thứ hai, lệnh được giải mã để CPU có thể xác định đó là loại lệnh nào. Có nhiều loại, bao gồm lệnh số học, lệnh nhánh và lệnh bộ nhớ. Khi CPU biết loại lệnh nào đang thực thi, các toán hạng cho lệnh sẽ được thu thập từ bộ nhớ hoặc các thanh ghi bên trong CPU. Nếu bạn muốn cộng số A với số B, bạn không thể thực hiện phép cộng cho đến khi bạn thực sự biết giá trị của A và B. Hầu hết các bộ xử lý hiện đại đều là 64 bit, nghĩa là kích thước của mỗi giá trị dữ liệu là 64 bit.

64-bit đề cập đến chiều rộng của một thanh ghi CPU, đường dẫn dữ liệu và/hoặc địa chỉ bộ nhớ. Đối với người dùng hàng ngày, điều đó có nghĩa là lượng thông tin mà máy tính có thể xử lý cùng một lúc và tốt nhất là so sánh với người anh em kiến trúc nhỏ hơn của nó, 32-bit. Kiến trúc 64-bit có thể xử lý gấp đôi lượng thông tin cùng một lúc (64 bit so với 32).
Sau khi CPU có toán hạng cho lệnh, nó chuyển sang giai đoạn thực hiện, tại đó hoạt động được thực hiện trên đầu vào. Có thể là thêm các số, thực hiện thao tác logic trên các số hoặc chỉ truyền các số qua mà không sửa đổi chúng. Sau khi kết quả được tính toán, bộ nhớ có thể cần được truy cập để lưu trữ kết quả hoặc CPU có thể chỉ giữ giá trị trong một trong các thanh ghi bên trong của nó. Sau khi kết quả được lưu trữ, CPU sẽ cập nhật trạng thái của các phần tử khác nhau và chuyển sang lệnh tiếp theo.
Tất nhiên, mô tả này là một sự đơn giản hóa rất lớn, và hầu hết các bộ xử lý hiện đại sẽ chia nhỏ một vài giai đoạn này thành 20 hoặc nhiều giai đoạn nhỏ hơn để cải thiện hiệu quả. Điều đó có nghĩa là mặc dù bộ xử lý sẽ bắt đầu và hoàn thành một số lệnh trong mỗi chu kỳ, nhưng có thể mất 20 hoặc nhiều chu kỳ hơn để bất kỳ lệnh nào hoàn thành từ đầu đến cuối. Mô hình này thường được gọi là đường ống vì mất một thời gian để lấp đầy đường ống và để chất lỏng đi qua hoàn toàn, nhưng khi đầy, bạn sẽ nhận được đầu ra không đổi.

Ví dụ về đường ống 4 giai đoạn. Các hộp màu đại diện cho các hướng dẫn độc lập với nhau.Tín dụng hình ảnh: Wikipedia
Thực thi không theo thứ tự và kiến trúc siêu vô hướng
Toàn bộ chu kỳ mà một lệnh trải qua là một quá trình được biên đạo rất chặt chẽ, nhưng không phải tất cả các lệnh đều có thể hoàn thành cùng một lúc. Ví dụ, phép cộng rất nhanh, trong khi phép chia hoặc tải từ bộ nhớ có thể mất hàng trăm chu kỳ. Thay vì làm toàn bộ bộ xử lý dừng lại trong khi một lệnh chậm hoàn thành, hầu hết các bộ xử lý hiện đại thực hiện không theo thứ tự.
Điều đó có nghĩa là chúng sẽ xác định lệnh nào sẽ có lợi nhất để thực thi tại một thời điểm nhất định và đệm các lệnh khác chưa sẵn sàng. Nếu lệnh hiện tại chưa sẵn sàng, bộ xử lý có thể nhảy về phía trước trong mã để xem có lệnh nào khác đã sẵn sàng không.
Ngoài việc thực thi không theo thứ tự, bộ xử lý hiện đại điển hình sử dụng cái gọi là kiến trúc siêu vô hướng . Điều này có nghĩa là tại bất kỳ thời điểm nào, bộ xử lý thực thi nhiều lệnh cùng lúc ở mỗi giai đoạn của đường ống. Nó cũng có thể chờ hàng trăm lệnh khác để bắt đầu thực thi. Để thực thi nhiều lệnh cùng lúc, bộ xử lý sẽ có nhiều bản sao của mỗi giai đoạn đường ống bên trong.
Nếu bộ xử lý thấy rằng hai lệnh đã sẵn sàng để thực thi và không có sự phụ thuộc giữa chúng, thay vì chờ chúng hoàn thành riêng rẽ, nó sẽ thực thi cả hai lệnh cùng lúc. Một triển khai phổ biến của điều này được gọi là Đa luồng đồng thời (SMT), còn được gọi là Siêu phân luồng. Bộ xử lý Intel và AMD thường hỗ trợ SMT hai chiều, trong khi IBM đã phát triển các chip hỗ trợ SMT tám chiều.

Để thực hiện được quá trình thực hiện được biên đạo cẩn thận này, một bộ xử lý có nhiều thành phần bổ sung ngoài lõi cơ bản. Có hàng trăm mô-đun riêng lẻ trong một bộ xử lý, mỗi mô-đun phục vụ một mục đích cụ thể, nhưng chúng ta sẽ chỉ xem xét những điều cơ bản. Hai thành phần lớn nhất và có lợi nhất là bộ đệm và bộ dự đoán nhánh. Các cấu trúc bổ sung mà chúng ta sẽ không đề cập bao gồm những thứ như bộ đệm sắp xếp lại, bảng bí danh đăng ký và trạm đặt chỗ.
Bộ nhớ đệm: Tăng tốc truy cập bộ nhớ
Mục đích của bộ nhớ đệm thường gây nhầm lẫn vì chúng lưu trữ dữ liệu giống như RAM hoặc SSD . Tuy nhiên, điều khiến bộ nhớ đệm trở nên khác biệt là độ trễ truy cập và tốc độ của chúng. Mặc dù RAM cực kỳ nhanh, nhưng nó chậm hơn CPU gấp nhiều lần. RAM có thể mất hàng trăm chu kỳ để phản hồi dữ liệu và bộ xử lý sẽ không có việc gì để làm. Nếu dữ liệu không nằm trong RAM, có thể mất hàng chục nghìn chu kỳ để dữ liệu trên SSD được truy cập. Nếu không có bộ nhớ đệm, bộ xử lý của chúng ta sẽ phải dừng lại.
Bộ xử lý thường có ba cấp bộ nhớ đệm tạo thành thứ được gọi là hệ thống phân cấp bộ nhớ . Bộ nhớ đệm L1 là nhỏ nhất và nhanh nhất, L2 ở giữa và L3 là lớn nhất và chậm nhất trong các bộ nhớ đệm. Phía trên các bộ nhớ đệm trong hệ thống phân cấp là các thanh ghi nhỏ lưu trữ một giá trị dữ liệu duy nhất trong quá trình tính toán. Các thanh ghi này là thiết bị lưu trữ nhanh nhất trong hệ thống của bạn theo cấp số nhân. Khi trình biên dịch chuyển đổi một chương trình cấp cao thành ngôn ngữ lắp ráp, nó sẽ xác định cách tốt nhất để sử dụng các thanh ghi này.
Khi CPU yêu cầu dữ liệu từ bộ nhớ, trước tiên nó sẽ kiểm tra xem dữ liệu đó đã được lưu trữ trong bộ đệm L1 chưa. Nếu đã lưu trữ, dữ liệu có thể được truy cập nhanh chóng chỉ trong vài chu kỳ. Nếu không có, CPU sẽ kiểm tra bộ đệm L2 và sau đó tìm kiếm bộ đệm L3. Bộ đệm được triển khai theo cách mà chúng thường trong suốt đối với lõi. Lõi sẽ chỉ yêu cầu một số dữ liệu tại một địa chỉ bộ nhớ đã chỉ định và bất kỳ cấp độ nào trong hệ thống phân cấp có dữ liệu đó sẽ phản hồi. Khi chúng ta chuyển sang các giai đoạn tiếp theo trong hệ thống phân cấp bộ nhớ, kích thước và độ trễ thường tăng theo cấp số nhân. Cuối cùng, nếu CPU không thể tìm thấy dữ liệu mà nó đang tìm kiếm trong bất kỳ bộ đệm nào, thì khi đó nó mới chuyển đến bộ nhớ chính (RAM).

Trên một bộ xử lý thông thường, mỗi lõi sẽ có hai bộ đệm L1: một cho dữ liệu và một cho hướng dẫn. Bộ đệm L1 thường có tổng dung lượng khoảng 100 kilobyte và kích thước có thể thay đổi tùy thuộc vào chip và thế hệ. Ngoài ra, thường có một bộ đệm L2 cho mỗi lõi, mặc dù nó có thể được chia sẻ giữa hai lõi trong một số kiến trúc. Bộ đệm L2 thường có dung lượng vài trăm kilobyte. Cuối cùng, có một bộ đệm L3 duy nhất được chia sẻ giữa tất cả các lõi và có dung lượng vào khoảng hàng chục megabyte.
Khi bộ xử lý thực thi mã, các lệnh và giá trị dữ liệu mà nó sử dụng thường xuyên nhất sẽ được lưu vào bộ nhớ đệm. Điều này tăng tốc đáng kể quá trình thực thi vì bộ xử lý không phải liên tục chuyển đến bộ nhớ chính để lấy dữ liệu cần thiết. Chúng ta sẽ nói thêm về cách các hệ thống bộ nhớ này thực sự được triển khai trong phần thứ hai và thứ ba của loạt bài này.
Ngoài ra, cần lưu ý rằng trong khi hệ thống phân cấp bộ nhớ đệm ba cấp (L1, L2, L3) vẫn là tiêu chuẩn, các CPU hiện đại (như Ryzen 3D V-Cache của AMD ) đã bắt đầu kết hợp các lớp bộ nhớ đệm xếp chồng bổ sung có xu hướng tăng hiệu suất trong một số trường hợp nhất định.
Dự đoán nhánh và thực hiện suy đoán
Bên cạnh bộ nhớ đệm, một trong những khối xây dựng quan trọng khác của bộ xử lý hiện đại là bộ dự đoán nhánh chính xác . Các lệnh nhánh tương tự như các câu lệnh "nếu" đối với bộ xử lý. Một tập lệnh sẽ thực thi nếu điều kiện là đúng, và một tập lệnh khác sẽ thực thi nếu điều kiện là sai. Ví dụ, bạn có thể muốn so sánh hai số và nếu chúng bằng nhau, thực thi một hàm và nếu chúng khác nhau, thực thi một hàm khác. Các lệnh nhánh này cực kỳ phổ biến và có thể chiếm khoảng 20% tổng số lệnh trong một chương trình.
Trên bề mặt, các lệnh nhánh này có vẻ không phải là vấn đề, nhưng thực tế chúng có thể rất khó để bộ xử lý thực hiện đúng. Vì tại bất kỳ thời điểm nào, CPU có thể đang trong quá trình thực hiện mười hoặc hai mươi lệnh cùng một lúc, nên điều rất quan trọng là phải biết lệnh nào cần thực hiện. Có thể mất 5 chu kỳ để xác định xem lệnh hiện tại có phải là lệnh nhánh hay không và thêm 10 chu kỳ nữa để xác định xem điều kiện có đúng không. Trong thời gian đó, bộ xử lý có thể đã bắt đầu thực hiện hàng chục lệnh bổ sung mà thậm chí không biết liệu đó có phải là lệnh chính xác để thực hiện hay không.
Để giải quyết vấn đề này, tất cả các bộ xử lý hiệu suất cao hiện đại đều sử dụng một kỹ thuật gọi là suy đoán . Điều này có nghĩa là bộ xử lý theo dõi các lệnh rẽ nhánh và dự đoán liệu một nhánh sẽ được thực hiện hay không. Nếu dự đoán là đúng, bộ xử lý đã bắt đầu thực hiện các lệnh tiếp theo, dẫn đến tăng hiệu suất. Nếu dự đoán không đúng, bộ xử lý sẽ dừng thực hiện, loại bỏ tất cả các lệnh được thực hiện không đúng và khởi động lại từ điểm đúng.
Những bộ dự đoán nhánh này nằm trong số những dạng máy học sớm nhất , vì chúng thích ứng với hành vi nhánh theo thời gian. Nếu một bộ dự đoán đưa ra quá nhiều dự đoán không chính xác, nó sẽ điều chỉnh để cải thiện độ chính xác. Nhiều thập kỷ nghiên cứu về các kỹ thuật dự đoán nhánh đã dẫn đến độ chính xác vượt quá 90% trong các bộ xử lý hiện đại.
Trong khi suy đoán cải thiện đáng kể hiệu suất bằng cách cho phép bộ xử lý thực hiện các lệnh đã sẵn sàng thay vì chờ các lệnh bị đình trệ, thì nó cũng gây ra các lỗ hổng bảo mật. Cuộc tấn công Spectre khét tiếng hiện nay khai thác các lỗi thực thi suy đoán trong dự đoán nhánh. Kẻ tấn công có thể sử dụng mã được chế tạo đặc biệt để lừa bộ xử lý thực hiện các lệnh suy đoán làm rò rỉ dữ liệu bộ nhớ nhạy cảm. Do đó, một số khía cạnh của suy đoán đã phải được thiết kế lại để ngăn chặn rò rỉ dữ liệu, dẫn đến hiệu suất giảm nhẹ.
Kiến trúc của bộ xử lý hiện đại đã tiến bộ đáng kể trong vài thập kỷ qua. Những cải tiến và thiết kế thông minh đã mang lại hiệu suất cao hơn và sử dụng phần cứng cơ bản tốt hơn. Tuy nhiên, các nhà sản xuất CPU rất kín tiếng về các công nghệ cụ thể bên trong bộ xử lý của họ, vì vậy không thể biết chính xác những gì diễn ra bên trong. Mặc dù vậy, các nguyên tắc cơ bản về cách bộ xử lý hoạt động vẫn nhất quán trên tất cả các thiết kế. Intel có thể thêm công thức bí mật của họ để tăng tỷ lệ truy cập bộ nhớ đệm hoặc AMD có thể thêm một bộ dự đoán nhánh nâng cao, nhưng cả hai đều thực hiện cùng một nhiệm vụ.
Tổng quan này và phần đầu tiên của loạt bài này bao gồm hầu hết các kiến thức cơ bản về cách bộ xử lý hoạt động. Trong phần thứ hai, chúng ta sẽ thảo luận về cách các thành phần tạo nên CPU được thiết kế, bao gồm các cổng logic, xung nhịp, quản lý nguồn, sơ đồ mạch và nhiều hơn nữa.
THEO TECHSP
Comments