forked from rouge-ruby/rouge
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request rouge-ruby#317 from Razer6/verilog-lexer
Implement Verilog and SystemVerilog lexer
- Loading branch information
Showing
4 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Verilog Lexer | ||
*/ | ||
module Foo( | ||
input logic Clk_CI, | ||
input logic Rst_RBI, | ||
input logic A, | ||
input logic B, | ||
output logic C | ||
); | ||
logic C_DN, C_DP; | ||
|
||
assign C = C_DP; | ||
|
||
always_comb begin : proc_next_state | ||
C_DN = A + B; | ||
end | ||
|
||
// Clocked process | ||
always_ff @(posedge Clk_CI, negedge Rst_RBI) begin | ||
if(~Rst_RBI) begin | ||
C_DP <= 1'b0; | ||
end else begin | ||
C_DP <= C_DN; | ||
end | ||
end | ||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# -*- coding: utf-8 -*- # | ||
|
||
module Rouge | ||
module Lexers | ||
class Verilog < RegexLexer | ||
title "Verilog and System Verilog" | ||
desc "The System Verilog hardware description language" | ||
tag 'verilog' | ||
filenames '*.v', '*.sv', '*.svh' | ||
mimetypes 'text/x-verilog', 'text/x-systemverilog' | ||
|
||
# optional comment or whitespace | ||
ws = %r((?:\s|//.*?\n|/[*].*?[*]/)+) | ||
id = /[a-zA-Z_][a-zA-Z0-9_]*/ | ||
|
||
def self.keywords | ||
@keywords ||= Set.new %w( | ||
alias always always_comb always_ff always_latch assert assert_strobe | ||
assign assume automatic attribute before begin bind bins binsof break | ||
case casex casez clocking config constraint context continue cover | ||
covergroup coverpoint cross deassign defparam default design dist do | ||
else end endattribute endcase endclass endclocking endconfig | ||
endfunction endgenerate endgroup endinterface endmodule endpackage | ||
endprimitive endprogram endproperty endspecify endsequence endtable | ||
endtask expect export extends extern final first_match for force | ||
foreach fork forkjoin forever function generate genvar if iff ifnone | ||
ignore_bins illegal_bins import incdir include initial inside instance | ||
interface intersect join join_any join_none liblist library local | ||
localparam matches module modport new noshowcancelled null package | ||
parameter primitive priority program property protected | ||
pulsestyle_onevent pulsestyle_ondetect pure rand randc randcase | ||
randsequence release return sequence showcancelled solve specify super | ||
table task this throughout timeprecision timeunit type typedef unique | ||
use wait wait_order while wildcard with within | ||
) | ||
end | ||
|
||
def self.keywords_type | ||
@keywords_type ||= Set.new %w( | ||
and bit buf bufif0 bufif1 byte cell chandle class cmos const disable | ||
edge enum event highz0 highz1 initial inout input int integer join | ||
logic longint macromodule medium nand negedge nmos nor not | ||
notif0 notif1 or output packed parameter pmos posedge pull0 pull1 | ||
pulldown pullup rcmos real realtime ref reg repeat rnmos rpmos rtran | ||
rtranif0 rtranif1 scalared shortint shortreal signed specparam | ||
static string strength strong0 strong1 struct supply0 supply1 tagged | ||
time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg union | ||
unsigned uwire var vectored virtual void wait wand weak[01] wire wor | ||
xnor xor | ||
) | ||
end | ||
|
||
def self.keywords_system_task | ||
@keyword_system_task ||= Set.new %w( | ||
acos acosh asin asinh assertfailoff assertfailon assertkill | ||
assertnonvacuouson assertoff asserton assertpassoff assertpasson | ||
assertvacuousoff atan atan2 atanh bits bitstoreal bitstoshortreal | ||
cast ceil changed changed_gclk changing_gclk clog2 cos cosh countones | ||
coverage_control coverage_get coverage_get_max coverage_merge | ||
coverage_save dimensions display displayb displayh displayo | ||
dist_chi_square dist_erlang dist_exponential dist_normal dist_poisson | ||
dist_t dist_uniform dumpall dumpfile dumpflush dumplimit dumpoff | ||
dumpon dumpports dumpportsall dumpportsflush dumpportslimit | ||
dumpportsoff dumpportson dumpvars error exit exp falling_gclk fclose | ||
fdisplay fdisplayb fdisplayh fdisplayo fell fell_gclk feof ferror | ||
fflush fgetc fgets finish floor fmonitor fmonitorb fmonitorh fmonitoro | ||
fopen fread fscanf fseek fstrobe fstrobeb fstrobeh fstrobeo ftell | ||
future_gclk fwrite fwriteb fwriteh fwriteo get_coverage high hypot | ||
increment info isunbounded isunknown itor left ln load_coverage_db | ||
log10 low monitor monitorb monitorh monitoro monitoroff monitoron | ||
onehot onehot0 past past_gclk pow printtimescale q_add q_exam q_full | ||
q_initialize q_remove random readmemb readmemh realtime realtobits | ||
rewind right rising_gclk rose rose_gclk rtoi sampled | ||
set_coverage_db_name sformat sformatf shortrealtobits signed sin sinh | ||
size sqrt sscanf stable stable_gclk steady_gclk stime stop strobe | ||
strobeb strobeh strobeo swrite swriteb swriteh swriteo system tan tanh | ||
time timeformat typename ungetc unpacked_dimensions unsigned warning | ||
write writeb writeh writememb writememh writeo | ||
) | ||
end | ||
|
||
state :expr_bol do | ||
mixin :inline_whitespace | ||
rule /`define/, Comment::Preproc, :macro | ||
|
||
rule(//) { pop! } | ||
end | ||
|
||
# :expr_bol is the same as :bol but without labels, since | ||
# labels can only appear at the beginning of a statement. | ||
state :bol do | ||
rule /#{id}:(?!:)/, Name::Label | ||
mixin :expr_bol | ||
end | ||
|
||
state :inline_whitespace do | ||
rule /[ \t\r]+/, Text | ||
rule /\\\n/, Text # line continuation | ||
rule %r(/(\\\n)?[*].*?[*](\\\n)?/)m, Comment::Multiline | ||
end | ||
|
||
state :whitespace do | ||
rule /\n+/m, Text, :bol | ||
rule %r(//(\\.|.)*?\n), Comment::Single, :bol | ||
mixin :inline_whitespace | ||
end | ||
|
||
state :expr_whitespace do | ||
rule /\n+/m, Text, :expr_bol | ||
mixin :whitespace | ||
end | ||
|
||
state :string do | ||
rule /"/, Str, :pop! | ||
rule /\\([\\abfnrtv"']|x[a-fA-F0-9]{2,4}|[0-7]{1,3})/, Str::Escape | ||
rule /[^\\"\n]+/, Str | ||
rule /\\\n/, Str | ||
rule /\\/, Str # stray backslash | ||
end | ||
|
||
state :statement do | ||
mixin :whitespace | ||
rule /L?"/, Str, :string | ||
rule /(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?/i, Num::Float | ||
rule /\d+e[+-]?[0-9]+/i, Num::Float | ||
rule /[0-9]*'h[0-9a-fA-F]+/, Num::Hex | ||
rule /[0-9]*'b?[01xz]+/, Num::Bin | ||
rule /[0-9]*'d[0-9]+/, Num::Integer | ||
rule /\d+[lu]*/i, Num::Integer | ||
rule %r([~!%^&*+-=\|?:<>/@{}]), Operator | ||
rule /[()\[\],.$\#]/, Punctuation | ||
rule /`(\w+)/, Comment::Preproc | ||
|
||
rule id do |m| | ||
name = m[0] | ||
|
||
if self.class.keywords.include? name | ||
token Keyword | ||
elsif self.class.keywords_type.include? name | ||
token Keyword::Type | ||
elsif self.class.keywords_system_task.include? name | ||
token Name::Builtin | ||
else | ||
token Name | ||
end | ||
end | ||
end | ||
|
||
state :root do | ||
mixin :expr_whitespace | ||
rule(//) { push :statement } | ||
end | ||
|
||
state :macro do | ||
rule /\n/, Comment::Preproc, :pop! | ||
mixin :inline_whitespace | ||
rule /;/, Punctuation | ||
rule /\=/, Operator | ||
rule /(\w+)/, Text | ||
end | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- # | ||
|
||
describe Rouge::Lexers::Verilog do | ||
let(:subject) { Rouge::Lexers::Verilog.new } | ||
|
||
describe 'guessing' do | ||
include Support::Guessing | ||
|
||
it 'guesses by filename' do | ||
assert_guess :filename => 'foo.v' | ||
assert_guess :filename => 'foo.sv' | ||
assert_guess :filename => 'foo.svh' | ||
end | ||
|
||
it 'guesses by mimetype' do | ||
assert_guess :mimetype => 'text/x-verilog' | ||
assert_guess :mimetype => 'text/x-systemverilog' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/** | ||
* Verilog Lexer | ||
*/ | ||
class C #(parameter int N = 1) extends BaseClass; | ||
int x; | ||
protected int data; | ||
|
||
constraint cq { message.data inside {[0:8]}; } | ||
|
||
task set (int i); | ||
x = i; | ||
endtask | ||
|
||
function int get; | ||
return x; | ||
endfunction | ||
|
||
endclass | ||
|
||
/* | ||
Register module | ||
*/ | ||
class Register #(parameter type T = int); | ||
T data; | ||
endclass | ||
|
||
virtual class Register; | ||
endclass | ||
|
||
typedef struct { | ||
rand bit [10:0] ID; // 11-bit identifier | ||
bit [1:0] rsvd; // "reserved for expansion" bits | ||
rand byte data[]; // data payload | ||
} message_t; | ||
|
||
class CAN_Message; | ||
rand message_t message; | ||
|
||
task getbits(ref bit data_o, input int delay=1); | ||
bit [17:0] header; | ||
bit [14:0] tail; | ||
header = {message.ID,message.RTR,message.rsvd,message.DLC}; | ||
tail = message.CRC; | ||
$display("tail=%0b",tail); | ||
//step through message and output each bit (from left to right) | ||
foreach(header[i]) #delay data_o = header[i]; | ||
foreach(message.data[i,j]) #delay data_o = message.data[i][j]; | ||
foreach(tail[i]) #delay data_o = tail[i]; | ||
endtask | ||
endclass | ||
|
||
enum {Red, Green, Blue} Colour; | ||
|
||
covergroup cg_Colour @(posedge Clock); | ||
coverpoint Colour; | ||
endgroup | ||
|
||
cg_Colour = new cg_inst; | ||
|
||
covergroup cg_Short @(posedge Clock); | ||
coverpoint i { | ||
bins zero = { 0 }; | ||
bins small = { [1:100] }; | ||
bins hunds[3] = { 200,300,400,500,600,700,800,900 }; | ||
bins large = { [1000:$] }; | ||
bins others[] = default; | ||
}; | ||
endgroup | ||
|
||
module Bus(input In1, output Out1); | ||
import "DPI" function void slave_write(input int address, | ||
input int data); | ||
export "DPI" function write; // Note – not a function prototype | ||
|
||
// This SystemVerilog function could be called from C | ||
function void write(int address, int data); | ||
// Call C function | ||
slave_write(address, data); // Arguments passed by copy | ||
endfunction | ||
... | ||
endmodule | ||
|
||
// Verilog code for AND-OR-INVERT gate | ||
module AOI (input A, B, C, D, output F); | ||
assign F = ~((A & B) | (C & D)); | ||
reg f; | ||
always @(sel or a or b) | ||
reg f, g; // a new reg variable, g | ||
always @(sel or a or b) | ||
begin | ||
if (sel == 1) | ||
begin | ||
f = a; | ||
g = ~a; | ||
end | ||
else | ||
begin | ||
f = b; | ||
g = a & b; | ||
end | ||
|
||
casez(A) | ||
4'b1???: Y<=4'b1000; | ||
4'b01??: Y<=4'b0100; | ||
4'b001?: Y<=4'b0010; | ||
4'b0001: Y<=4'b0001; | ||
default: Y<=4'b0000; | ||
endcase | ||
|
||
for (i = 0; i < 16; i = i +1) begin | ||
$display ("Current value of i is %d", i); | ||
end | ||
|
||
repeat (16) begin | ||
$display ("Current value of i is %d", i); | ||
i = i + 1; | ||
end | ||
end | ||
|
||
parameter ROWBITS = 4; | ||
reg [ROWBITS-1:0] temp; | ||
always @(posedge sysclk) begin | ||
temp <= '0; // fill with 0 | ||
end | ||
end | ||
|
||
parameter ROWBITS = 4; | ||
reg [ROWBITS-1:0] temp; | ||
always @(posedge sysclk) begin | ||
for (integer c=0; c<ROWBITS; c=c+1) begin: test | ||
temp[c] <= 1'b0; | ||
end | ||
end | ||
|
||
genvar index; | ||
generate | ||
for (index=0; index < 8; index=index+1) | ||
begin: gen_code_label | ||
BUFR BUFR_inst ( | ||
.O(clk_o(index)), // Clock buffer ouptput | ||
.CE(ce), // Clock enable input | ||
.CLR(clear), // Clock buffer reset input | ||
.I(clk_i(index)) // Clock buffer input | ||
); | ||
end | ||
endgenerate | ||
|
||
always_latch begin | ||
if (enable) begin | ||
a_latch = something; | ||
end | ||
//No else clause so a_latch's value | ||
//is not always defined, so it holds its value | ||
end | ||
|
||
always @* begin | ||
if (enable) begin | ||
a_latch = something; | ||
end | ||
//No else clause so a_latch's value | ||
//is not always defined, so it holds its value | ||
end | ||
|
||
always_ff @(posedge clk) begin | ||
a <= b; | ||
end | ||
|
||
endmodule | ||
// end of Verilog code | ||
// |