# -*- coding: utf-8 -*- """ HDL Tests ~~~~~~~~~ :copyright: Copyright 2006-2020 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import pytest from pygments.lexers import SystemVerilogLexer from pygments.token import (Comment, Keyword, Name, Number, Operator, Punctuation, Text) @pytest.fixture(scope='module') def lexer(): yield SystemVerilogLexer() SYSTEMVERILOG_BASIC_TEXT = """\ // Adder flops the sum of its inputs module Adder #( parameter int N = 42 ) ( output logic [N-1:0] y, output logic co, input logic [N-1:0] a, input logic [N-1:0] b, input logic ci, input logic clk ); always_ff @(posedge clk) begin {co, y} <= a + b + ci; end endmodule : Adder """ SYSTEMVERILOG_BASIC_TOKENS = [ (Comment.Single, '// Adder flops the sum of its inputs\n'), (Keyword, 'module'), (Text, ' '), (Name, 'Adder'), (Text, ' '), (Punctuation, '#'), (Punctuation, '('), (Text, '\n'), (Text, ' '), (Keyword, 'parameter'), (Text, ' '), (Keyword.Type, 'int'), (Text, ' '), (Name, 'N'), (Text, ' '), (Operator, '='), (Text, ' '), (Number.Integer, '42'), (Text, '\n'), (Punctuation, ')'), (Text, ' '), (Punctuation, '('), (Text, '\n'), (Text, ' '), (Keyword, 'output'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Punctuation, '['), (Name, 'N'), (Operator, '-'), (Number.Integer, '1'), (Operator, ':'), (Number.Integer, '0'), (Punctuation, ']'), (Text, ' '), (Name, 'y'), (Punctuation, ','), (Text, '\n'), (Text, ' '), (Keyword, 'output'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Name, 'co'), (Punctuation, ','), (Text, '\n'), (Text, '\n'), (Text, ' '), (Keyword, 'input'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Punctuation, '['), (Name, 'N'), (Operator, '-'), (Number.Integer, '1'), (Operator, ':'), (Number.Integer, '0'), (Punctuation, ']'), (Text, ' '), (Name, 'a'), (Punctuation, ','), (Text, '\n'), (Text, ' '), (Keyword, 'input'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Punctuation, '['), (Name, 'N'), (Operator, '-'), (Number.Integer, '1'), (Operator, ':'), (Number.Integer, '0'), (Punctuation, ']'), (Text, ' '), (Name, 'b'), (Punctuation, ','), (Text, '\n'), (Text, ' '), (Keyword, 'input'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Name, 'ci'), (Punctuation, ','), (Text, '\n'), (Text, '\n'), (Text, ' '), (Keyword, 'input'), (Text, ' '), (Keyword.Type, 'logic'), (Text, ' '), (Name, 'clk'), (Text, '\n'), (Punctuation, ')'), (Punctuation, ';'), (Text, '\n'), (Text, ' '), (Keyword, 'always_ff'), (Text, ' '), (Punctuation, '@'), (Punctuation, '('), (Keyword, 'posedge'), (Text, ' '), (Name, 'clk'), (Punctuation, ')'), (Text, ' '), (Keyword, 'begin'), (Text, '\n'), (Text, ' '), (Punctuation, '{'), (Name, 'co'), (Punctuation, ','), (Text, ' '), (Name, 'y'), (Punctuation, '}'), (Text, ' '), (Operator, '<'), (Operator, '='), (Text, ' '), (Name, 'a'), (Text, ' '), (Operator, '+'), (Text, ' '), (Name, 'b'), (Text, ' '), (Operator, '+'), (Text, ' '), (Name, 'ci'), (Punctuation, ';'), (Text, '\n'), (Text, ' '), (Keyword, 'end'), (Text, '\n'), (Keyword, 'endmodule'), (Text, ' '), (Operator, ':'), (Text, ' '), (Name, 'Adder'), (Text, '\n'), ] def test_systemverilog_basic(lexer): """A basic SystemVerilog test. Examine tokens emitted by the SV lexer for a trivial module. Not intended to stress any particular corner of the language. """ tokens = list(lexer.get_tokens(SYSTEMVERILOG_BASIC_TEXT)) assert tokens == SYSTEMVERILOG_BASIC_TOKENS # Believe it or not, SystemVerilog supports spaces before and after the base # specifier (ie 'b, 'd, 'h). See IEEE 1800-2017 Section 5.7.1 for examples. SYSTEMVERILOG_NUMBERS_TEXT = """ 8'b10101010 8 'b10101010 8'b 10101010 8'sb10101010 8'Sb10101010 8'B10101010 8'b1010_1010 8'b10xXzZ?10 24'o01234567 24 'o01234567 24'o 01234567 24'so01234567 24'So01234567 24'O01234567 24'o0123_4567 24'o01xXzZ?7 32'd27182818 32 'd27182818 32'd 27182818 32'sd27182818 32'Sd27182818 32'D27182818 32'd2718_2818 32'd27xXzZ?8 32'hdeadbeef 32 'hdeadbeef 32'h deadbeef 32'shdeadbeef 32'Shdeadbeef 32'Hdeadbeef 32'hdead_beef 32'hdexXzZ?f '0 '1 'x 'X 'z 'Z 42 1234_5678 """ SYSTEMVERILOG_NUMBERS_TOKENS = [ (Number.Bin, "8'b10101010"), (Text, '\n'), (Number.Bin, "8 'b10101010"), (Text, '\n'), (Number.Bin, "8'b 10101010"), (Text, '\n'), (Number.Bin, "8'sb10101010"), (Text, '\n'), (Number.Bin, "8'Sb10101010"), (Text, '\n'), (Number.Bin, "8'B10101010"), (Text, '\n'), (Number.Bin, "8'b1010_1010"), (Text, '\n'), (Number.Bin, "8'b10xXzZ?10"), (Text, '\n'), (Text, '\n'), (Number.Oct, "24'o01234567"), (Text, '\n'), (Number.Oct, "24 'o01234567"), (Text, '\n'), (Number.Oct, "24'o 01234567"), (Text, '\n'), (Number.Oct, "24'so01234567"), (Text, '\n'), (Number.Oct, "24'So01234567"), (Text, '\n'), (Number.Oct, "24'O01234567"), (Text, '\n'), (Number.Oct, "24'o0123_4567"), (Text, '\n'), (Number.Oct, "24'o01xXzZ?7"), (Text, '\n'), (Text, '\n'), (Number.Integer, "32'd27182818"), (Text, '\n'), (Number.Integer, "32 'd27182818"), (Text, '\n'), (Number.Integer, "32'd 27182818"), (Text, '\n'), (Number.Integer, "32'sd27182818"), (Text, '\n'), (Number.Integer, "32'Sd27182818"), (Text, '\n'), (Number.Integer, "32'D27182818"), (Text, '\n'), (Number.Integer, "32'd2718_2818"), (Text, '\n'), (Number.Integer, "32'd27xXzZ?8"), (Text, '\n'), (Text, '\n'), (Number.Hex, "32'hdeadbeef"), (Text, '\n'), (Number.Hex, "32 'hdeadbeef"), (Text, '\n'), (Number.Hex, "32'h deadbeef"), (Text, '\n'), (Number.Hex, "32'shdeadbeef"), (Text, '\n'), (Number.Hex, "32'Shdeadbeef"), (Text, '\n'), (Number.Hex, "32'Hdeadbeef"), (Text, '\n'), (Number.Hex, "32'hdead_beef"), (Text, '\n'), (Number.Hex, "32'hdexXzZ?f"), (Text, '\n'), (Text, '\n'), (Number, "'0"), (Text, ' '), (Number, "'1"), (Text, ' '), (Number, "'x"), (Text, ' '), (Number, "'X"), (Text, ' '), (Number, "'z"), (Text, ' '), (Number, "'Z"), (Text, '\n'), (Text, '\n'), (Number.Integer, '42'), (Text, ' '), (Number.Integer, '1234_5678'), (Text, '\n'), ] def test_systemverilog_numbers(lexer): """Test most types of numbers""" tokens = list(lexer.get_tokens(SYSTEMVERILOG_NUMBERS_TEXT)) assert tokens == SYSTEMVERILOG_NUMBERS_TOKENS # See 1800-2017 Table 11-2: Operator Precedence and Associativity # Note that the duplicates (unary/binary) have been removed, # ie '+', '-', '&', '|', '^', '~^', '^~' SYSTEMVERILOG_OPERATORS_TEXT = """ () [] :: . + - ! ~ & ~& | ~| ^ ~^ ^~ ++ -- ** * / % << >> <<< >>> < <= > >= inside dist == != === !== ==? !=? && || ?: -> <-> = += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= := :/ <= {} {{}} """ # Note: This is a inconsistent mix of operator and punctuation SYSTEMVERILOG_OPERATORS_TOKENS = [ (Punctuation, '('), (Punctuation, ')'), (Text, ' '), (Punctuation, '['), (Punctuation, ']'), (Text, ' '), # Note: This should be '::' (Operator, ':'), (Operator, ':'), (Text, ' '), (Punctuation, '.'), (Text, '\n'), (Operator, '+'), (Text, ' '), (Operator, '-'), (Text, ' '), (Operator, '!'), (Text, ' '), (Operator, '~'), (Text, ' '), (Operator, '&'), (Text, ' '), # Note: This should be '~&' (Operator, '~'), (Operator, '&'), (Text, ' '), (Operator, '|'), (Text, ' '), # Note: This should be '~|' (Operator, '~'), (Operator, '|'), (Text, ' '), (Operator, '^'), (Text, ' '), # Note: This should be '~^' (Operator, '~'), (Operator, '^'), (Text, ' '), # Note: This should be '^~' (Operator, '^'), (Operator, '~'), (Text, ' '), # Note: This should be '++' (Operator, '+'), (Operator, '+'), (Text, ' '), # Note: This should be '--' (Operator, '-'), (Operator, '-'), (Text, '\n'), # Note: This should be '**' (Operator, '*'), (Operator, '*'), (Text, '\n'), (Operator, '*'), (Text, ' '), (Operator, '/'), (Text, ' '), (Operator, '%'), (Text, '\n'), # Note: This should be '<<' (Operator, '<'), (Operator, '<'), (Text, ' '), # Note: This should be '>>' (Operator, '>'), (Operator, '>'), (Text, ' '), # Note: This should be '<<<' (Operator, '<'), (Operator, '<'), (Operator, '<'), (Text, ' '), # Note: This should be '>>>' (Operator, '>'), (Operator, '>'), (Operator, '>'), (Text, '\n'), (Operator, '<'), (Text, ' '), # Note: This should be '<=' (Operator, '<'), (Operator, '='), (Text, ' '), (Operator, '>'), (Text, ' '), # Note: This should be '>=' (Operator, '>'), (Operator, '='), (Text, ' '), (Operator.Word, 'inside'), (Text, ' '), (Operator.Word, 'dist'), (Text, '\n'), # Note: This should be '==' (Operator, '='), (Operator, '='), (Text, ' '), # Note: This should be '!=' (Operator, '!'), (Operator, '='), (Text, ' '), # Note: This should be '===' (Operator, '='), (Operator, '='), (Operator, '='), (Text, ' '), # Note: This should be '!==' (Operator, '!'), (Operator, '='), (Operator, '='), (Text, ' '), # Note: This should be '==?' (Operator, '='), (Operator, '='), (Operator, '?'), (Text, ' '), # Note: This should be '!=?' (Operator, '!'), (Operator, '='), (Operator, '?'), (Text, '\n'), # Note: This should be '&&' (Operator, '&'), (Operator, '&'), (Text, '\n'), # Note: This should be '||' (Operator, '|'), (Operator, '|'), (Text, '\n'), (Operator, '?'), (Operator, ':'), (Text, '\n'), # Note: This should be '->' (Operator, '-'), (Operator, '>'), (Text, ' '), # Note: This should be '<->' (Operator, '<'), (Operator, '-'), (Operator, '>'), (Text, '\n'), (Operator, '='), (Text, ' '), # Note: This should be '+=' (Operator, '+'), (Operator, '='), (Text, ' '), # Note: This should be '-=' (Operator, '-'), (Operator, '='), (Text, ' '), # Note: This should be '*=' (Operator, '*'), (Operator, '='), (Text, ' '), # Note: This should be '/=' (Operator, '/'), (Operator, '='), (Text, ' '), # Note: This should be '%=' (Operator, '%'), (Operator, '='), (Text, ' '), # Note: This should be '&=' (Operator, '&'), (Operator, '='), (Text, ' '), # Note: This should be '^=' (Operator, '^'), (Operator, '='), (Text, ' '), # Note: This should be '|=' (Operator, '|'), (Operator, '='), (Text, ' '), # Note: This should be '<<=' (Operator, '<'), (Operator, '<'), (Operator, '='), (Text, ' '), # Note: This should be '>>=' (Operator, '>'), (Operator, '>'), (Operator, '='), (Text, ' '), # Note: This should be '<<<=' (Operator, '<'), (Operator, '<'), (Operator, '<'), (Operator, '='), (Text, ' '), # Note: This should be '>>>=' (Operator, '>'), (Operator, '>'), (Operator, '>'), (Operator, '='), (Text, ' '), # Note: This should be ':=' (Operator, ':'), (Operator, '='), (Text, ' '), # Note: This should be ':/' (Operator, ':'), (Operator, '/'), (Text, ' '), # Note: This should be '<=' (Operator, '<'), (Operator, '='), (Text, '\n'), (Punctuation, '{'), (Punctuation, '}'), (Text, ' '), # Note: This should be '{{' (Punctuation, '{'), (Punctuation, '{'), # Note: This should be '}}' (Punctuation, '}'), (Punctuation, '}'), (Text, '\n'), ] def test_systemverilog_operators(lexer): """Test various operators""" tokens = list(lexer.get_tokens(SYSTEMVERILOG_OPERATORS_TEXT)) assert tokens == SYSTEMVERILOG_OPERATORS_TOKENS # Most of the interesting types of class declarations SYSTEMVERILOG_CLASSES_TEXT = """ class Foo; endclass class Bar; endclass : Bar class Fiz extends Buz; endclass : Fiz class Free #(parameter type T = byte) extends Beer #(T); endclass : Free """ SYSTEMVERILOG_CLASSES_TOKENS = [ (Keyword.Declaration, 'class'), (Text, ' '), (Name.Class, 'Foo'), (Punctuation, ';'), (Text, '\n'), (Keyword.Declaration, 'endclass'), (Text, '\n'), (Text, '\n'), (Keyword.Declaration, 'class'), (Text, ' '), (Name.Class, 'Bar'), (Punctuation, ';'), (Text, '\n'), (Keyword.Declaration, 'endclass'), (Text, ' '), (Punctuation, ':'), (Text, ' '), (Name.Class, 'Bar'), (Text, '\n'), (Text, '\n'), (Keyword.Declaration, 'class'), (Text, ' '), (Name.Class, 'Fiz'), (Text, ' '), (Keyword.Declaration, 'extends'), (Text, ' '), (Name.Class, 'Buz'), (Punctuation, ';'), (Text, '\n'), (Keyword.Declaration, 'endclass'), (Text, ' '), (Punctuation, ':'), (Text, ' '), (Name.Class, 'Fiz'), (Text, '\n'), (Text, '\n'), (Keyword.Declaration, 'class'), (Text, ' '), (Name.Class, 'Free'), (Text, ' '), (Punctuation, '#'), (Punctuation, '('), (Keyword, 'parameter'), (Text, ' '), (Keyword.Type, 'type'), (Text, ' '), (Name, 'T'), (Text, ' '), (Operator, '='), (Text, ' '), (Keyword.Type, 'byte'), (Punctuation, ')'), (Text, ' '), (Keyword.Declaration, 'extends'), (Text, ' '), (Name.Class, 'Beer'), (Text, ' '), (Punctuation, '#'), (Punctuation, '('), (Name, 'T'), (Punctuation, ')'), (Punctuation, ';'), (Text, '\n'), (Keyword.Declaration, 'endclass'), (Text, ' '), (Punctuation, ':'), (Text, ' '), (Name.Class, 'Free'), (Text, '\n'), ] def test_systemverilog_classes(lexer): """Test class/extends/endclass group captures""" tokens = list(lexer.get_tokens(SYSTEMVERILOG_CLASSES_TEXT)) assert tokens == SYSTEMVERILOG_CLASSES_TOKENS