From 15000e71d1c5cfe92d9f3eaddbc95ed6483b675f Mon Sep 17 00:00:00 2001 From: Taichi Ishitani Date: Wed, 15 Jan 2025 00:06:07 +0900 Subject: [PATCH] check veryl keyword (refs: rggen/rggen#154) --- lib/rggen/veryl.rb | 6 + .../veryl/register_map/keyword_checker.rb | 35 ++++ lib/rggen/veryl/register_map/name.rb | 10 + spec/rggen/veryl/register_map/name_spec.rb | 189 ++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 lib/rggen/veryl/register_map/keyword_checker.rb create mode 100644 lib/rggen/veryl/register_map/name.rb create mode 100644 spec/rggen/veryl/register_map/name_spec.rb diff --git a/lib/rggen/veryl.rb b/lib/rggen/veryl.rb index ed5ec77..eb118c3 100644 --- a/lib/rggen/veryl.rb +++ b/lib/rggen/veryl.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'rggen/systemverilog/rtl' require_relative 'veryl/version' require_relative 'veryl/utility/data_object' require_relative 'veryl/utility/modport' @@ -10,6 +11,7 @@ require_relative 'veryl/component' require_relative 'veryl/feature' require_relative 'veryl/factories' +require_relative 'veryl/register_map/keyword_checker' RgGen.setup_plugin :'rggen-veryl' do |plugin| plugin.version RgGen::Veryl::VERSION @@ -54,4 +56,8 @@ 'veryl/bit_field/type/wo_wo1_wotrg', 'veryl/bit_field/type/wrc_wrs' ] + + plugin.files [ + 'veryl/register_map/name' + ] end diff --git a/lib/rggen/veryl/register_map/keyword_checker.rb b/lib/rggen/veryl/register_map/keyword_checker.rb new file mode 100644 index 0000000..75ea868 --- /dev/null +++ b/lib/rggen/veryl/register_map/keyword_checker.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module RgGen + module Veryl + module RegisterMap + module KeywordChecker + VERYL_KEYWORDS = [ + 'always_comb', 'always_ff', 'as', 'assign', 'bit', 'break', 'case', 'clock', + 'clock_negedge', 'clock_posedge', 'const', 'default', 'else', 'embed', 'enum', + 'export', 'f32', 'f64', 'final', 'for', 'function', 'i32', 'i64', 'if', + 'if_reset', 'import', 'in', 'include', 'initial', 'inout', 'input', 'inside', + 'inst', 'interface', 'let', 'local', 'logic', 'modport', 'module', 'output', + 'outside', 'package', 'param', 'proto', 'pub', 'ref', 'repeat', 'reset', + 'reset_async_high', 'reset_async_low', 'reset_sync_high', 'reset_sync_low', + 'return', 'signed', 'step', 'struct', 'switch', 'tri', 'type', 'u32', 'u64', + 'unsafe', 'var' + ].freeze + + def self.included(klass) + klass.class_eval do + verify(:feature, prepend: true) do + error_condition do + @name && VERYL_KEYWORDS.include?(@name) + end + message do + layer_name = component.layer.to_s.sub('_', ' ') + "veryl keyword is not allowed for #{layer_name} name: #{@name}" + end + end + end + end + end + end + end +end diff --git a/lib/rggen/veryl/register_map/name.rb b/lib/rggen/veryl/register_map/name.rb new file mode 100644 index 0000000..b7ef882 --- /dev/null +++ b/lib/rggen/veryl/register_map/name.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +[:register_block, :register_file, :register, :bit_field].each do |layer| + RgGen.modify_simple_feature(layer, :name) do + register_map do + include RgGen::SystemVerilog::RegisterMap::KeywordChecker + include RgGen::Veryl::RegisterMap::KeywordChecker + end + end +end diff --git a/spec/rggen/veryl/register_map/name_spec.rb b/spec/rggen/veryl/register_map/name_spec.rb new file mode 100644 index 0000000..956ac57 --- /dev/null +++ b/spec/rggen/veryl/register_map/name_spec.rb @@ -0,0 +1,189 @@ +# frozen_string_literal: true + +RSpec.describe 'regiter_map/name' do + include_context 'clean-up builder' + include_context 'register map common' + + before(:all) do + RgGen.enable(:register_block, :name) + RgGen.enable(:register_file, :name) + RgGen.enable(:register, :name) + RgGen.enable(:bit_field, :name) + end + + let(:veryl_keywords) do + [ + 'always_comb', 'always_ff', 'as', 'assign', 'bit', 'break', 'case', 'clock', + 'clock_negedge', 'clock_posedge', 'const', 'default', 'else', 'embed', 'enum', + 'export', 'f32', 'f64', 'final', 'for', 'function', 'i32', 'i64', 'if', 'if_reset', + 'import', 'in', 'include', 'initial', 'inout', 'input', 'inside', 'inst', 'interface', + 'let', 'local', 'logic', 'modport', 'module', 'output', 'outside', 'package', 'param', + 'proto', 'pub', 'ref', 'repeat', 'reset', 'reset_async_high', 'reset_async_low', + 'reset_sync_high', 'reset_sync_low', 'return', 'signed', 'step', 'struct', 'switch', + 'tri', 'type', 'u32', 'u64', 'unsafe', 'var' + ] + end + + let(:systemverilog_keywords) do + [ + 'accept_on', 'alias', 'always', 'always_comb', 'always_ff', + 'always_latch', 'and', 'assert', 'assign', 'assume', 'automatic', + 'before', 'begin', 'bind', 'bins', 'binsof', 'bit', 'break', 'buf', + 'bufif0', 'bufif1', 'byte', 'case', 'casex', 'casez', 'cell', 'chandle', + 'checker', 'class', 'clocking', 'cmos', 'config', 'const', 'constraint', + 'context', 'continue', 'cover', 'covergroup', 'coverpoint', 'cross', + 'deassign', 'default', 'defparam', 'design', 'disable', 'dist', 'do', + 'edge', 'else', 'end', 'endcase', 'endchecker', 'endclass', 'endclocking', + 'endconfig', 'endfunction', 'endgenerate', 'endgroup', 'endinterface', + 'endmodule', 'endpackage', 'endprimitive', 'endprogram', 'endproperty', + 'endspecify', 'endsequence', 'endtable', 'endtask', 'enum', 'event', + 'eventually', 'expect', 'export', 'extends', 'extern', 'final', 'first_match', + 'for', 'force', 'foreach', 'forever', 'fork', 'forkjoin', 'function', + 'generate', 'genvar', 'global', 'highz0', 'highz1', 'if', 'iff', 'ifnone', + 'ignore_bins', 'illegal_bins', 'implements', 'implies', 'import', 'incdir', + 'include', 'initial', 'inout', 'input', 'inside', 'instance', 'int', + 'integer', 'interconnect', 'interface', 'intersect', 'join', 'join_any', + 'join_none', 'large', 'let', 'liblist', 'library', 'local', 'localparam', + 'logic', 'longint', 'macromodule', 'matches', 'medium', 'modport', + 'module', 'nand', 'negedge', 'nettype', 'new', 'nexttime', 'nmos', + 'nor', 'noshowcancelled', 'not', 'notif0', 'notif1', 'null', 'or', + 'output', 'package', 'packed', 'parameter', 'pmos', 'posedge', 'primitive', + 'priority', 'program', 'property', 'protected', 'pull0', 'pull1', + 'pulldown', 'pullup', 'pulsestyle_ondetect', 'pulsestyle_onevent', + 'pure', 'rand', 'randc', 'randcase', 'randsequence', 'rcmos', 'real', + 'realtime', 'ref', 'reg', 'reject_on', 'release', 'repeat', 'restrict', + 'return', 'rnmos', 'rpmos', 'rtran', 'rtranif0', 'rtranif1', 's_always', + 's_eventually', 's_nexttime', 's_until', 's_until_with', 'scalared', + 'sequence', 'shortint', 'shortreal', 'showcancelled', 'signed', 'small', + 'soft', 'solve', 'specify', 'specparam', 'static', 'string', 'strong', + 'strong0', 'strong1', 'struct', 'super', 'supply0', 'supply1', + 'sync_accept_on', 'sync_reject_on', 'table', 'tagged', 'task', 'this', + 'throughout', 'time', 'timeprecision', 'timeunit', 'tran', 'tranif0', + 'tranif1', 'tri', 'tri0', 'tri1', 'triand', 'trior', 'trireg', 'type', + 'typedef', 'union', 'unique', 'unique0', 'unsigned', 'until', 'until_with', + 'untyped', 'use', 'uwire', 'var', 'vectored', 'virtual', 'void', 'wait', + 'wait_order', 'wand', 'weak', 'weak0', 'weak1', 'while', 'wildcard', + 'wire', 'with', 'within', 'wor', 'xnor', 'xor' + ] - veryl_keywords + end + + context 'レジスタブロック名がVerylの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + veryl_keywords.each do |keyword| + expect { + create_register_map do + register_block { name keyword } + end + }.to raise_register_map_error "veryl keyword is not allowed for register block name: #{keyword}" + end + end + end + + context 'レジスタブロック名がSystemVerilogの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + systemverilog_keywords.each do |keyword| + expect { + create_register_map do + register_block { name keyword } + end + }.to raise_register_map_error "systemverilog keyword is not allowed for register block name: #{keyword}" + end + end + end + + context 'レジスタファイル名がVerylの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + veryl_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register_file { name keyword } + end + end + }.to raise_register_map_error "veryl keyword is not allowed for register file name: #{keyword}" + end + end + end + + context 'レジスタファイル名がSystemVerilogの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + systemverilog_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register_file { name keyword } + end + end + }.to raise_register_map_error "systemverilog keyword is not allowed for register file name: #{keyword}" + end + end + end + + context 'レジスタ名がVerylの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + veryl_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register { name keyword } + end + end + }.to raise_register_map_error "veryl keyword is not allowed for register name: #{keyword}" + end + end + end + + context 'レジスタ名がSystemVerilogの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + systemverilog_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register { name keyword } + end + end + }.to raise_register_map_error "systemverilog keyword is not allowed for register name: #{keyword}" + end + end + end + + context 'ビットフィールド名がVerylの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + veryl_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register do + name 'register_0' + bit_field { name keyword } + end + end + end + }.to raise_register_map_error "veryl keyword is not allowed for bit field name: #{keyword}" + end + end + end + + context 'ビットフィールド名がSystemVerilogの予約語に一致する場合' do + it 'RegiterMapErrorを起こす' do + systemverilog_keywords.each do |keyword| + expect { + create_register_map do + register_block do + name 'block_0' + register do + name 'register_0' + bit_field { name keyword } + end + end + end + }.to raise_register_map_error "systemverilog keyword is not allowed for bit field name: #{keyword}" + end + end + end +end