Script là một phần không thể thiếu trong công việc hằng ngày của một kỹ sư làm việc trong lĩnh vực vi mạch. Script xuất hiện trong mọi công đoạn thiết kế từ front-end đến back-end. Script là công cụ mạnh giúp rút ngắn thời gian thực hiện một công việc. Bài viết này trình bày một phương pháp và cách thức tham khảo để có thể xây dựng một định dạng script chuyên ngiệp. Ngôn ngữ được sử dụng trong bài viết này là PERL. Thông qua ví dụ minh họa, bạn có thể biết thêm một số thành phần Perl hay được dùng thường xuyên như đọc thư mục, đọc file, tạo file, ghi file, subrountine, kiểm tra mẫu dữ liệu trong một chuỗi ký tự, các biến hệ thống, ...
Lưu ý, phương pháp được trình bày trong bài viết này chỉ là một tham khảo giúp các bạn mới bắt đầu có thể hiểu, lựa chọn và xây dựng cách thức của riêng mình.
1) Script là gì?
Trước hết, chúng ta đi qua một số khái niệm cơ bản để hiểu về mục đích, ý nghĩa và cách sử dụng script.
Script là một chương trình tập hợp các lệnh (instruction hoặc command) sẽ được "dịch" và "thực thi" thông qua một phần mềm hay chương trình khác. Nội dung của script sẽ được "dịch" và "thực thi" từng dòng, nghĩa là được "thông dịch" (interpreted), chứ không phải biên dịch (compiled).
"Thông dịch" nghĩa là từng dòng code sẽ được một chương trình hoặc phần mềm khác "dịch" và "thực thi" tuần tự. Khác với "biên dịch", tất cả các code được chuyển từ ngôn ngữ lập trình thành một file thực thi, file .exe. File thực thi này là một chương trình độc lập được dùng để chạy các tác vụ mong muốn.
Ngôn ngữ dùng để tạo ra script gọi là ngôn ngữ script, ví dụ như Shell, Perl, Ruby, Python, JavaScript, .... Ngôn ngữ dùng để tạo ra chương trình độc lập gọi là ngôn ngữ lập trình, ví dụ như C/C++, Visual Basic, ...
Phần mềm (chương trình) dùng để dịch và thực thi script gọi là trình thông dịch (interpreter) như trình thông dịch C-shell, trình thông dịch Perl, ... Ví dụ, để thực thi một Perl script tên perl_ex.pl, chúng ta cần chỉ rõ trình thông dịch sẽ được sử dụng để dịch và thực thi script này bằng cách gọi trình thông dịch trên terminal:
perl perl_ex.pl
hoặc khai báo đường dẫn của trình thông dịch ở đầu file trong Perl script, ví dụ như:
#!/usr/bin/perl
Sau đó, gọi và thực thi trực tiếp Perl script trên terminal:
./perl_ex.pl
Trong cả hai cách trên thì trình thông dịch Perl sẽ được gọi để dịch và thực thi code trong file perl_ex.pl.
Phần mềm (chương trình) dùng để chuyển ngôn ngữ lập trình thành ngôn ngữ máy gọi là trình biên dịch (compiler), ví dụ như gcc/g++ là một trình biên dịch C/C++, ...
Script sinh ra để điều khiển, gọi và thực thi các thành phần có sẵn. Thành phần có sẵn ở đây chính là các chương trình (phần mềm) đã được cài đặt trên thiết bị. Script giúp kết nối các chương trình độc lập với nhau và thực thi chúng theo một trình tự, điều kiện nhất định do người tạo script lựa chọn. Từ đó, script giúp giảm bớt thời gian thực hiện các thao tác thủ công, tối ưu hóa công việc.
Ví dụ, bạn cần thay thế một cụm từ ABCD thành XYZ trong 100 file. Nếu làm thủ công, bạn cần thực hiện 100 lần các thao tác sau:
Hình 1: Sự khác nhau giữa quá trình thực thi một script file và program file |
Ví dụ, bạn cần thay thế một cụm từ ABCD thành XYZ trong 100 file. Nếu làm thủ công, bạn cần thực hiện 100 lần các thao tác sau:
- Mở file bằng một editor như Notepad
- Dùng chức năng thay thế của editor để chuyển ABCD thành XYZ hoặc tệ hơn là thay thế từng cụm từ trong file bằng cách đánh máy
- Lưu lại file
- Đóng file
Tất cả các thao tác trên có thể thay bằng 1 script. Bạn chỉ cần chạy script để nó tự động thực hiện các thao tác thay thế ABCD thành XYZ trên 100 file.
2) Thế nào là một định dạng script chuyên nghiệp?
Một script chuyên nghiệp đương nhiên phải thực hiện được các tác vụ (chức năng) được mong muốn một cách chính xác, nhanh nhất có thể và chiếm ít tài nguyên hệ thống. Điều này tùy vào khả năng và trình độ của mỗi người. Trong hiểu biết hạn hẹp của mình, tác giả không đề cập đến vấn đề này.
Vậy ngoài vấn đề trên, một script có cấu trúc chuyên nghiệp cần có những thông tin phụ kèm theo, càng chi tiết càng tốt, để giúp người dùng script có thể dễ dàng hiểu và sử dụng script. Đồng thời, ngoài kết quả chính, script còn có thể tạo ra các kết quả phụ giúp người dùng script hoặc dùng kết quả của script có thể dễ dàng trace* hoặc debug**.
*trace - tra cứu và tìm hiểu nguồn gốc của một vấn đề, hiện tượng.
**debug - Giải thích nguyên nhân sinh ra một vấn đề, hiện tượng.
Bạn có thể đã từng gặp một số vấn đề sau đây khi sử dụng một script do người khác viết:
3) Giới thiệu một cấu trúc Perl script chuyên nghiệp
Một script chuyên nghiệp đương nhiên phải thực hiện được các tác vụ (chức năng) được mong muốn một cách chính xác, nhanh nhất có thể và chiếm ít tài nguyên hệ thống. Điều này tùy vào khả năng và trình độ của mỗi người. Trong hiểu biết hạn hẹp của mình, tác giả không đề cập đến vấn đề này.
Vậy ngoài vấn đề trên, một script có cấu trúc chuyên nghiệp cần có những thông tin phụ kèm theo, càng chi tiết càng tốt, để giúp người dùng script có thể dễ dàng hiểu và sử dụng script. Đồng thời, ngoài kết quả chính, script còn có thể tạo ra các kết quả phụ giúp người dùng script hoặc dùng kết quả của script có thể dễ dàng trace* hoặc debug**.
*trace - tra cứu và tìm hiểu nguồn gốc của một vấn đề, hiện tượng.
**debug - Giải thích nguyên nhân sinh ra một vấn đề, hiện tượng.
Bạn có thể đã từng gặp một số vấn đề sau đây khi sử dụng một script do người khác viết:
- Không biết rõ script hỗ trợ các tùy chọn (option) nào
- Các thông điệp trong quá trình chạy như cảnh báo lỗi, hiển thị trạng thái, ... của script không lưu vào log file để có thể trace khi cần
- Xem một kết quả do script tạo nhưng không thể biết ai tạo? tạo lúc nào? thư mục chứa source ở đâu?
- Script thiếu những comment chỉ dẫn tối thiểu để có thể đọc hiểu và chỉnh sửa khi cần
- Không thể biết một kết quả ngõ ra được tạo từ script nào khi dùng một tool là tổ hợp của nhiều file script khác nhau.
3) Giới thiệu một cấu trúc Perl script chuyên nghiệp
Trong phần này tác giả trình bày về một định dạng (format), có thể hiểu là cấu trúc, của script mà theo tác giả là sẽ làm cho một script trở nên chuyên nghiệp hơn. Cấu trúc này gồm:
Header chỉ là các comment.
Phần 2: Khởi tạo log file
Biến $myLog chứa tên của log file sẽ được tạo ra là logGetPort.log. Hàm system() được sử dụng để gọi lệnh remove (rm) của hệ thống để xóa file logGetPort.log nếu nó đã được tạo trước đó. Bạn có thể viết như sau:
Phần 3: Tạo biến chứa tên của script
$0 là biến hệ thống chứa tên chương trình đang chạy. Khi script này được thực thi thì $0 chứa tên của chính script này. Tuy nhiên giá trị đó sẽ là "./getPort.pl" nên dòng lệnh thứ 2 sẽ remove "./" để lấy đúng tên script. Chú ý, toán tử "=~" là toán tử kiểm tra các mẫu ký tự (pattern-matching operator). Ở đây, $myScript sẽ được kiểm tra mẫu ký tự "./" và thay thế bằng một ký tự trống, nghìa là xóa "./" bằng toán tử thay thế (subsituation operator).
Phần 4: Kiểm tra đối số của script
@ARGV là biến mảng của hệ thống chứa các đối số gán cho một chương trình thực thi trên terminal (command line). Ví dụ:
Đoạn code if sẽ kiểm tra số lượng đối số có bằng 0. Nếu bằng 0 thì nó sẽ gọi lại chính script này đê thực thi với tùy chọn "-help" với mục đích in ra thông tin các option của script cho người dùng lựa chọn và thoát script với lệnh exit.
Phần 5: Biến chứa thông tin chung
- Header của script: Chứa những thông tin cơ bản liên quan đến script như chức năng chính của script, tác giả, lịch sử cập nhật, ... Đây là các thông tin tổng quan ban đầu giúp người dùng nhanh chóng hiểu chức năng chính của script và các lưu ý quan trọng nếu có.
- Khởi tạo một log file: Tạo một log file để ghi lại quá trình hoạt động của script và những thông điệp hỗ trợ người sử dụng có thể trace hoặc debug
- Tạo biến chứa tên của script hiện tại với mục đích:
- Gọi lại chính script này để thực thi nếu cần
- In thông điệp hỗ trợ việc trace và debug
- Kiểm tra đối số của script như kiểm tra số lượng đối số và tính hợp lệ khác nếu cần. Ở bước này, nếu đối số của script không thỏa mãn một vài tiêu chí cơ bản thì script sẽ ngừng thực thi và thông báo đến người dùng.
- Tạo các biến chứa thông tin chung như tên người dùng script, thời điểm chạy script, đường dẫn thư mục chạy script, ... với mục đích hỗ trợ việc trace và debug
- Tạo header chứa các thông tin sẽ in trên terminal trong quá trình chạy hoặc in trong log file hoặc in trong file kết quả để hỗ trợ việc trace và debug
- Khai báo tất cả các biến toàn cục dùng trong suốt quá trình chạy script. Các biến cục bộ hoặc biến tạm chỉ dùng trong một đoạn xử lý cụ thẻ của script thì chỉ nên khai báo trong đoạn xử lý đó. Điều này giúp giảm tài nguyên phần cứng khi chạy script.
- So sánh các đối số để gán giá trị phù hợp cho các biến toàn cục khai báo ở bước 7. Giá trị các biến này sẽ điều khiển việc thực thi chức năng chính của script ở các bước sau.
- Code thực thi các chức năng chính
- Đóng log file được khởi tạo ở bước 2. sSau khi khởi tạo ở bước 2, log file có thể được ghi những thông tin do người tạo script quyết định. Đến bước này, sau khi script đã thực thi xong toàn bộ các chức năng chính. Log file phải được đóng lại. Chú ý, việc đóng log file luôn nằm sau bước 9 để các bước từ 3 đến 9 có thể ghi vào log file khi cần.
- Code của tất cả các chương trình con (subrountine) sử dụng ở các bước trên. Các subrountine là các chương trình con thực thi một chức năng nào đó, thường lặp lại nhiều lần, trong script và thường đặt cuối các script. Các phần code khác của script sẽ gọi subroutine để yêu cầu nó thực thi tại thời điểm thích hợp với đối số thích hợp nếu có.
Trong đó, đối số của script là các giá trị tùy chọn (option) được script hỗ trợ. Các giá trị này sẽ được khai báo trên dòng lệnh khi chạy script. Ví dụ như:
Để minh họa các thành phần cấu trúc của script, chúng ta hãy thực hiện một ví dụ "Viết một script đọc các file RTL code để lấy danh sách các port (input, output và inout). In danh sách này ra một file và sắp xếp theo thứ tự input->output->inout.". Script này sẽ có tên là getPort.pl với 11 thành phần đã liệt kê trên đây được thể hiện như sau:
Phần 1: Header của script
./hello_perl.pl -f inFile.txt
Trong ví dụ trên, script hello_perl.pl nhận 2 đối số là "-f" và "inFile.txt".Hình 2: Cấu trúc một script Perl "chuyên nghiệp" |
Phần 1: Header của script
#(1) Header of Script
#----------------------------------
#Author : Nguyen Hung Quan
#Website: http://nguyenquanicd.blogspot.com/
#Function: List all input, output and inout of a module
#Note: Do NOT support RTL file with comment block /* */
#Reversion and History:
# v0.0 - Create firstly
#----------------------------------
Phần 2: Khởi tạo log file
my $myLog = "logGetPort.log";
system "/usr/bin/rm -f logGetPort.log";
open (LOGFILE, ">$myLog") or die because $!;
Biến $myLog chứa tên của log file sẽ được tạo ra là logGetPort.log. Hàm system() được sử dụng để gọi lệnh remove (rm) của hệ thống để xóa file logGetPort.log nếu nó đã được tạo trước đó. Bạn có thể viết như sau:
system "rm -f logGetPort.log";
Không cần chỉ rõ đường dẫn đến file thực thi (.exe) của lệnh này nếu đường dẫn của nó đã có trong biến môi trường $PATH của hệ điều hành. Khi đó, bạn có thể thực thi lệnh trên terminal:
rm -f logGetPort.log
Bạn có thể kiểm tra giá trị biến $PATH bằng lệnh:
echo $PATH
Logic được khởi tạo bằng lệnh open, trong đó:- LOGFILE là từ khóa do người dùng đặt sẽ lưu handle của file được tạo ra. Một file sẽ được ghi và đọc thông qua handle này.
- $myLog là biến chứa tên file sẽ tạo
- Dấu ">" chỉ ra đây là file sẽ được tạo mới. Nếu không có ">" thì hàm open sẽ hiểu là "mở" một file đã tồn tại.
Phần 3: Tạo biến chứa tên của script
my $myScript = $0;
$myScript =~ s/\.\///;
$0 là biến hệ thống chứa tên chương trình đang chạy. Khi script này được thực thi thì $0 chứa tên của chính script này. Tuy nhiên giá trị đó sẽ là "./getPort.pl" nên dòng lệnh thứ 2 sẽ remove "./" để lấy đúng tên script. Chú ý, toán tử "=~" là toán tử kiểm tra các mẫu ký tự (pattern-matching operator). Ở đây, $myScript sẽ được kiểm tra mẫu ký tự "./" và thay thế bằng một ký tự trống, nghìa là xóa "./" bằng toán tử thay thế (subsituation operator).
s/<mẫu bị thay thế>/<mẫu thay thế>/
Phần 4: Kiểm tra đối số của script
my $argNum = @ARGV;
if ($argNum == 0) {
printLog (LOGFILE, "[ERROR] Missing options
- please fill your options\n");
system "./$myScript -help";
exit;
}
@ARGV là biến mảng của hệ thống chứa các đối số gán cho một chương trình thực thi trên terminal (command line). Ví dụ:
/hello_perl.pl -f inFile.txt
@ARGV sẽ chứa 2 đối số là "-f" và "inFile.txt". Gán một mảng đến một biến vô hướng như $argNum thì biến vô hướng $argNum sẽ chứa số lượng đối số của mảng. Như ví dụ này, $argNum sẽ bằng 2.Đoạn code if sẽ kiểm tra số lượng đối số có bằng 0. Nếu bằng 0 thì nó sẽ gọi lại chính script này đê thực thi với tùy chọn "-help" với mục đích in ra thông tin các option của script cho người dùng lựa chọn và thoát script với lệnh exit.
Phần 5: Biến chứa thông tin chung
#Account name
my $wName = getlogin();
#Generation time
my $wTime = localtime();
#Working directory
my $wDir = $ENV{PWD};
Như các comment trong code:
- $wName sẽ chứa tên người chạy script (user ID) bằng cách dùng function getlogin().
- $wTime sẽ chứa thời điểm chạy script bằng cách dùng function localtime()
- $wDir sẽ chứa đường dẫn thư mục mà script đang được thực thi lấy từ biến môi trường %ENV
Phần 6: Tạo header cho output
my $headerFile;
$headerFile .= "#----------------------------------\n";
$headerFile .= "#Author : $wName\n";
$headerFile .= "#Date : $wTime\n";
$headerFile .= "#Working directory : $wDir\n";
$headerFile .= "#Number of arguments : $argNum\n";
$headerFile .= "#Submitted command : $myScript @ARGV\n";
$headerFile .= "#----------------------------------\n";
printLog (LOGFILE, $headerFile);
Biến $headerFile sẽ lưu các thông tin như người dùng script, thời gian sử dụng, thư mục làm việc, đối số và lệnh đã được sử dụng. Chú ý, ".=" là toán tử nối chuỗi và gán. Nó nối chuỗi bên phải dấu ".=" vào chuỗi đang chứa trong $headerFile. Sau đó, gán chuỗi đã nối vào $headerFile.
$headerFile sẽ được ghi vào log file bằng một subrountine tên printLog(). Subrountine này được định nghĩa trong phần 11.
Phần 7: Biến toàn cục
my $rmComment = 0;
my $mode = "file";
my $myRtl;
my $myDir;
my $outLine;
my $outFile = "outputFile.txt";
$rmComment là biến điều khiển việc có xóa comment trong dòng code khai báo port đi hay không, bằng 1 là "có xóa".
$mode là biến chỉ ra chế độ mà script đang thực thi là cho 1 file code duy nhất hay cho một thư mục chứa nhiều file code. Nếu script thực thi cho 1 thư mục, biến này sẽ được gán lại thành "dir".
$myRtl chứa tên file RTL code là đầu vào của script
$myDir chứa tên thư mục RTL code, gồm nhiều file RTL code, là đầu vào của script
$outLine là biến chứa thông tin sẽ được in vào file kết quả
$outFile là biến chứa tên file kết quả sẽ được tạo ra. File này sẽ chứa nội dụng lưu trong biến $outLine.
Phần 8: Quét và kiểm tra đối số
while ($argNum != 0) {
my $arg = shift(@ARGV); #Get an argument
switch($arg) {
#Get RTL file
case "-f" {
$myRtl = shift(@ARGV);
}
#Get RTL directory
case "-d" {
$myDir = shift(@ARGV);
$mode = "dir";
}
#Set option "remove comment"
case "-rc" {
$rmComment = 1;
}
case "-help" {
printLog (LOGFILE, "#----------------------------------\n");
printLog (LOGFILE, "Format: $myScript
< option 0="" > < value 0="" > ... <
option n="" > < value n="" >\n");
printLog (LOGFILE, " Option:\n");
printLog (LOGFILE, " -f : Declare an RTL file (.sv .v).\n
Example \"-f test.v\"\n");
printLog (LOGFILE, " -d : Declare an RTL directory
which contains RTL files (only .sv or .v).\n
Example \"-d working/rtlIn\"\n");
printLog (LOGFILE, " -rc : Remove comments.
Default is \"no-remove\".\n
Example \"-rc\"\n");
printLog (LOGFILE, " -help : Show all options.\n");
printLog (LOGFILE, "#----------------------------------\n");
exit;
}
else {
printLog (LOGFILE, "[ERROR]Do NOT support the option: $arg\n");
system "./$myScript -help";
exit;
}
}
$argNum = @ARGV; #Update number of arguments
}
switch được sử dụng để kiểm tra các giá trị tùy chọn (đối số) được cấp cho script khi chạy. Tùy vào mỗi case mà các biến tương ứng sẽ được gán phù hợp. Script sẽ ngừng thực thi tiếp (exit) nếu đối số không thuộc các tùy chọn đã cho (nhánh else) hoặc tùy chọn có chứa "-help".
getPort.pl hỗ trợ các tùy chọn sau:
Hình 3: Flowchart của đoạn code "quét và kiểm tra các đối số" |
- -f : Khai báo tên file RTL
- -d : Khai báo thư mục chứa nhiều file RTL (không dùng chung với -f)
- -rc : Xóa các comment (nếu có) ở các dòng code khai báo port
- -help: In đầy đủ các option của script
Để sử dụng được switch, bạn cần cài đặt gói hỗ trợ sau:
Sau đó khai báo "use Switch;" ở đầu script và sau khai báo phần mềm Perl. Cách cài đặt một package Perl, các bạn có thể tham khảo ở bài viết này.
switch được đặt trong một vòng lặp while. Vòng lặp này được thực thi nếu số lượng đối số chứa trong @ARGV khác 0. Với mỗi lần thực thi, đầu tiên, mảng @ARGV sẽ được dịch để lấy đối số gán cho biến $arg. tùy vào giá trị của $arg mà giá trị tiếp theo của mảng @ARGV sẽ được lấy tiếp bằng function shift và gán vào biến tương ứng. Ví dụ như, nếu $arg bằng "-f" thì giá trị kế tiếp được shift từ @ARGV là tên file RTL code sẽ được gán cho biến $myRtl.
Sau mỗi lần kiểm tra đối số, số lượng giá trị của mảng @ARGV sẽ bị giảm dần và được gán lại cho biến $argNum sau mỗi lần lặp. Khi $argNum=0, nghĩa là tất cả các đối số đã được kiểm tra và sử dụng, vòng lặp while sẽ bị thoát.
Sau mỗi lần kiểm tra đối số, số lượng giá trị của mảng @ARGV sẽ bị giảm dần và được gán lại cho biến $argNum sau mỗi lần lặp. Khi $argNum=0, nghĩa là tất cả các đối số đã được kiểm tra và sử dụng, vòng lặp while sẽ bị thoát.
Phần 9: Chức năng chính của script
if ($mode eq "dir") {
printLog(LOGFILE, "--- START reading RTL directory: $myDir\n");
#Get all file names and store to an array
opendir (DIR, $myDir) or die because $!;
my @fileList = readdir(DIR);
closedir (DIR);
#Scan all RTL files
my $fileCount = 0;
foreach $myRtl (@fileList) {
if (($myRtl =~ /.sv$/) || ($myRtl =~ /.v$/)) {
$fileCount++;
#Return a unused signal array
printLog(LOGFILE, "+ RTL file $fileCount : $myRtl\n");
$myRtl = "$myDir/$myRtl";
$lineOut .= "$fileCount) $myRtl\n";
$lineOut .= getPort($myRtl, $rmComment);
$lineOut .= "\n";
}
printLog (LOGFILE, "\n");
}
printLog(LOGFILE, "--- END reading RTL directory: $myDir\n\n");
}
else {
printLog(LOGFILE, "--- START reading RTL file: $myRtl\n");
$lineOut .= " $myRtl\n";
$lineOut = getPort($myRtl, $rmComment);
printLog(LOGFILE, "--- END reading RTL file: $myRtl\n\n");
}
open (OFILE, " > $outFile") or die because $!;
print OFILE $lineOut;
close(OFILE);
Phần chức năng chính của chương trình gồm 2 đoạn code:
Phần code này có sử dụng một subrountine là getPort(). Nó sẽ dùng 2 đối số đầu vào là một đường dẫn file RTL $myRtl và biến xác định xem comment có được xóa hay không $rmComment.
Các bạn hãy so sánh flowchart trên và code để hiểu rõ hơn.
- Đoạn if/else đọc thư mục chứa RTL hoặc một file RTL để lấy danh sách port lưu vào biến $lineOut
- Đoạn in biến $lineOut vào file outputFile.txt thông quan handle OFILE.
Phần code này có sử dụng một subrountine là getPort(). Nó sẽ dùng 2 đối số đầu vào là một đường dẫn file RTL $myRtl và biến xác định xem comment có được xóa hay không $rmComment.
Hình 4: Flowchart phần chức năng chính của script |
Phần 10: Đóng log file
close (LOGFILE);
Sau khi quá trình thực thi script hoàn tất, log file đã tạo ở phần 2 và được ghi nội dung trong các phần từ 3 đến 9 thông qua subrountine printLog() sẽ được đóng lại.
Phần 11: Định nghĩa Subrountine
Phần 11: Định nghĩa Subrountine
#
#Print to a log file
#
sub printLog {
my $fileHandle = shift;
my $msg = shift;
#
print "$msg";
print $fileHandle $msg;
} #printLog
#
#Read a RTL file and return a unused signal array
#
sub getPort {
my $fileIn = shift;
my $opIn = shift;
my $portIn;
my $portOut;
my $portInout;
my $portList;
#
open (RTL, $fileIn) or die because $!;
foreach my $line (< RTL >) {
chomp($line);
#Pre-operate
#Remove START spaces
$line =~ s/^\s+//;
#Replace tab or many spaces to one space
$line =~ s/\s+/ /g;
#Remove END space
$line =~ s/\s+$//;
#Post-operate
#Do NOT care the comment line
if ($line !~ /^\/\//) {
#Remove comment at END of a line
if (($opIn == 1) && ($line =~ /\/\//)) {
my @wordArray = split(/\/\//, $line);
$line = $wordArray[0];
}
#
if ($line =~ /^input /) {
$portIn .= "$line\n";
}
elsif ($line =~ /^output /) {
$portOut .= "$line\n";
}
elsif ($line =~ /^inout /) {
$portInout .= "$line\n";
}
}
}
close (RTL);
#
if (defined($portIn)) {
$portList = "$portIn";
}
if (defined($portOut)) {
$portList .= "$portOut";
}
if (defined($portInout)) {
$portList .= "$portInout";
}
#
$portList; #This is the returned value
} #getPort
Subrountine printLog sẽ in thông điệp mà bạn muốn ra terminal và vào log file.
Subrountine getPort sẽ đọc một RTL file và trích xuất danh sách khai báo port của module. Sau khi sắp xếp chúng theo thứ tự input->output->inout, danh sách khai báo này được trả về cho chương trình cha thông qua $portList..
4) Một số kết quả chạy trên cygwin terminal
4.1) Kết quả chạy lệnh "./getPort.pl -help"
4.2) Kết quả chạy lệnh "./getPort.pl -d rtl"
Hiển thị trên terminal và trong log file:
Hiển thị trong output file outputFile.txt là danh sách port của tất cả các file RTL trong thư mục rtl là uart_apb_if.v, uart_receiver.v, uart_top.v và uart_transmitter.v.
Nhận xét, scritp này hỗ trợ các đặc điểm sau giúp việc sử dụng script, trace và debug dễ dàng hơn:
Hình 5: Flowchart của subrountine printLog() |
Hình 6: Flowchart rút gọn của getPort() |
4.1) Kết quả chạy lệnh "./getPort.pl -help"
#----------------------------------
#Author : 8560w
#Date : Mon Sep 2 12:02:14 2019
#Working directory : /cygdrive/d/20.Project/7.Perl
#Number of arguments : 1
#Submitted command : getPort.pl -help
#----------------------------------
#----------------------------------
Format: getPort.pl < option 0 > < value 0 >
... < option N > < value N >
Option:
-f : Declare an RTL file (only .sv or .v).
Example "-f test.v"
-d : Declare an RTL directory which contains RTL files
(only .sv or .v).
Example "-d working/rtlIn"
-rc : Remove comments. Default is "no-remove".
Example "-rc"
-help : Show all options.
#----------------------------------
4.2) Kết quả chạy lệnh "./getPort.pl -d rtl"
Hiển thị trên terminal và trong log file:
#----------------------------------
#Author : 8560w
#Date : Mon Sep 2 12:03:46 2019
#Working directory : /cygdrive/d/20.Project/7.Perl
#Number of arguments : 2
#Submitted command : getPort.pl -d rtl
#----------------------------------
--- START reading RTL directory: rtl
+ RTL file 1 : uart_apb_if.v
+ RTL file 2 : uart_receiver.v
+ RTL file 3 : uart_top.v
+ RTL file 4 : uart_transmitter.v
--- END reading RTL directory: rtl
Hiển thị trong output file outputFile.txt là danh sách port của tất cả các file RTL trong thư mục rtl là uart_apb_if.v, uart_receiver.v, uart_top.v và uart_transmitter.v.
Nhận xét, scritp này hỗ trợ các đặc điểm sau giúp việc sử dụng script, trace và debug dễ dàng hơn:
- Kiểm tra đối số, cảnh báo người dùng script nếu có sai sót
- Hỗ trợ tùy chọn "-help" cho phép người dùng tra cứu tùy chọn của script
- Tạo log file
- In ra thông tin tên người dùng, thời gian, vị trí và command mà người dùng dử dụng
- Đánh dấu và chú thích chức năng từng đoạn code giúp người dùng script có thể đọc hiểu và chỉnh sửa nếu cần
Dữ liệu có thể tải:
Lịch sử cập nhật:
1) 2019.Sep.02 - Tạo lần đầu
Bai viet hay xin cam on tac gia.
Trả lờiXóa