Đây là 1 bài viết hay, đáng lẽ mình chỉ nên đưa đường link. Nhưng do
người viết là dân lập trình nên có nhiều đoạn không liên quan đến DT-VT
--> cắt bớt ra để mọi người đọc cho dễ:
Sau một thời gian “trằn trọc băn khoăn, tối ngủ ngon lành”, quyết
định tổng kết những gì ghi nhận được về FPGA để mai mốt lại ngâm cứu
tiếp.
FPGA nói ngắn gọn là “lập trình phần cứng” hay “lập trình chip”. Nó
cũng là “lập trình”. Hãy xem xét lập trình ở các cấp độ khác nhau. Ở cấp
cao nhất của lập trình, cấp thông dịch, bao gồm các ngôn ngữ như PHP,
Python, Ruby… Các chương trình loại này được một chương trình khác chạy
và thực hiện từng lệnh một. Thấp hơn một tí là các ngôn ngữ có Virtual
Machine (VM) và thực hiện mã giả và Just-In-Time compilation như Java
hay .NET. Ở mức này các chương trình sẽ được chuyển từng phần sang mã
máy. Đến lượt VM sẽ xử lý các mã giả.
Sau mã giả dĩ nhiên là đến mã thật. Những chương trình thuộc thế hệ
cũ như C sẽ được biên dịch trực tiếp ra mã máy, loại lệnh mà CPU có thể
đọc hiểu trực tiếp. Đối với các chương trình dùng VM, bản thân VM cũng
là một chương trình mà sẽ chuyển mã giả của VM đó sang một tập mã máy và
thực thi. Đối với các chương trình thông dịch thì đoạn mã tổng cộng
dùng để thực thi to hơn nhiều, bao gồm phân tích cú pháp và gọi các hàm
tương ứng với từng lệnh. Với cùng một đoạn lệnh thực hiện cùng một tính
năng, đoạn viết bằng C là gọn gàn nhất, được chuyển trực tiếp thành
những mã lệnh CPU liên quan trực tiếp đến tính năng cần thực hiện. Với
các chương trình dùng VM, đoạn mã lệnh CPU to hơn do là tổ hợp của mã
lệnh cho CPU của từng mã giả VM. Với chương trình thông dịch, mã liên
quan còn to hơn nữa do dính dáng đến phần phân tích cú pháp.
Như ta thấy, càng đi xuống khối lượng “mã” dùng để thực hiện một
tính năng giảm dần, cô đọng dần, tập trung vào cốt lõi của tính năng cần
thực hiện. Nhưng! Để ý là mã giả cũng là một tập mã, cũng được phân
tích thành một tập các mã thiệt dành cho CPU. CPU cũng có một tập mã,
nên trên nguyên tắc các mã lệnh CPU cũng có thể được tách thành một tập
các “mã điện tử”!
Không biết có ai đã từng phân vân cách hoạt động của một CPU như thế
nào chưa. CPU tuy phức tạp nhưng tất cả các thao tác của CPU đều có thể
quy về các phép toán logic và số học. Mỗi khi thực hiện một lệnh, CPU
sẽ nhảy qua lệnh kế tiếp. Phép nhảy này, đối với kiến trúc x86, đơn giản
là cộng thêm vào thanh ghi IP độ dài của mã lệnh vừa thực hiện (Với ARM
còn dễ hơn, cứ cộng 4 vào r15 vì kích thước mã lệnh trong kiến trúc
RISC là cố định). Phép nhảy đến một địa chỉ. Phép nhảy có điều kiện có
thể quy ra là phép cộng với tích của kết quả biểu thức có điều kiện (trả
về 1 hoặc 0) với khoảng cách cần nhảy. Nếu điều kiện là đúng, trả về 1,
thì IP được cộng thêm vào, nói cách khác là nhảy. Nếu điều kiện sai,
trả về 0, thì IP vẫn giữ nguyên. Như vậy có thể nói hầu hết các phép
toán của CPU đều có thể biến thành AND OR NOT XOR với cộng trừ nhân
chia. Trong khi cộng trừ nhân chia cũng có thể biến thành AND OR NOT
XOR!
Như vậy có thể thấy ta có thể chuyển các một chuỗi mã lệnh cho CPU
về một mớ cổng logic nối với nhau (giả bộ thế). Khi đã chuyển về như
thế, ta có thể tìm ra những chỗ thừa thãi và loại bỏ bớt các cổng logic
không cần thiết sao cho kết quả cuối cùng vẫn giữ nguyên. Làm như thế
nghĩa là đã loại bỏ CPU ra khỏi quá trình thực hiện chương trình. Chương
trình ban đầu giờ đây biến thành một tập các cổng logic (tạm thời quên
đi việc truy cập bộ nhớ và các thiết bị phần cứng khác). Thậm chí ngay
cả không tối ưu các cổng logic, ta vẫn giảm được thời gian xử lý do loại
phần phân tích lệnh và nhảy lệnh của CPU (cũng giống như công việc của
trình thông dịch). FSM (lát nữa nói) của một chương trình cụ thể sẽ đơn
giản hơn nhiều so với một CPU tổng quát.
Như mô tả, cuối cùng thì chương trình được “lập trình” không còn sử
dụng CPU nữa. Và kết quả chương trình không phải là một tập mã máy mà là
một sơ đồ các cổng logic. Vậy cần có một ngôn ngữ để “vẽ” mấy cái sơ đồ
mạch đó, bằng chữ (rõ ràng vẽ hình thì rất khó kiểm tra giám sát, mà
máy tính lại ngu, không giỏi đọc hình bằng đọc chữ). Các ngôn ngữ này
được gọi là Hardware Description Language, phổ biến là VHDL và Verilog.
Nếu coi mấy cái sơ đồ logic đó là “mã máy” theo cách nhìn của dân làm
phần mềm thì rõ ràng chẳng ai điên đi viết trực tiếp trên mấy cái đó cả
(tệ tương đương viết hợp ngữ). Do đó HDL sẽ được dùng để mô tả tổng quát
hơn và sẽ có một cái “trình biên dịch” để biến cái mô tả đó thành “mã
máy” (dân chip gọi là netlist thì phải).
Như vậy, ta có thể nhìn thấy việc “lập trình phần cứng” đơn giản chỉ
là một bước tiếp theo của dây chuyền “thông dịch, mã giả, máy ảo, JIT,
biên dịch, mã máy”. Mặc dù kỳ dị nhưng vẫn chấp nhận được, từ quan điểm
lập trình viên. Quay lại FPGA. Đơn vị cơ bản của FPGA là macrocell tuy
nhiên vẫn không rõ macrocell là gì. Nó có vẻ phức tạp hơn cổng logic.
Macrocell đối với FPGA cũng giống như mã máy CPU đối với lập trình phần
mềm. Đó là nền tảng lập trình. FPGA có một lượng macrocell khá là lớn
nên có thể vô tư thiết kế. Khi “lập trình FPGA”, ta nối các macrocell
này lại với nhau, như thể ta lấy các mã lệnh CPU cho vào danh sách theo
một thứ tự nhất định vậy. Mặc dù nối macrocell thì nhiều chân hơn, nối
tùm lum hơn là cái danh sách mã lệnh một chiều thẳng đuột của lập trình
phần mềm. Việc ghi “chương trình” vào FPGA được thực hiện thông qua giao
tiếp JTAG. Nói đơn giản, JTAG cho phép ta trực tiếp đưa tín hiệu vào
các chân của một con chip cụ thể trên board mà không cần quan tâm đến
mấy thứ còn lại trên board, như thể ta tháo con chip đó ra và mần thịt
riêng mình nó.
Thao tác ở mức phần cứng đòi hỏi nhiều thứ hơn là chỉ “sơ đồ các
cổng logic”. Một trong những thứ đó là điều khiển chức năng của các
chân: liệu chân này là chân vào, chân ra, hay chân gãy (điện trở cao,
cấm cả vào lẫn ra)... Làm việc với cổng logic cũng có nhiều cái thú vị
hơn lập trình cấp cao hơn. Ví dụ như mạch flip-flop, xem như một bit nhớ
đơn giản. Ngoài ra còn có một khái niệm khác có ở cấp lập trình cao hơn
nhưng không tồn tại ở cấp FPGA: việc chạy tuần tự các lệnh. Với mạch
điện thì chỉ cần cho điện ở cổng vào là toàn mạch chạy hết, không có cái
gì tuần tự hết. Tuần tự được là nhờ hai thứ: flip-flop để ghi nhớ trạng
thái và chân xung nhịp đầu vào để hoạt động theo từng xung một. Ta có
thể viết mô tả HDL để một mớ cổng logic (hay macrocell gì gì đó) hoạt
động khi có xung đồng hồ (một cổng AND là hết) và lưu kết quả vào
flip-flop. Ta lại viết một mô tả khác cho một mớ cổng logic hoạt động
khi có xung đồng hồ và kết quả của cổng flip-flop vừa lưu là 1 (ví dụ
thế). Ở đây một tập các flip-flop sẽ hoạt động như bộ nhớ lưu lại trạng
thái cuối cùng của chip. Nhiệm vụ của ta là vẽ ra một máy trạng thái hữu
hạn (Finite state machine) trên giấy mô tả các bước thực hiện và sau đó
chuyển sang vẽ mạch. À dĩ nhiên là không đến nỗi phải vẽ mạch. Verilog
khá dễ viết và dễ hiểu nên cũng không đến nỗi. Verilog cũng hỗ trợ luôn
các biểu thức số học và biểu thức logic phức tạp nên càng khoẻ. Ai quan
tâm thì đọc tiếp trang 53 cuốn “The Verilog Hardware Description
Language, fifth edition” của Thomas và Moorby (ai có cuốn nào hay hơn,
chỉ dùm cái).
Với việc có thể biến FSM thành mạch một cách dễ dàng, có thể nói ta
muốn làm gì cũng được. Chương trình lớn thế nào cũng biến thành mạch
được (“A Turing machine is a finite-state machine associated with an
external storage or memory medium.”—Minsky (1967), p. 117) Chạy được hay
không là chuyện khác! Bởi vì...
* Bởi vì phần cứng thì mắc hơn phần mềm, không có tiền là không có thử cái gì hết
* Bởi vì không có nhiều công cụ hỗ trợ trên Linux. Chỉ có thể
kiếm ra icarus verilog, gtkwave và gplcver. Cả icarus verilog vẫn cần bộ
Xilinx Foundation. Còn nguyên bộ Xilinx ISE gì gì đó thì giá trên trời.
Lại ca bài ca tiền là tiền nhiều khi không mà có, tiền là tiền nhiều
khi có mà .. hổng đủ
* Bởi vì phần cứng có tác động của các yếu tố “cứng” như độ trễ
của các cỗng logic, độ lệch của xung nhịp, độ dốc của xung… mà mô phỏng
phần mềm thì chưa chắc đúng. Còn dùng thiết bị debug chuyên dụng thì lại
ca bài ca “tiền là tiền nhiều khi…”
* Bởi vì lười quá nên biết làm sao. Thôi kệ nó.
Túm lại FPGA là thế. FPGA không phải là thần thánh gì. FPGA cũng là
lập trình thôi (dù đỏi hỏi một chút hiểu biết về điện tử). FPGA giúp ta
đạt được tốc độ nhanh hơn vì loại cả thằng CPU to vật vã ra. FPGA giúp
ta trở nên nhỏ hơn (một con chip chứa cả bầu trời!).Nhưng FPGA vẫn chưa
là vô địch. Vô địch là ASIC. Với ASIC, FPGA giúp ta tạo ra sản phẩm rẻ
hơn (với điều kiện chế tạo số lượng lớn). Và cho dù có thể dùng FPGA để
viết cả CPU, đừng mơ đến việc viết một con CPU (chấp làm ASIC luôn) mà
có thể qua mặt Intel :)
Cuối cùng cũng phải dành một dòng để nhắc đến một dự án đầy tham
vọng có sử dụng FPGA: Open Graphics Project. Hi vọng dự án thành công
tốt đẹp.
source: http://dev.gentoo.org/~pclouds/blog/arc ... index.html
thank and sorry pclouds.
No comments:
Post a Comment