;; verilog-mode.el --- major mode for editing verilog source in Emacs ;; ;; $Id: verilog-mode.el 246 2006-06-21 22:32:17Z mac $ ;; Copyright (C) 2006 Free Software Foundation, Inc. ;; Author: Michael McNamara (mac@verilog.com) ;; http://www.verilog.com ;; ;; AUTO features, signal, modsig; by: Wilson Snyder ;; (wsnyder@wsnyder.org or wsnyder@world.std.com) ;; http://www.veripool.com ;; Keywords: languages ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: ;; This mode borrows heavily from the Pascal-mode and the cc-mode of emacs ;; USAGE ;; ===== ;; A major mode for editing Verilog HDL source code. When you have ;; entered Verilog mode, you may get more info by pressing C-h m. You ;; may also get online help describing various functions by: C-h f ;; ;; You can get step by step help in installing this file by going to ;; ;; The short list of installation instructions are: To set up ;; automatic verilog mode, put this file in your load path, and put ;; the following in code (please un comment it first!) in your ;; .emacs, or in your site's site-load.el ; (autoload 'verilog-mode "verilog-mode" "Verilog mode" t ) ; (setq auto-mode-alist (cons '("\\.v\\'" . verilog-mode) auto-mode-alist)) ; (setq auto-mode-alist (cons '("\\.dv\\'" . verilog-mode) auto-mode-alist)) ;; If you want to customize Verilog mode to fit your needs better, ;; you may add these lines (the values of the variables presented ;; here are the defaults). Note also that if you use an emacs that ;; supports custom, it's probably better to use the custom menu to ;; edit these. ;; ;; Be sure to examine at the help for verilog-auto, and the other ;; verilog-auto-* functions for some major coding time savers. ;; ; ;; User customization for Verilog mode ; (setq verilog-indent-level 3 ; verilog-indent-level-module 3 ; verilog-indent-level-declaration 3 ; verilog-indent-level-behavioral 3 ; verilog-indent-level-directive 1 ; verilog-case-indent 2 ; verilog-auto-newline t ; verilog-auto-indent-on-newline t ; verilog-tab-always-indent t ; verilog-auto-endcomments t ; verilog-minimum-comment-distance 40 ; verilog-indent-begin-after-if t ; verilog-auto-lineup '(all)) ;; KNOWN BUGS / BUG REPORTS ;; ======================= ;; This is beta code, and likely has bugs. Please report any and all ;; bugs to me at mac@verilog.com. Use ;; verilog-submit-bug-report to submit a report. ;; ;;; History: ;; ;; ;;; Code: (provide 'verilog-mode) ;; This variable will always hold the version number of the mode (defconst verilog-mode-version (substring "$$Revision: 246 $$" 12 -3) "Version of this verilog mode.") (defconst verilog-running-on-xemacs (string-match "XEmacs" emacs-version)) (defun verilog-version () "Inform caller of the version of this file." (interactive) (message (concat "Using verilog-mode version " verilog-mode-version) )) ;; Insure we have certain packages, and deal with it if we don't (if (fboundp 'eval-when-compile) (eval-when-compile (require 'verilog-mode) (condition-case nil (require 'imenu) (error nil)) (condition-case nil (require 'reporter) (error nil)) (condition-case nil (require 'easymenu) (error nil)) (condition-case nil (require 'regexp-opt) (error nil)) (condition-case nil (load "skeleton") ;; bug in 19.28 through 19.30 skeleton.el, not provided. (error nil)) (condition-case nil (require 'vc) (error nil)) (condition-case nil (if (fboundp 'when) nil ;; fab (defmacro when (var &rest body) (` (cond ( (, var) (,@ body)))))) (error nil)) (condition-case nil (if (fboundp 'unless) nil ;; fab (defmacro unless (var &rest body) (` (if (, var) nil (,@ body))))) (error nil)) (condition-case nil (if (fboundp 'store-match-data) nil ;; fab (defmacro store-match-data (&rest args) nil)) (error nil)) (condition-case nil (if (boundp 'current-menubar) nil ;; great (progn (defmacro set-buffer-menubar (&rest args) nil) (defmacro add-submenu (&rest args) nil)) ) (error nil)) (condition-case nil (if (fboundp 'zmacs-activate-region) nil ;; great (defmacro zmacs-activate-region (&rest args) nil)) (error nil)) (condition-case nil (if (fboundp 'char-before) nil ;; great (defmacro char-before (&rest body) (` (char-after (1- (point)))))) (error nil)) ;; Requires to define variables that would be "free" warnings (condition-case nil (require 'font-lock) (error nil)) (condition-case nil (require 'compile) (error nil)) (condition-case nil (require 'custom) (error nil)) (condition-case nil (require 'dinotrace) (error nil)) (condition-case nil (if (fboundp 'dinotrace-unannotate-all) nil ;; great (defun dinotrace-unannotate-all (&rest args) nil)) (error nil)) (condition-case nil (if (fboundp 'customize-apropos) nil ;; great (defun customize-apropos (&rest args) nil)) (error nil)) (condition-case nil (if (fboundp 'match-string-no-properties) nil ;; great (defsubst match-string-no-properties (match) (buffer-substring-no-properties (match-beginning match) (match-end match)))) (error nil)) (if (and (featurep 'custom) (fboundp 'custom-declare-variable)) nil ;; We've got what we needed ;; We have the old custom-library, hack around it! (defmacro defgroup (&rest args) nil) (defmacro customize (&rest args) (message "Sorry, Customize is not available with this version of emacs")) (defmacro defcustom (var value doc &rest args) (` (defvar (, var) (, value) (, doc)))) ) (if (fboundp 'defface) nil ; great! (defmacro defface (var value doc &rest args) (` (make-face (, var)))) ) (if (and (featurep 'custom) (fboundp 'customize-group)) nil ;; We've got what we needed ;; We have an intermediate custom-library, hack around it! (defmacro customize-group (var &rest args) (`(customize (, var) ))) ) )) ;; Provide a regular expression optimization routine, using regexp-opt ;; if provided by the user's elisp libraries (eval-and-compile (if (fboundp 'regexp-opt) ;; regexp-opt is defined, does it take 3 or 2 arguments? (if (fboundp 'function-max-args) (case (function-max-args `regexp-opt) ( 3 ;; It takes 3 (condition-case nil ; Hide this defun from emacses ;with just a two input regexp (defun verilog-regexp-opt (a b) "Deal with differing number of required arguments for `regexp-opt'. Call 'regexp-opt' on A and B." (regexp-opt a b 't) ) (error nil)) ) ( 2 ;; It takes 2 (defun verilog-regexp-opt (a b) "Call 'regexp-opt' on A and B." (regexp-opt a b)) ) ( t nil)) ;; We can't tell; assume it takes 2 (defun verilog-regexp-opt (a b) "Call 'regexp-opt' on A and B." (regexp-opt a b)) ) ;; There is no regexp-opt, provide our own (defun verilog-regexp-opt (strings &optional paren shy) (let ((open (if paren "\\(" "")) (close (if paren "\\)" ""))) (concat open (mapconcat 'regexp-quote strings "\\|") close))) )) (eval-when-compile (defun verilog-regexp-words (a) "Call 'regexp-opt' with word delimiters." (concat "\\<" (verilog-regexp-opt a t) "\\>"))) (defun verilog-regexp-words (a) "Call 'regexp-opt' with word delimiters for the words A." (concat "\\<" (verilog-regexp-opt a t) "\\>")) (defun verilog-customize () "Link to customize screen for Verilog." (interactive) (customize-group 'verilog-mode)) (defun verilog-font-customize () "Link to customize fonts used for Verilog." (interactive) (customize-apropos "font-lock-*" 'faces)) (defgroup verilog-mode nil "Facilitates easy editing of Verilog source text" :group 'languages) ; (defgroup verilog-mode-fonts nil ; "Facilitates easy customization fonts used in Verilog source text" ; :link '(customize-apropos "font-lock-*" 'faces) ; :group 'verilog-mode) (defgroup verilog-mode-indent nil "Customize indentation and highlighting of verilog source text" :group 'verilog-mode) (defgroup verilog-mode-actions nil "Customize actions on verilog source text" :group 'verilog-mode) (defgroup verilog-mode-auto nil "Customize AUTO actions when expanding verilog source text" :group 'verilog-mode) (defcustom verilog-linter "surelint --std --synth --style --sim --race --fsm --msglimit=none " "*Unix program and arguments to call to run a lint checker on verilog source. Invoked when you type \\[compile]. \\[next-error] will take you to the next lint error as expected." :type 'string :group 'verilog-mode-actions) (defcustom verilog-coverage "surecov --code --fsm --expr " "*Program and arguments to use to annotate for coverage verilog source." :type 'string :group 'verilog-mode-actions) (defcustom verilog-simulator "verilog " "*Program and arguments to use to interpret verilog source." :type 'string :group 'verilog-mode-actions) (defcustom verilog-compiler "vcs " "*Program and arguments to use to compile verilog source." :type 'string :group 'verilog-mode-actions) (defvar verilog-tool 'verilog-linter) (defcustom verilog-highlight-translate-off nil "*Non-nil means background-highlight code excluded from translation. That is, all code between \"// synopsys translate_off\" and \"// synopsys translate_on\" is highlighted using a different background color \(face `verilog-font-lock-translate-off-face'). Note: this will slow down on-the-fly fontification (and thus editing). NOTE: Activate the new setting in a Verilog buffer by re-fontifying it (menu entry \"Fontify Buffer\"). XEmacs: turn off and on font locking." :type 'boolean :group 'verilog-mode-indent) (defcustom verilog-indent-level 3 "*Indentation of Verilog statements with respect to containing block." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-indent-level-module 3 "* Indentation of Module level Verilog statements. (eg always, initial) Set to 0 to get initial and always statements lined up on the left side of your screen." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-indent-level-declaration 3 "*Indentation of declarations with respect to containing block. Set to 0 to get them list right under containing block." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-indent-declaration-macros nil "*How to treat macro expansions in a declaration. If nil, indent as: input [31:0] a; input `CP; output c; If non nil, treat as input [31:0] a; input `CP ; output c;" :group 'verilog-mode-indent :type 'boolean) (defcustom verilog-indent-lists t "*How to treat indenting items in a list. If t (the default), indent as: always @( posedge a or reset ) begin If nil, treat as always @( posedge a or reset ) begin" :group 'verilog-mode-indent :type 'boolean) (defcustom verilog-indent-level-behavioral 3 "*Absolute indentation of first begin in a task or function block. Set to 0 to get such code to start at the left side of the screen." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-indent-level-directive 1 "*Indentation to add to each level of `ifdef declarations. Set to 0 to have all directives start at the left side of the screen." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-cexp-indent 2 "*Indentation of Verilog statements split across lines." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-case-indent 2 "*Indentation for case statements." :group 'verilog-mode-indent :type 'integer) (defcustom verilog-auto-newline t "*True means automatically newline after semicolons." :group 'verilog-mode-indent :type 'boolean) (defcustom verilog-auto-indent-on-newline t "*True means automatically indent line after newline." :group 'verilog-mode-indent :type 'boolean) (defcustom verilog-tab-always-indent t "*True means TAB should always re-indent the current line. Nil means TAB will only reindent when at the beginning of the line." :group 'verilog-mode-indent :type 'boolean) (defcustom verilog-tab-to-comment nil "*True means TAB moves to the right hand column in preparation for a comment." :group 'verilog-mode-actions :type 'boolean) (defcustom verilog-indent-begin-after-if t "*If true, indent begin statements following if, else, while, for and repeat. Otherwise, line them up." :group 'verilog-mode-indent :type 'boolean ) (defcustom verilog-align-ifelse nil "*If true, align `else' under matching `if'. Otherwise else is lined up with first character on line holding matching if." :group 'verilog-mode-indent :type 'boolean ) (defcustom verilog-minimum-comment-distance 10 "*Minimum distance (in lines) between begin and end required before a comment. Setting this variable to zero results in every end acquiring a comment; the default avoids too many redundant comments in tight quarters" :group 'verilog-mode-indent :type 'integer) (defcustom verilog-auto-lineup '(declaration) "*If this list contains the symbol 'all', then all line ups described below are done. If this list contains the symbol 'declaration', then declarations are lined up with any preceding declarations, taking into account widths and the like, so for example the code: reg [31:0] a; reg b; would become reg [31:0] a; reg b; If this list contains the symbol 'assignment', then assignments are lined up with any preceding assignments, so for example the code a_long_variable = b + c; d = e + f; would become a_long_variable = b + c; d = e + f;" ;; The following is not implemented: ;If this list contains the symbol 'case', then case items are lined up ;with any preceding case items, so for example the code ; case (a) begin ; a_long_state : a = 3; ; b: a = 4; ; endcase ;would become ; case (a) begin ; a_long_state : a = 3; ; b : a = 4; ; endcase ; :group 'verilog-mode-indent :type 'list ) (defcustom verilog-auto-endcomments t "*True means insert a comment /* ... */ after 'end's. The name of the function or case will be set between the braces." :group 'verilog-mode-actions :type 'boolean ) (defcustom verilog-auto-read-includes nil "*True means do a `verilog-read-defines' and `verilog-read-includes' before each AUTO expansion. This makes it easier to embed defines and includes, but can result in very slow reading times if there are many or large include files." :group 'verilog-mode-actions :type 'boolean ) (defcustom verilog-auto-save-policy nil "*Non-nil indicates action to take when saving a Verilog buffer with AUTOs. A value of `force' will always do a \\[verilog-auto] automatically if needed on every save. A value of `detect' will do \\[verilog-auto] automatically when it thinks necessary. A value of `ask' will query the user when it thinks updating is needed. You should not rely on the 'ask or 'detect policies, they are safeguards only. They do not detect when AUTOINSTs need to be updated because a sub-module's port list has changed." :group 'verilog-mode-actions :type '(choice (const nil) (const ask) (const detect) (const force))) (defcustom verilog-auto-star-expand t "*Non-nil indicates to expand a SystemVerilog .* instance ports. They will be expanded in the same way as if there was a AUTOINST in the instantiation. See also `verilog-auto-star' and `verilog-auto-star-save'." :group 'verilog-mode-actions :type 'boolean) (defcustom verilog-auto-star-save nil "*Non-nil indicates to save to disk SystemVerilog .* instance expansions. Nil indicates direct connections will be removed before saving. Only meaningful to those created due to `verilog-auto-star-expand' being set. Instead of setting this, you may want to use /*AUTOINST*/, which will always be saved." :group 'verilog-mode-actions :type 'boolean) (defvar verilog-auto-update-tick nil "Modification tick at which autos were last performed.") (defvar verilog-auto-last-file-locals nil "Text from file-local-variables during last evaluation.") (defvar verilog-error-regexp-add-didit nil) (defvar verilog-error-regexp nil) (setq verilog-error-regexp-add-didit nil verilog-error-regexp '( ; SureLint ;; ("[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 1 2) ; Most SureFire tools ("\\(WARNING\\|ERROR\\|INFO\\)[^:]*: \\([^,]+\\), \\(line \\|\\)\\([0-9]+\\):" 2 4 ) ("\ \\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\ :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5) ; xsim ; Error! in file /homes/mac/Axis/Xsim/test.v at line 13 [OBJ_NOT_DECLARED] ("\\(Error\\|Warning\\).*in file (\\([^ \t]+\\) at line *\\([0-9]+\\))" 2 3) ; vcs ("\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 2 3) ("Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 2) ("\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 2 3) ("syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 1 2) ; Verilator ("%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 3 4) ("%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 3 4) ; vxl ("\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 3) ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+\\([0-9]+\\):.*$" 1 2) ; vxl ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+line[ \t]+\\([0-9]+\\):.*$" 1 2) ; nc-verilog (".*\\*[WE],[0-9A-Z]+ (\\([^ \t,]+\\),\\([0-9]+\\)|" 1 2) ; Leda ("In file \\([^ \t]+\\)[ \t]+line[ \t]+\\([0-9]+\\):\n[^\n]*\n[^\n]*\n\\[\\(Warning\\|Error\\|Failure\\)\\][^\n]*" 1 2) ) ; "*List of regexps for verilog compilers, like verilint. See compilation-error-regexp-alist for the formatting." ) (defvar verilog-error-font-lock-keywords '( ("[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 1 bold t) ("[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 2 bold t) ("\\(WARNING\\|ERROR\\|INFO\\): \\([^,]+\\), line \\([0-9]+\\):" 2 bold t) ("\\(WARNING\\|ERROR\\|INFO\\): \\([^,]+\\), line \\([0-9]+\\):" 3 bold t) ("\ \\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\ :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 bold t) ("\ \\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\ :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 bold t) ("\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 2 bold t) ("\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 3 bold t) ("%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 3 bold t) ("%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 4 bold t) ("Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 bold t) ("Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 bold t) ("\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 2 bold t) ("\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 3 bold t) ("syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 1 bold t) ("syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 2 bold t) ; vxl ("\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 bold t) ("\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 bold t) ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+\\([0-9]+\\):.*$" 1 bold t) ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+\\([0-9]+\\):.*$" 2 bold t) ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+line[ \t]+\\([0-9]+\\):.*$" 1 bold t) ("([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+line[ \t]+\\([0-9]+\\):.*$" 2 bold t) ; nc-verilog (".*[WE],[0-9A-Z]+ (\\([^ \t,]+\\),\\([0-9]+\\)|" 1 bold t) (".*[WE],[0-9A-Z]+ (\\([^ \t,]+\\),\\([0-9]+\\)|" 2 bold t) ; Leda ("In file \\([^ \t]+\\)[ \t]+line[ \t]+\\([0-9]+\\):\n[^\n]*\n[^\n]*\n\\[\\(Warning\\|Error\\|Failure\\)\\][^\n]*" 1 bold t) ("In file \\([^ \t]+\\)[ \t]+line[ \t]+\\([0-9]+\\):\n[^\n]*\n[^\n]*\n\\[\\(Warning\\|Error\\|Failure\\)\\][^\n]*" 2 bold t) ) "*Keywords to also highlight in Verilog *compilation* buffers." ) (defcustom verilog-library-flags '("") "*List of standard Verilog arguments to use for /*AUTOINST*/. These arguments are used to find files for `verilog-auto', and match the flags accepted by a standard Verilog-XL simulator. -f filename Reads more `verilog-library-flags' from the filename. +incdir+dir Adds the directory to `verilog-library-directories'. -Idir Adds the directory to `verilog-library-directories'. -y dir Adds the directory to `verilog-library-directories'. +libext+.v Adds the extensions to `verilog-library-extensions'. -v filename Adds the filename to `verilog-library-files'. You might want these defined in each file; put at the *END* of your file something like: // Local Variables: // verilog-library-flags:(\"-y dir -y otherdir\") // End: Verilog-mode attempts to detect changes to this local variable, but they are only insured to be correct when the file is first visited. Thus if you have problems, use \\[find-alternate-file] RET to have these take effect. See also the variables mentioned above." :group 'verilog-mode-auto :type '(repeat string)) (defcustom verilog-library-directories '(".") "*List of directories when looking for files for /*AUTOINST*/. The directory may be relative to the current file, or absolute. Environment variables are also expanded in the directory names. Having at least the current directory is a good idea. You might want these defined in each file; put at the *END* of your file something like: // Local Variables: // verilog-library-directories:(\".\" \"subdir\" \"subdir2\") // End: Verilog-mode attempts to detect changes to this local variable, but they are only insured to be correct when the file is first visited. Thus if you have problems, use \\[find-alternate-file] RET to have these take effect. See also `verilog-library-flags', `verilog-library-files' and `verilog-library-extensions'." :group 'verilog-mode-auto :type '(repeat file)) (defcustom verilog-library-files '(".") "*List of files to search for modules when looking for AUTOINST files. This is a complete path, usually to a technology file with many standard cells defined in it. You might want these defined in each file; put at the *END* of your file something like: // Local Variables: // verilog-library-files:(\"/some/path/technology.v\" \"/some/path/tech2.v\") // End: Verilog-mode attempts to detect changes to this local variable, but they are only insured to be correct when the file is first visited. Thus if you have problems, use \\[find-alternate-file] RET to have these take effect. See also `verilog-library-flags', `verilog-library-directories'." :group 'verilog-mode-auto :type '(repeat directory)) (defcustom verilog-library-extensions '(".v") "*List of extensions to use when looking for files for /*AUTOINST*/. See also `verilog-library-flags', `verilog-library-directories'." :type '(repeat string) :group 'verilog-mode-auto) (defcustom verilog-active-low-regexp nil "*If set, treat signals matching this regexp as active low. This is used for AUTORESET and AUTOTIEOFF. For proper behavior, you will probably also need `verilog-auto-reset-widths' set." :group 'verilog-mode-auto :type 'string) (defcustom verilog-auto-sense-include-inputs nil "*If true, AUTOSENSE should include all inputs. If nil, only inputs that are NOT output signals in the same block are included." :type 'boolean :group 'verilog-mode-auto) (defcustom verilog-auto-sense-defines-constant nil "*If true, AUTOSENSE should assume all defines represent constants. When true, the defines will not be included in sensitivity lists. To maintain compatibility with other sites, this should be set at the bottom of each verilog file that requires it, rather then being set globally." :type 'boolean :group 'verilog-mode-auto) (defcustom verilog-auto-reset-widths t "*If true, AUTORESET should determine the width of signals. This is then used to set the width of the zero (32'h0 for example). This is required by some lint tools that aren't smart enough to ignore widths of the constant zero. This may result in ugly code when parameters determine the MSB or LSB of a signal inside a AUTORESET." :type 'boolean :group 'verilog-mode-auto) (defcustom verilog-assignment-delay "" "*Text used for delays in delayed assignments. Add a trailing space if set." :type 'string :group 'verilog-mode-auto) (defcustom verilog-auto-inst-vector t "*If true, when creating default ports with AUTOINST, use bus subscripts. If nil, skip the subscript when it matches the entire bus as declared in the module (AUTOWIRE signals always are subscripted, you must manually declare the wire to have the subscripts removed.) Nil may speed up some simulators, but is less general and harder to read, so avoid." :group 'verilog-mode-auto :type 'boolean ) (defcustom verilog-auto-inst-template-numbers nil "*If true, when creating templated ports with AUTOINST, add a comment. The comment will add the line number of the template that was used for that port declaration. Setting this aids in debugging, but nil is suggested for regular use to prevent large numbers of merge conflicts." :group 'verilog-mode-auto :type 'boolean ) (defvar verilog-auto-inst-column 40 "Column number for first part of auto-inst.") (defcustom verilog-auto-input-ignore-regexp nil "*If set, when creating AUTOINPUT list, ignore signals matching this regexp." :group 'verilog-mode-auto :type 'string ) (defcustom verilog-auto-inout-ignore-regexp nil "*If set, when creating AUTOINOUT list, ignore signals matching this regexp." :group 'verilog-mode-auto :type 'string ) (defcustom verilog-auto-output-ignore-regexp nil "*If set, when creating AUTOOUTPUT list, ignore signals matching this regexp." :group 'verilog-mode-auto :type 'string ) (defcustom verilog-typedef-regexp nil "*If non-nil, regular expression that matches Verilog-2001 typedef names. For example, \"_t$\" matches typedefs named with _t, as in the C language." :group 'verilog-mode-auto :type 'string ) (defcustom verilog-mode-hook 'verilog-set-compile-command "*Hook (List of functions) run after verilog mode is loaded." :type 'hook :group 'verilog-mode) (defcustom verilog-auto-hook nil "*Hook run after `verilog-mode' updates AUTOs." :type 'hook :group 'verilog-mode-auto) (defcustom verilog-before-auto-hook nil "*Hook run before `verilog-mode' updates AUTOs." :type 'hook :group 'verilog-mode-auto) (defcustom verilog-delete-auto-hook nil "*Hook run after `verilog-mode' deletes AUTOs." :type 'hook :group 'verilog-mode-auto) (defcustom verilog-before-delete-auto-hook nil "*Hook run before `verilog-mode' deletes AUTOs." :type 'hook :group 'verilog-mode-auto) (defvar verilog-imenu-generic-expression '((nil "^\\s-*\\(\\(m\\(odule\\|acromodule\\)\\)\\|primitive\\)\\s-+\\([a-zA-Z0-9_.:]+\\)" 4) ("*Vars*" "^\\s-*\\(reg\\|wire\\)\\s-+\\(\\|\\[[^]]+\\]\\s-+\\)\\([A-Za-z0-9_]+\\)" 3)) "Imenu expression for Verilog-mode. See `imenu-generic-expression'.") ;; ;; provide a verilog-header function. ;; Customization variables: ;; (defvar verilog-date-scientific-format nil "*If non-nil, dates are written in scientific format (e.g. 1997/09/17). If nil, in European format (e.g. 17.09.1997). The brain-dead American format (e.g. 09/17/1997) is not supported.") (defvar verilog-company nil "*Default name of Company for verilog header. If set will become buffer local.") (defvar verilog-project nil "*Default name of Project for verilog header. If set will become buffer local.") (define-abbrev-table 'verilog-mode-abbrev-table ()) (defvar verilog-mode-map () "Keymap used in Verilog mode.") (if verilog-mode-map () (setq verilog-mode-map (make-sparse-keymap)) (define-key verilog-mode-map ";" 'electric-verilog-semi) (define-key verilog-mode-map [(control 59)] 'electric-verilog-semi-with-comment) (define-key verilog-mode-map ":" 'electric-verilog-colon) ;;(define-key verilog-mode-map "=" 'electric-verilog-equal) (define-key verilog-mode-map "\`" 'electric-verilog-tick) (define-key verilog-mode-map "\t" 'electric-verilog-tab) (define-key verilog-mode-map "\r" 'electric-verilog-terminate-line) ;; backspace/delete key bindings (define-key verilog-mode-map [backspace] 'backward-delete-char-untabify) (unless (boundp 'delete-key-deletes-forward) ; XEmacs variable (define-key verilog-mode-map [delete] 'delete-char) (define-key verilog-mode-map [(meta delete)] 'kill-word)) (define-key verilog-mode-map "\M-\C-b" 'electric-verilog-backward-sexp) (define-key verilog-mode-map "\M-\C-f" 'electric-verilog-forward-sexp) (define-key verilog-mode-map "\M-\r" (function (lambda () (interactive) (electric-verilog-terminate-line 1)))) (define-key verilog-mode-map "\M-\t" 'verilog-complete-word) (define-key verilog-mode-map "\M-?" 'verilog-show-completions) (define-key verilog-mode-map [(meta control h)] 'verilog-mark-defun) (define-key verilog-mode-map "\C-c\`" 'verilog-lint-off) (define-key verilog-mode-map "\C-c\*" 'verilog-delete-auto-star-implicit) (define-key verilog-mode-map "\C-c\C-r" 'verilog-label-be) (define-key verilog-mode-map "\C-c\C-i" 'verilog-pretty-declarations) (define-key verilog-mode-map "\C-c=" 'verilog-pretty-expr) (define-key verilog-mode-map "\C-c\C-b" 'verilog-submit-bug-report) (define-key verilog-mode-map "\M-*" 'verilog-star-comment) (define-key verilog-mode-map "\C-c\C-c" 'verilog-comment-region) (define-key verilog-mode-map "\C-c\C-u" 'verilog-uncomment-region) (define-key verilog-mode-map "\M-\C-a" 'verilog-beg-of-defun) (define-key verilog-mode-map "\M-\C-e" 'verilog-end-of-defun) (define-key verilog-mode-map "\C-c\C-d" 'verilog-goto-defun) (define-key verilog-mode-map "\C-c\C-k" 'verilog-delete-auto) (define-key verilog-mode-map "\C-c\C-a" 'verilog-auto) (define-key verilog-mode-map "\C-c\C-s" 'verilog-auto-save-compile) (define-key verilog-mode-map "\C-c\C-z" 'verilog-inject-auto) (define-key verilog-mode-map "\C-c\C-e" 'verilog-expand-vector) (define-key verilog-mode-map "\C-c\C-h" 'verilog-header) ) ;; menus (defvar verilog-which-tool 1) (defvar verilog-xemacs-menu '("Verilog" ("Choose Compilation Action" ["Lint" (progn (setq verilog-tool 'verilog-linter) (setq verilog-which-tool 1) (verilog-set-compile-command)) :style radio :selected (= verilog-which-tool 1)] ["Coverage" (progn (setq verilog-tool 'verilog-coverage) (setq verilog-which-tool 2) (verilog-set-compile-command)) :style radio :selected (= verilog-which-tool 2)] ["Simulator" (progn (setq verilog-tool 'verilog-simulator) (setq verilog-which-tool 3) (verilog-set-compile-command)) :style radio :selected (= verilog-which-tool 3)] ["Compiler" (progn (setq verilog-tool 'verilog-compiler) (setq verilog-which-tool 4) (verilog-set-compile-command)) :style radio :selected (= verilog-which-tool 4)] ) ("Move" ["Beginning of function" verilog-beg-of-defun t] ["End of function" verilog-end-of-defun t] ["Mark function" verilog-mark-defun t] ["Goto function/module" verilog-goto-defun t] ["Move to beginning of block" electric-verilog-backward-sexp t] ["Move to end of block" electric-verilog-forward-sexp t] ) ("Comments" ["Comment Region" verilog-comment-region t] ["UnComment Region" verilog-uncomment-region t] ["Multi-line comment insert" verilog-star-comment t] ["Lint error to comment" verilog-lint-off t] ) "----" ["Compile" compile t] ["AUTO, Save, Compile" verilog-auto-save-compile t] ["Next Compile Error" next-error t] ["Ignore Lint Warning at point" verilog-lint-off t] "----" ["Line up declarations around point" verilog-pretty-declarations t] ["Line up equations around point" verilog-pretty-expr t] ["Redo/insert comments on every end" verilog-label-be t] ["Expand [x:y] vector line" verilog-expand-vector t] ["Insert begin-end block" verilog-insert-block t] ["Complete word" verilog-complete-word t] "----" ["Recompute AUTOs" verilog-auto t] ["Kill AUTOs" verilog-delete-auto t] ["Inject AUTOs" verilog-inject-auto t] ("AUTO Help..." ["AUTO General" (describe-function 'verilog-auto) t] ["AUTO Library Flags" (describe-variable 'verilog-library-flags) t] ["AUTO Library Path" (describe-variable 'verilog-library-directories) t] ["AUTO Library Files" (describe-variable 'verilog-library-files) t] ["AUTO Library Extensions" (describe-variable 'verilog-library-extensions) t] ["AUTO `define Reading" (describe-function 'verilog-read-defines) t] ["AUTO `include Reading" (describe-function 'verilog-read-includes) t] ["AUTOARG" (describe-function 'verilog-auto-arg) t] ["AUTOASCIIENUM" (describe-function 'verilog-auto-ascii-enum) t] ["AUTOINOUTMODULE" (describe-function 'verilog-auto-inout-module) t] ["AUTOINOUT" (describe-function 'verilog-auto-inout) t] ["AUTOINPUT" (describe-function 'verilog-auto-input) t] ["AUTOINST" (describe-function 'verilog-auto-inst) t] ["AUTOINST (.*)" (describe-function 'verilog-auto-star) t] ["AUTOOUTPUT" (describe-function 'verilog-auto-output) t] ["AUTOOUTPUTEVERY" (describe-function 'verilog-auto-output-every) t] ["AUTOREG" (describe-function 'verilog-auto-reg) t] ["AUTOREGINPUT" (describe-function 'verilog-auto-reg-input) t] ["AUTORESET" (describe-function 'verilog-auto-reset) t] ["AUTOSENSE" (describe-function 'verilog-auto-sense) t] ["AUTOTIEOFF" (describe-function 'verilog-auto-tieoff) t] ["AUTOUNUSED" (describe-function 'verilog-auto-unused) t] ["AUTOWIRE" (describe-function 'verilog-auto-wire) t] ) "----" ["Submit bug report" verilog-submit-bug-report t] ["Version and FAQ" verilog-faq t] ["Customize Verilog Mode..." verilog-customize t] ["Customize Verilog Fonts & Colors" verilog-font-customize t] ) "Emacs menu for VERILOG mode." ) (defvar verilog-statement-menu '("Statements" ["Header" verilog-sk-header t] ["Comment" verilog-sk-comment t] "----" ["Module" verilog-sk-module t] ["Primitive" verilog-sk-primitive t] "----" ["Input" verilog-sk-input t] ["Output" verilog-sk-output t] ["Inout" verilog-sk-inout t] ["Wire" verilog-sk-wire t] ["Reg" verilog-sk-reg t] ["Define thing under point as a register" verilog-sk-define-signal t] "----" ["Initial" verilog-sk-initial t] ["Always" verilog-sk-always t] ["Function" verilog-sk-function t] ["Task" verilog-sk-task t] ["Specify" verilog-sk-specify t] ["Generate" verilog-sk-generate t] "----" ["Begin" verilog-sk-begin t] ["If" verilog-sk-if t] ["(if) else" verilog-sk-else-if t] ["For" verilog-sk-for t] ["While" verilog-sk-while t] ["Fork" verilog-sk-fork t] ["Repeat" verilog-sk-repeat t] ["Case" verilog-sk-case t] ["Casex" verilog-sk-casex t] ["Casez" verilog-sk-casez t] ) "Menu for statement templates in Verilog." ) (easy-menu-define verilog-menu verilog-mode-map "Menu for Verilog mode" verilog-xemacs-menu) (easy-menu-define verilog-stmt-menu verilog-mode-map "Menu for statement templates in Verilog." verilog-statement-menu) (defvar verilog-mode-abbrev-table nil "Abbrev table in use in Verilog-mode buffers.") (define-abbrev-table 'verilog-mode-abbrev-table ()) ;; compilation program (defun verilog-set-compile-command () "Function to compute shell command to compile verilog. Can be the path and arguments for your Verilog simulator: \"vcs -p123 -O\" or a string like \"(cd /tmp; surecov %s)\". In the former case, the path to the current buffer is concat'ed to the value of verilog-tool; in the later, the path to the current buffer is substituted for the %s. Where __FILE__ appears in the string, the buffer-file-name of the current buffer, without the directory portion, will be substituted." (interactive) (cond ((or (file-exists-p "makefile") ;If there is a makefile, use it (file-exists-p "Makefile")) (make-local-variable 'compile-command) (setq compile-command "make ")) (t (make-local-variable 'compile-command) (setq compile-command (if (string-match "%s" (eval verilog-tool)) (format (eval verilog-tool) (or buffer-file-name "")) (concat (eval verilog-tool) " " (or buffer-file-name "")))) ) ) (verilog-modify-compile-command)) (defun verilog-modify-compile-command () "Replace meta-information in `compile-command'. Where __FILE__ appears in the string, the current buffer's file-name, without the directory portion, will be substituted." (when (string-match "\\b__FILE__\\b" compile-command) (make-local-variable 'compile-command) (setq compile-command (verilog-string-replace-matches "\\b__FILE__\\b" (file-name-nondirectory (buffer-file-name)) t t compile-command)))) (defun verilog-error-regexp-add () "Add the messages to the `compilation-error-regexp-alist'. Called by `compilation-mode-hook'. This allows \\[next-error] to find the errors." (if (not verilog-error-regexp-add-didit) (progn (setq verilog-error-regexp-add-didit t) (setq-default compilation-error-regexp-alist (append verilog-error-regexp (default-value 'compilation-error-regexp-alist))) ;; Could be buffer local at this point; maybe also in let; change all three (setq compilation-error-regexp-alist (default-value 'compilation-error-regexp-alist)) (set (make-local-variable 'compilation-error-regexp-alist) (default-value 'compilation-error-regexp-alist)) ))) (add-hook 'compilation-mode-hook 'verilog-error-regexp-add) (defconst verilog-directive-re ;; "`case" "`default" "`define" "`define" "`else" "`endfor" "`endif" ;; "`endprotect" "`endswitch" "`endwhile" "`for" "`format" "`if" "`ifdef" ;; "`ifndef" "`include" "`let" "`protect" "`switch" "`timescale" ;; "`time_scale" "`undef" "`while" "\\<`\\(case\\|def\\(ault\\|ine\\(\\)?\\)\\|e\\(lse\\|nd\\(for\\|if\\|protect\\|switch\\|while\\)\\)\\|for\\(mat\\)?\\|i\\(f\\(def\\|ndef\\)?\\|nclude\\)\\|let\\|protect\\|switch\\|time\\(_scale\\|scale\\)\\|undef\\|while\\)\\>") (defconst verilog-directive-begin "\\<`\\(for\\|i\\(f\\|fdef\\|fndef\\)\\|switch\\|while\\)\\>") (defconst verilog-directive-middle "\\<`\\(else\\|default\\|case\\)\\>") (defconst verilog-directive-end "`\\(endfor\\|endif\\|endswitch\\|endwhile\\)\\>") (defconst verilog-directive-re-1 (concat "[ \t]*" verilog-directive-re)) ;; ;; Regular expressions used to calculate indent, etc. ;; (defconst verilog-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>") (defconst verilog-case-re "\\(\\\\|\\\\)") ;; Want to match ;; aa : ;; aa,bb : ;; a[34:32] : ;; a, ;; b : (defconst verilog-no-indent-begin-re "\\<\\(if\\|else\\|while\\|for\\|repeat\\|always\\|always_comb\\|always_ff\\|always_latch\\)\\>") (defconst verilog-ends-re ;; Parenthesis indicate type of keyword found (concat "\\(\\\\)\\|" ; 1 "\\(\\\\)\\|" ; 2 "\\(\\\\)\\|" ; 3 "\\(\\\\)\\|" ; 4 "\\(\\\\)\\|" ; 5 "\\(\\\\)\\|" ; 6 "\\(\\\\)\\|" ; 7 "\\(\\\\)\\|" ; 8 "\\(\\\\)\\|" ; 9 "\\(\\\\)\\|" ; 10 "\\(\\\\)\\|" ; 11 "\\(\\\\)" ; 12 )) (defconst verilog-autoindent-lines-re ;; Matches to names in this list cause auto-end-commentation ;; ;; "macromodule" "module" "primitive" "interface" "end" "endcase" "endfunction" ;; "endtask" "endmodule" "endprimitive" "endinterface" "endspecify" "endtable" "join" ;; "begin" "else" `{directives} (concat "\\(" verilog-directive-re "\\|\\(\\\\|" "e\\(lse\\>\\|nd\\(\\>\\|c\\(ase\\|lass\\)\\>\\|covergroup\\>\\|function\\>\\|module\\>\\|program\\>\\|primitive\\>\\|interface\\>\\|package\\>" "\\|specify\\>\\|ta\\(ble\\>\\|sk\\>\\)\\)\\)\\|" "join\\(_any\\|_none\\)?\\>\\|m\\(acromodule\\>\\|odule\\>\\)\\|primitive\\>\\|interface\\>\\|package\\>\\)\\)" )) (defconst verilog-enders-re ;; Parenthesis indicate type of keyword found (concat "\\(\\\\)\\|" ; 1 "\\(\\\\)\\|" ; 2 "\\(\\\\)")) (defconst verilog-endcomment-reason-re ;; Parenthesis indicate type of keyword found (concat "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\.*\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\(\[ \t\]*@\\)?\\)\\|" "\\(\\\\(\[ \t\]*@\\)?\\)\\|" "\\(\\\\(\[ \t\]*@\\)?\\)\\|" "\\(\\\\(\[ \t\]*@\\)?\\)\\|" "\\(@\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|" "\\(\\\\)\\|\\(\\\\)\\|" "#")) (defconst verilog-named-block-re "begin[ \t]*:") ;; These words begin a block which can occur inside a module which should be indented, ;; and closed with the respective word from the end-block list (defconst verilog-beg-block-re (eval-when-compile (verilog-regexp-words `("begin" "case" "casex" "casez" "randcase" "generate" "fork" "function" "property" "specify" "table" "task")))) ;; These are the same words, in a specific order in the regular ;; expression so that matching will work nicely for ;; verilog-forward-sexp and verilog-calc-indent (defconst verilog-beg-block-re-ordered "\\<\\(begin\\)\\|\\(randcase\\|case[xz]?\\)\\|\\(fork\\)\\|\\(class\\)\\|\\(covergroup\\)\\|\\(table\\)\\|\\(specify\\)\\|\\(function\\)\\|\\(task\\)\\|\\(generate\\)\\|\\(property\\)\\>") (defconst verilog-end-block-re (eval-when-compile (verilog-regexp-words `("end" ;; closes begin "endcase" ;; closes any of case, casex casez or randcase "endclass" "join" "join_any" "join_none" ;; closes fork "endfunction" "endgenerate" "endproperty" "endspecify" "endtable" "endtask" ) ))) (defconst verilog-nameable-item-re (eval-when-compile (verilog-regexp-words `("begin" "fork" "join" "join_any" "join_none" "end" "endcase" "endconfig" "endclass" "endfunction" "endgenerate" "endmodule" "endprimative" "endinterface" "endpackage" "endspecify" "endtable" "endtask" ) ))) (defconst verilog-declaration-re (eval-when-compile (verilog-regexp-words `("assign" "defparam" "event" "inout" "input" "integer" "localparam" "output" "parameter" "real" "realtime" "reg" "supply" "supply0" "supply1" "time" "tri" "tri0" "tri1" "triand" "trior" "trireg" "wand" "wire" "typedef" "struct" "logic" "bit" "genvar" "wor")))) (defconst verilog-range-re "\\(\\[[^]]*\\]\\s-*\\)+") (defconst verilog-optional-signed-re "\\s-*\\(signed\\)?") (defconst verilog-optional-signed-range-re (concat "\\s-*\\(\\<\\(reg\\|wire\\)\\>\\s-*\\)?\\(\\\\s-*\\)?\\(" verilog-range-re "\\)?")) (defconst verilog-macroexp-re "`\\sw+") (defconst verilog-delay-re "#\\s-*\\(\\([0-9_]+\\('s?[hdxbo][0-9a-fA-F_xz]+\\)?\\)\\|\\(([^()]*)\\)\\|\\(\\sw+\\)\\)") (defconst verilog-declaration-re-2-no-macro (concat "\\s-*" verilog-declaration-re "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)" ; "\\|\\(" verilog-macroexp-re "\\)" "\\)?")) (defconst verilog-declaration-re-2-macro (concat "\\s-*" verilog-declaration-re "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)" "\\|\\(" verilog-macroexp-re "\\)" "\\)?")) (defconst verilog-declaration-re-1-macro (concat "^" verilog-declaration-re-2-macro)) ; (concat ; "^\\s-*\\<\\(in\\(?:out\\|put\\|teger\\)\\|output\\|re\\(?:al\\(?:time\\)?\\|g\\)\\|t\\(?:ime\\|ri\\(?:and\\|or\\|reg\\|[01]\\)?\\|ypedef\\)\\|w\\(?:and\\|ire\\|or\\)\\)\\>" ; "\\s-*" ; "\\(" ; "\\(" ; "\\(\\<\\(reg\\|wire\\)\\>\\s-*\\)?" ; "\\(\\\\s-*\\)?" ; "\\(\\(\\[[^]]*\\]\\)+\\)?" ; "\\)" ; "\\|" ; "\\(#\\s-*\\(" ; "\\([0-9_]+\\('s?[hdxbo][0-9a-fA-F_xz]+\\)?\\)" ; "\\|\\(([^()]*)\\)" ; "\\|\\(\\sw+\\)" ; "\\)" ; "\\)" ; "\\|\\(`\\sw+\\)\\)?" ; )) (defconst verilog-declaration-re-1-no-macro (concat "^" verilog-declaration-re-2-no-macro)) (defconst verilog-defun-re (eval-when-compile (verilog-regexp-words `("macromodule" "module" "class" "program" "interface" "package" "primitive" "config")))) (defconst verilog-end-defun-re (eval-when-compile (verilog-regexp-words `("endmodule" "endclass" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig")))) (defconst verilog-zero-indent-re (concat verilog-defun-re "\\|" verilog-end-defun-re)) (defconst verilog-behavioral-block-beg-re (concat "\\(\\\\|\\\\|\\\\|\\\\|\\\\|" "\\\\|\\\\|\\\\)")) (defconst verilog-indent-re (eval-when-compile (verilog-regexp-words `( "always" "always_latch" "always_ff" "always_comb" "begin" "end" "case" "casex" "casez" "randcase" "endcase" "class" "endclass" "config" "endconfig" "covergroup" "endgroup" "fork" "join" "join_any" "join_none" "function" "endfunction" "final" "generate" "endgenerate" "initial" "interface" "endinterface" "module" "macromodule" "endmodule" "package" "endpackage" "primitive" "endprimative" "program" "endprogram" "property" "endproperty" "specify" "endspecify" "table" "endtable" "task" "endtask" "`case" "`default" "`define" "`undef" "`if" "`ifdef" "`ifndef" "`else" "`endif" "`while" "`endwhile" "`for" "`endfor" "`format" "`include" "`let" "`protect" "`endprotect" "`switch" "`endswitch" "`timescale" "`time_scale" )))) (defconst verilog-defun-level-re (eval-when-compile (verilog-regexp-words `( "module" "macromodule" "primitive" "class" "program" "initial" "final" "always" "always_comb" "always_ff" "always_latch" "endtask" "endfunction" "interface" "package" "config")))) (defconst verilog-defun-level-not-generate-re (eval-when-compile (verilog-regexp-words `( "module" "macromodule" "primitive" "class" "program" "interface" "package" "config")))) (defconst verilog-cpp-level-re (eval-when-compile (verilog-regexp-words `( "endmodule" "endprimitive" "endinterface" "endpackage" "endprogram" "endclass" )))) (defconst verilog-behavioral-level-re ;; "function" "task" "\\(\\<\\(function\\>\\|task\\>\\)\\)") (defconst verilog-complete-reg (eval-when-compile (verilog-regexp-words `( "always" "assign" "always_latch" "always_ff" "always_comb" "extern" "initial" "final" "repeat" "case" "casex" "casez" "randcase" "while" "if" "for" "forever" "else" "parameter" "task" "function" "do" "foreach" )))) (defconst verilog-end-statement-re (concat "\\(" verilog-beg-block-re "\\)\\|\\(" verilog-end-block-re "\\)")) (defconst verilog-endcase-re (concat verilog-case-re "\\|" "\\(endcase\\)\\|" verilog-defun-re )) ;; Strings used to mark beginning and end of excluded text (defconst verilog-exclude-str-start "/* -----\\/----- EXCLUDED -----\\/-----") (defconst verilog-exclude-str-end " -----/\\----- EXCLUDED -----/\\----- */") (defconst verilog-keywords '( "`case" "`default" "`define" "`define" "`else" "`endfor" "`endif" "`endprotect" "`endswitch" "`endwhile" "`for" "`format" "`if" "`ifdef" "`ifndef" "`include" "`let" "`protect" "`switch" "`timescale" "`time_scale" "`undef" "`while" "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" "class" "clocking" "cmos" "config" "const" "constraint" "context" "continue" "cover" "covergroup" "coverpoint" "cross" "deassign" "default" "defparam" "design" "disable" "dist" "do" "edge" "else" "end" "endcase" "endclass" "endclocking" "endconfig" "endfunction" "endgenerate" "endgroup" "endinterface" "endmodule" "endpackage" "endprimitive" "endprogram" "endproperty" "endspecify" "endsequence" "endtable" "endtask" "enum" "event" "expect" "export" "extends" "extern" "final" "first_match" "for" "force" "foreach" "forever" "fork" "forkjoin" "function" "generate" "genvar" "highz0" "highz1" "if" "iff" "ifnone" "ignore_bins" "illegal_bins" "import" "incdir" "include" "initial" "inout" "input" "inside" "instance" "int" "integer" "interface" "intersect" "join" "join_any" "join_none" "large" "liblist" "library" "local" "localparam" "logic" "longint" "macromodule" "matches" "medium" "modport" "module" "nand" "negedge" "new" "nmos" "nor" "noshowcancelled" "not" "notif0" "notif1" "null" "or" "output" "package" "packed" "parameter" "pmos" "posedge" "primitive" "priority" "program" "property" "protected" "pull0" "pull1" "pulldown" "pullup" "pulsestyle_onevent" "pulsestyle_ondetect" "pure" "rand" "randc" "randcase" "randsequence" "rcmos" "real" "realtime" "ref" "reg" "release" "repeat" "return" "rnmos" "rpmos" "rtran" "rtranif0" "rtranif1" "scalared" "sequence" "shortint" "shortreal" "showcancelled" "signed" "small" "solve" "specify" "specparam" "static" "string" "strong0" "strong1" "struct" "super" "supply0" "supply1" "table" "tagged" "task" "this" "throughout" "time" "timeprecision" "timeunit" "tran" "tranif0" "tranif1" "tri" "tri0" "tri1" "triand" "trior" "trireg" "type" "typedef" "union" "unique" "unsigned" "use" "var" "vectored" "virtual" "void" "wait" "wait_order" "wand" "weak0" "weak1" "while" "wildcard" "wire" "with" "within" "wor" "xnor" "xor" ) "List of Verilog keywords.") (defconst verilog-emacs-features (let ((major (and (boundp 'emacs-major-version) emacs-major-version)) (minor (and (boundp 'emacs-minor-version) emacs-minor-version)) flavor comments flock-syntax) ;; figure out version numbers if not already discovered (and (or (not major) (not minor)) (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version) (setq major (string-to-int (substring emacs-version (match-beginning 1) (match-end 1))) minor (string-to-int (substring emacs-version (match-beginning 2) (match-end 2))))) (if (not (and major minor)) (error "Cannot figure out the major and minor version numbers")) ;; calculate the major version (cond ((= major 4) (setq major 'v18)) ;Epoch 4 ((= major 18) (setq major 'v18)) ;Emacs 18 ((= major 19) (setq major 'v19 ;Emacs 19 flavor (if (or (string-match "Lucid" emacs-version) (string-match "XEmacs" emacs-version)) 'XEmacs 'FSF))) ((> major 19) (setq major 'v20 flavor (if (or (string-match "Lucid" emacs-version) (string-match "XEmacs" emacs-version)) 'XEmacs 'FSF))) ;; I don't know (t (error "Cannot recognize major version number: %s" major))) ;; XEmacs 19 uses 8-bit modify-syntax-entry flags, as do all ;; patched Emacs 19, Emacs 18, Epoch 4's. Only Emacs 19 uses a ;; 1-bit flag. Let's be as smart as we can about figuring this ;; out. (if (or (eq major 'v20) (eq major 'v19)) (let ((table (copy-syntax-table))) (modify-syntax-entry ?a ". 12345678" table) (cond ;; XEmacs pre 20 and Emacs pre 19.30 use vectors for syntax tables. ((vectorp table) (if (= (logand (lsh (aref table ?a) -16) 255) 255) (setq comments '8-bit) (setq comments '1-bit))) ;; XEmacs 20 is known to be 8-bit ((eq flavor 'XEmacs) (setq comments '8-bit)) ;; Emacs 19.30 and beyond are known to be 1-bit ((eq flavor 'FSF) (setq comments '1-bit)) ;; Don't know what this is (t (error "Couldn't figure out syntax table format")) )) ;; Emacs 18 has no support for dual comments (setq comments 'no-dual-comments)) ;; determine whether to use old or new font lock syntax ;; We can assume 8-bit syntax table emacsen support new syntax, otherwise ;; look for version > 19.30 (setq flock-syntax (if (or (equal comments '8-bit) (equal major 'v20) (and (equal major 'v19) (> minor 30))) 'flock-syntax-after-1930 'flock-syntax-before-1930)) ;; lets do some minimal sanity checking. (if (or ;; Lemacs before 19.6 had bugs (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6)) ;; Emacs 19 before 19.21 has known bugs (and (eq major 'v19) (eq flavor 'FSF) (< minor 21)) ) (with-output-to-temp-buffer "*verilog-mode warnings*" (print (format "The version of Emacs that you are running, %s, has known bugs in its syntax parsing routines which will affect the performance of verilog-mode. You should strongly consider upgrading to the latest available version. verilog-mode may continue to work, after a fashion, but strange indentation errors could be encountered." emacs-version)))) ;; Emacs 18, with no patch is not too good (if (and (eq major 'v18) (eq comments 'no-dual-comments)) (with-output-to-temp-buffer "*verilog-mode warnings*" (print (format "The version of Emacs 18 you are running, %s, has known deficiencies in its ability to handle the dual verilog (and C++) comments, (e.g. the // and /* */ comments). This will not be much of a problem for you if you only use the /* */ comments, but you really should strongly consider upgrading to one of the latest Emacs 19's. In Emacs 18, you may also experience performance degradations. Emacs 19 has some new built-in routines which will speed things up for you. Because of these inherent problems, verilog-mode is not supported on emacs-18." emacs-version)))) ;; Emacs 18 with the syntax patches are no longer supported (if (and (eq major 'v18) (not (eq comments 'no-dual-comments))) (with-output-to-temp-buffer "*verilog-mode warnings*" (print (format "You are running a syntax patched Emacs 18 variant. While this should work for you, you may want to consider upgrading to Emacs 19. The syntax patches are no longer supported either for verilog-mode.")))) (list major comments flock-syntax)) "A list of features extant in the Emacs you are using. There are many flavors of Emacs out there, each with different features supporting those needed by `verilog-mode'. Here's the current supported list, along with the values for this variable: Vanilla Emacs 18/Epoch 4: (v18 no-dual-comments flock-syntax-before-1930) Emacs 18/Epoch 4 (patch2): (v18 8-bit flock-syntax-after-1930) XEmacs (formerly Lucid) 19: (v19 8-bit flock-syntax-after-1930) XEmacs 20: (v20 8-bit flock-syntax-after-1930) Emacs 19.1-19.30: (v19 8-bit flock-syntax-before-1930) Emacs 19.31-19.xx: (v19 8-bit flock-syntax-after-1930) Emacs20 : (v20 1-bit flock-syntax-after-1930).") (defconst verilog-comment-start-regexp "//\\|/\\*" "Dual comment value for `comment-start-regexp'.") (defun verilog-populate-syntax-table (table) "Populate the syntax TABLE." (modify-syntax-entry ?\\ "\\" table) (modify-syntax-entry ?+ "." table) (modify-syntax-entry ?- "." table) (modify-syntax-entry ?= "." table) (modify-syntax-entry ?% "." table) (modify-syntax-entry ?< "." table) (modify-syntax-entry ?> "." table) (modify-syntax-entry ?& "." table) (modify-syntax-entry ?| "." table) (modify-syntax-entry ?` "w" table) (modify-syntax-entry ?_ "w" table) (modify-syntax-entry ?\' "." table) ) (defun verilog-setup-dual-comments (table) "Set up TABLE to handle block and line style comments." (cond ((memq '8-bit verilog-emacs-features) ;; XEmacs (formerly Lucid) has the best implementation (modify-syntax-entry ?/ ". 1456" table) (modify-syntax-entry ?* ". 23" table) (modify-syntax-entry ?\n "> b" table) ) ((memq '1-bit verilog-emacs-features) ;; Emacs 19 does things differently, but we can work with it (modify-syntax-entry ?/ ". 124b" table) (modify-syntax-entry ?* ". 23" table) (modify-syntax-entry ?\n "> b" table) ) )) (defvar verilog-mode-syntax-table nil "Syntax table used in `verilog-mode' buffers.") (defconst verilog-font-lock-keywords nil "Default highlighting for Verilog mode.") (defconst verilog-font-lock-keywords-1 nil "Subdued level highlighting for Verilog mode.") (defconst verilog-font-lock-keywords-2 nil "Medium level highlighting for Verilog mode. See also `verilog-font-lock-extra-types'.") (defconst verilog-font-lock-keywords-3 nil "Gaudy level highlighting for Verilog mode. See also `verilog-font-lock-extra-types'.") (defvar verilog-font-lock-translate-off-face 'verilog-font-lock-translate-off-face "Font to use for translated off regions") (defface verilog-font-lock-translate-off-face '((((class color) (background light)) (:background "gray90" :italic t )) (((class color) (background dark)) (:background "gray10" :italic t )) (((class grayscale) (background light)) (:foreground "DimGray" :italic t)) (((class grayscale) (background dark)) (:foreground "LightGray" :italic t)) (t (:italis t))) "Font lock mode face used to background highlight translate-off regions." :group 'font-lock-highlighting-faces) (defvar verilog-font-lock-p1800-face 'verilog-font-lock-p1800-face "Font to use for p1800 keywords") (defface verilog-font-lock-p1800-face '((((class color) (background light)) (:foreground "DarkOrange3" :bold t )) (((class color) (background dark)) (:foreground "orange1" :bold t )) (t (:italic t))) "Font lock mode face used to highlight P1800 keywords." :group 'font-lock-highlighting-faces) (let* ((verilog-type-font-keywords (eval-when-compile (verilog-regexp-opt '( "and" "bit" "buf" "bufif0" "bufif1" "cmos" "defparam" "event" "genvar" "inout" "input" "integer" "localparam" "logic" "nand" "nmos" "not" "notif0" "notif1" "or" "output" "parameter" "pmos" "pull0" "pull1" "pullup" "rcmos" "real" "realtime" "reg" "rnmos" "rpmos" "rtran" "rtranif0" "rtranif1" "signed" "struct" "supply" "supply0" "supply1" "time" "tran" "tranif0" "tranif1" "tri" "tri0" "tri1" "triand" "trior" "trireg" "typedef" "vectored" "wand" "wire" "wor" "xnor" "xor" ) nil ))) (verilog-pragma-keywords (eval-when-compile (verilog-regexp-opt '("surefire" "synopsys" "rtl_synthesis" "verilint" ) nil ))) (verilog-p1800-keywords (eval-when-compile (verilog-regexp-opt '("alias" "assert" "assume" "automatic" "before" "bind" "bins" "binsof" "break" "byte" "cell" "chandle" "class" "clocking" "config" "const" "constraint" "context" "continue" "cover" "covergroup" "coverpoint" "cross" "deassign" "design" "dist" "do" "edge" "endclass" "endclocking" "endconfig" "endgroup" "endprogram" "endproperty" "endsequence" "enum" "expect" "export" "extends" "extern" "first_match" "foreach" "forkjoin" "genvar" "highz0" "highz1" "ifnone" "ignore_bins" "illegal_bins" "import" "incdir" "include" "inside" "instance" "int" "intersect" "large" "liblist" "library" "local" "longint" "matches" "medium" "modport" "new" "noshowcancelled" "null" "packed" "program" "property" "protected" "pull0" "pull1" "pulsestyle_onevent" "pulsestyle_ondetect" "pure" "rand" "randc" "randcase" "randsequence" "ref" "release" "return" "scalared" "sequence" "shortint" "shortreal" "showcancelled" "small" "solve" "specparam" "static" "string" "strong0" "strong1" "struct" "super" "tagged" "this" "throughout" "timeprecision" "timeunit" "type" "union" "unsigned" "use" "var" "virtual" "void" "wait_order" "weak0" "weak1" "wildcard" "with" "within" ) nil ))) (verilog-font-keywords (eval-when-compile (verilog-regexp-opt '( "assign" "begin" "case" "casex" "casez" "randcase" "deassign" "default" "disable" "else" "end" "endcase" "endfunction" "endgenerate" "endinterface" "endmodule" "endprimitive" "endspecify" "endtable" "endtask" "final" "for" "force" "return" "break" "continue" "forever" "fork" "function" "generate" "if" "iff" "initial" "interface" "join" "join_any" "join_none" "macromodule" "module" "negedge" "package" "endpackage" "always" "always_comb" "always_ff" "always_latch" "posedge" "primitive" "priority" "release" "repeat" "specify" "table" "task" "unique" "wait" "while" "class" "program" "endclass" "endprogram" ) nil )))) (setq verilog-font-lock-keywords (list ;; Fontify all builtin keywords (concat "\\<\\(" verilog-font-keywords "\\|" ;; And user/system tasks and functions "\\$[a-zA-Z][a-zA-Z0-9_\\$]*" "\\)\\>") ;; Fontify all types (cons (concat "\\<\\(" verilog-type-font-keywords "\\)\\>") 'font-lock-type-face) ;; Fontify IEEE-P1800 keywords (cons (concat "\\<\\(" verilog-p1800-keywords "\\)\\>") 'verilog-font-lock-p1800-face) )) (setq verilog-font-lock-keywords-1 (append verilog-font-lock-keywords (list ;; Fontify module definitions (list "\\<\\(\\(macro\\)?module\\|primitive\\|class\\|program\\|interface\\|package\\|task\\)\\>\\s-*\\(\\sw+\\)" '(1 font-lock-keyword-face) '(3 font-lock-function-name-face 'prepend)) ;; Fontify function definitions (list (concat "\\\\s-+\\(integer\\|real\\(time\\)?\\|time\\)\\s-+\\(\\sw+\\)" ) '(1 font-lock-keyword-face) '(3 font-lock-reference-face prepend) ) '("\\\\s-+\\(\\[[^]]+\\]\\)\\s-+\\(\\sw+\\)" (1 font-lock-keyword-face) (2 font-lock-reference-face append) ) '("\\\\s-+\\(\\sw+\\)" 1 'font-lock-reference-face append) ))) (setq verilog-font-lock-keywords-2 (append verilog-font-lock-keywords-1 (list ;; Fontify pragmas (concat "\\(//\\s-*" verilog-pragma-keywords "\\s-.*\\)") ;; Fontify escaped names '("\\(\\\\\\S-*\\s-\\)" 0 font-lock-function-name-face) ;; Fontify macro definitions/ uses '("`\\s-*[A-Za-z][A-Za-z0-9_]*" 0 font-lock-function-name-face) ;; Fontify delays/numbers '("\\(@\\)\\|\\(#\\s-*\\(\\(\[0-9_.\]+\\('s?[hdxbo][0-9a-fA-F_xz]*\\)?\\)\\|\\(([^()]+)\\|\\sw+\\)\\)\\)" 0 font-lock-type-face append) ;; Fontify instantiation names '("\\([A-Za-z][A-Za-z0-9_]+\\)\\s-*(" 1 font-lock-function-name-face) ))) (setq verilog-font-lock-keywords-3 (append verilog-font-lock-keywords-2 (when verilog-highlight-translate-off (list ;; Fontify things in translate off regions '(verilog-match-translate-off (0 'verilog-font-lock-translate-off-face prepend)) ))) ) ) (defun verilog-inside-comment-p () "Check if point inside a nested comment." (save-excursion (let ((st-point (point)) hitbeg) (or (search-backward "//" (verilog-get-beg-of-line) t) (if (progn ;; This is for tricky case //*, we keep searching if /* is proceeded by // on same line (while (and (setq hitbeg (search-backward "/*" nil t)) (progn (forward-char 1) (search-backward "//" (verilog-get-beg-of-line) t)))) hitbeg) (not (search-forward "*/" st-point t))))))) (defun verilog-declaration-end () (search-forward ";")) (defun verilog-point-text (&optional pointnum) "Return text describing where POINTNUM or current point is (for errors). Use filename, if current buffer being edited shorten to just buffer name." (concat (or (and (equal (window-buffer (selected-window)) (current-buffer)) (buffer-name)) buffer-file-name (buffer-name)) ":" (int-to-string (count-lines (point-min) (or pointnum (point)))))) (defun electric-verilog-backward-sexp () "Move backward over a sexp." (interactive) ;; before that see if we are in a comment (verilog-backward-sexp) ) (defun electric-verilog-forward-sexp () "Move backward over a sexp." (interactive) ;; before that see if we are in a comment (verilog-forward-sexp) ) (defun verilog-backward-sexp () (let ((reg) (elsec 1) (found nil) (st (point)) ) (if (not (looking-at "\\<")) (forward-word -1)) (cond ((verilog-skip-backward-comment-or-string) ) ((looking-at "\\") (setq reg (concat verilog-end-block-re "\\|\\(\\\\)" "\\|\\(\\\\)" )) (while (and (not found) (verilog-re-search-backward reg nil 'move)) (cond ((match-end 1) ; endblock ; try to leap back to matching outward block by striding across ; indent level changing tokens then immediately ; previous line governs indentation. (verilog-leap-to-head)) ((match-end 2) ; else, we're in deep (setq elsec (1+ elsec))) ((match-end 3) ; found it (setq elsec (1- elsec)) (if (= 0 elsec) ;; Now previous line describes syntax (setq found 't) )) ) ) ) ((looking-at verilog-end-block-re) (verilog-leap-to-head)) ((looking-at "\\(endmodule\\>\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)") (cond ((match-end 1) (verilog-re-search-backward "\\<\\(macro\\)?module\\>" nil 'move)) ((match-end 2) (verilog-re-search-backward "\\" nil 'move)) ((match-end 3) (verilog-re-search-backward "\\" nil 'move)) ((match-end 4) (verilog-re-search-backward "\\" nil 'move)) ((match-end 5) (verilog-re-search-backward "\\" nil 'move)) ((match-end 6) (verilog-re-search-backward "\\" nil 'move)) (t (goto-char st) (backward-sexp 1)))) (t (goto-char st) (backward-sexp)) ) ;; cond )) (defun verilog-forward-sexp () (let ((reg) (st (point))) (if (not (looking-at "\\<")) (forward-word -1)) (cond ((verilog-skip-forward-comment-or-string) (verilog-forward-syntactic-ws) ) ((looking-at verilog-beg-block-re-ordered);; begin|case|fork|class|table|specify|function|task|generate|covergroup|property (cond ((match-end 1) ; end ;; Search forward for matching begin (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 2) ; endcase ;; Search forward for matching case (setq reg "\\(\\\\|\\[^:]\\)\\|\\(\\\\)" )) ((match-end 3) ; join ;; Search forward for matching fork (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 4) ; endclass ;; Search forward for matching class (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 5) ; endtable ;; Search forward for matching table (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 6) ; endspecify ;; Search forward for matching specify (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 7) ; endfunction ;; Search forward for matching function (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 8) ; endtask ;; Search forward for matching task (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 9) ; endgenerate ;; Search forward for matching generate (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 10) ; endgroup ;; Search forward for matching covergroup (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 11) ; endproperty ;; Search forward for matching property (setq reg "\\(\\\\)\\|\\(\\\\)" )) ) (if (forward-word 1) (catch 'skip (let ((nest 1)) (while (verilog-re-search-forward reg nil 'move) (cond ((match-end 2) ; end (setq nest (1- nest)) (if (= 0 nest) (throw 'skip 1))) ((match-end 1) ; begin (setq nest (1+ nest))))) ))) ) ((looking-at "\\(\\<\\(macro\\)?module\\>\\)\\|\\(\\\\)\\|\\\\)\\|\\\\)\\|\\\\)\\|\\(\\\\)") (cond ((match-end 1) (verilog-re-search-forward "\\" nil 'move)) ((match-end 2) (verilog-re-search-forward "\\" nil 'move)) ((match-end 3) (verilog-re-search-forward "\\" nil 'move)) ((match-end 4) (verilog-re-search-forward "\\" nil 'move)) ((match-end 5) (verilog-re-search-forward "\\" nil 'move)) ((match-end 6) (verilog-re-search-forward "\\" nil 'move)) (t (goto-char st) (if (= (following-char) ?\) ) (forward-char 1) (forward-sexp 1))))) (t (goto-char st) (if (= (following-char) ?\) ) (forward-char 1) (forward-sexp 1))) ) ;; cond )) (defun verilog-declaration-beg () (verilog-re-search-backward verilog-declaration-re (bobp) t)) ;; ;; Macros ;; (defsubst verilog-string-replace-matches (from-string to-string fixedcase literal string) "Replace occurrences of FROM-STRING with TO-STRING. FIXEDCASE and LITERAL as in `replace-match`. STRING is what to replace. The case (verilog-string-replace-matches \"o\" \"oo\" nil nil \"foobar\") will break, as the o's continuously replace. xa -> x works ok though." ;; Hopefully soon to a emacs built-in (let ((start 0)) (while (string-match from-string string start) (setq string (replace-match to-string fixedcase literal string) start (min (length string) (match-end 0)))) string)) (defsubst verilog-string-remove-spaces (string) "Remove spaces surrounding STRING." (save-match-data (setq string (verilog-string-replace-matches "^\\s-+" "" nil nil string)) (setq string (verilog-string-replace-matches "\\s-+$" "" nil nil string)) string)) (defsubst verilog-re-search-forward (REGEXP BOUND NOERROR) ; checkdoc-params: (REGEXP BOUND NOERROR) "Like `re-search-forward', but skips over match in comments or strings." (store-match-data '(nil nil)) (while (and (re-search-forward REGEXP BOUND NOERROR) (and (verilog-skip-forward-comment-or-string) (progn (store-match-data '(nil nil)) (if BOUND (< (point) BOUND) t) )))) (match-end 0)) (defsubst verilog-re-search-backward (REGEXP BOUND NOERROR) ; checkdoc-params: (REGEXP BOUND NOERROR) "Like `re-search-backward', but skips over match in comments or strings." (store-match-data '(nil nil)) (while (and (re-search-backward REGEXP BOUND NOERROR) (and (verilog-skip-backward-comment-or-string) (progn (store-match-data '(nil nil)) (if BOUND (> (point) BOUND) t) )))) (match-end 0)) (defsubst verilog-re-search-forward-quick (regexp bound noerror) "Like `verilog-re-search-forward', including use of REGEXP BOUND and NOERROR, but trashes match data and is faster for REGEXP that doesn't match often. This may at some point use text properties to ignore comments, so there may be a large up front penalty for the first search." (let (pt) (while (and (not pt) (re-search-forward regexp bound noerror)) (if (not (verilog-inside-comment-p)) (setq pt (match-end 0)))) pt)) (defsubst verilog-re-search-backward-quick (regexp bound noerror) ; checkdoc-params: (REGEXP BOUND NOERROR) "Like `verilog-re-search-backward', including use of REGEXP BOUND and NOERROR, but trashes match data and is faster for REGEXP that doesn't match often. This may at some point use text properties to ignore comments, so there may be a large up front penalty for the first search." (let (pt) (while (and (not pt) (re-search-backward regexp bound noerror)) (if (not (verilog-inside-comment-p)) (setq pt (match-end 0)))) pt)) (defsubst verilog-get-beg-of-line (&optional arg) (save-excursion (beginning-of-line arg) (point))) (defsubst verilog-get-end-of-line (&optional arg) (save-excursion (end-of-line arg) (point))) (defsubst verilog-within-string () (save-excursion (nth 3 (parse-partial-sexp (verilog-get-beg-of-line) (point))))) (require 'font-lock) (defvar verilog-need-fld 1) (defvar font-lock-defaults-alist nil) ;In case we are XEmacs (defun verilog-font-lock-init () "Initialize fontification." ;; highlight keywords and standardized types, attributes, enumeration ;; values, and subprograms (setq verilog-font-lock-keywords-3 (append verilog-font-lock-keywords-2 (when verilog-highlight-translate-off (list ;; Fontify things in translate off regions '(verilog-match-translate-off (0 'verilog-font-lock-translate-off-face prepend)) )) ) ) (put 'verilog-mode 'font-lock-defaults '((verilog-font-lock-keywords verilog-font-lock-keywords-1 verilog-font-lock-keywords-2 verilog-font-lock-keywords-3 ) nil ;; nil means highlight strings & comments as well as keywords nil ;; nil means keywords must match case nil ;; syntax table handled elsewhere verilog-beg-of-defun ;; function to move to beginning of reasonable region to highlight )) (if verilog-need-fld (let ((verilog-mode-defaults '((verilog-font-lock-keywords verilog-font-lock-keywords-1 verilog-font-lock-keywords-2 verilog-font-lock-keywords-3 ) nil ;; nil means highlight strings & comments as well as keywords nil ;; nil means keywords must match case nil ;; syntax table handled elsewhere verilog-beg-of-defun ;; function to move to beginning of reasonable region to highlight ))) (setq font-lock-defaults-alist (append font-lock-defaults-alist (list (cons 'verilog-mode verilog-mode-defaults)))) (setq verilog-need-fld 0)))) ;; initialize fontification for Verilog Mode (verilog-font-lock-init) ;; ;; ;; Mode ;; ;;###autoload (defun verilog-mode () "Major mode for editing Verilog code. \\ NEWLINE, TAB indents for Verilog code. Delete converts tabs to spaces as it moves back. Supports highlighting. Use \\[verilog-faq] for a pointer to frequently asked questions. Variables controlling indentation/edit style: variable `verilog-indent-level' (default 3) Indentation of Verilog statements with respect to containing block. `verilog-indent-level-module' (default 3) Absolute indentation of Module level Verilog statements. Set to 0 to get initial and always statements lined up on the left side of your screen. `verilog-indent-level-declaration' (default 3) Indentation of declarations with respect to containing block. Set to 0 to get them list right under containing block. `verilog-indent-level-behavioral' (default 3) Indentation of first begin in a task or function block Set to 0 to get such code to lined up underneath the task or function keyword `verilog-indent-level-directive' (default 1) Indentation of `ifdef/`endif blocks `verilog-cexp-indent' (default 1) Indentation of Verilog statements broken across lines i.e.: if (a) begin `verilog-case-indent' (default 2) Indentation for case statements. `verilog-auto-newline' (default nil) Non-nil means automatically newline after semicolons and the punctuation mark after an end. `verilog-auto-indent-on-newline' (default t) Non-nil means automatically indent line after newline `verilog-tab-always-indent' (default t) Non-nil means TAB in Verilog mode should always reindent the current line, regardless of where in the line point is when the TAB command is used. `verilog-indent-begin-after-if' (default t) Non-nil means to indent begin statements following a preceding if, else, while, for and repeat statements, if any. otherwise, the begin is lined up with the preceding token. If t, you get: if (a) begin // amount of indent based on `verilog-cexp-indent' otherwise you get: if (a) begin `verilog-auto-endcomments' (default t) Non-nil means a comment /* ... */ is set after the ends which ends cases, tasks, functions and modules. The type and name of the object will be set between the braces. `verilog-minimum-comment-distance' (default 10) Minimum distance (in lines) between begin and end required before a comment will be inserted. Setting this variable to zero results in every end acquiring a comment; the default avoids too many redundant comments in tight quarters. `verilog-auto-lineup' (default `(all)) List of contexts where auto lineup of code should be done. Turning on Verilog mode calls the value of the variable `verilog-mode-hook' with no args, if that value is non-nil. Other useful functions are: \\[verilog-complete-word]\t-complete word with appropriate possibilities (functions, verilog keywords...) \\[verilog-comment-region]\t- Put marked area in a comment, fixing nested comments. \\[verilog-uncomment-region]\t- Uncomment an area commented with \ \\[verilog-comment-region]. \\[verilog-insert-block]\t- insert begin ... end; \\[verilog-star-comment]\t- insert /* ... */ \\[verilog-mark-defun]\t- Mark function. \\[verilog-beg-of-defun]\t- Move to beginning of current function. \\[verilog-end-of-defun]\t- Move to end of current function. \\[verilog-label-be]\t- Label matching begin ... end, fork ... join and case ... endcase statements; \\[verilog-sk-always] Insert a always @(AS) begin .. end block \\[verilog-sk-begin] Insert a begin .. end block \\[verilog-sk-case] Insert a case block, prompting for details \\[verilog-sk-else] Insert an else begin .. end block \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for details \\[verilog-sk-generate] Insert a generate .. endgenerate block \\[verilog-sk-header] Insert a nice header block at the top of file \\[verilog-sk-initial] Insert an initial begin .. end block \\[verilog-sk-fork] Insert a fork begin .. end .. join block \\[verilog-sk-module] Insert a module .. (/*AUTOARG*/);.. endmodule block \\[verilog-sk-primitive] Insert a primitive .. (.. );.. endprimitive block \\[verilog-sk-interface] Insert an interface .. (.. );.. endinterface block \\[verilog-sk-repeat] Insert a repeat (..) begin .. end block \\[verilog-sk-specify] Insert a specify .. endspecify block \\[verilog-sk-task] Insert a task .. begin .. end endtask block \\[verilog-sk-while] Insert a while (...) begin .. end block, prompting for details \\[verilog-sk-casex] Insert a casex (...) item: begin.. end endcase block, prompting for details \\[verilog-sk-casez] Insert a casez (...) item: begin.. end endcase block, prompting for details \\[verilog-sk-if] Insert an if (..) begin .. end block \\[verilog-sk-else-if] Insert an else if (..) begin .. end block \\[verilog-sk-comment] Insert a comment block \\[verilog-sk-assign] Insert an assign .. = ..; statement \\[verilog-sk-function] Insert a function .. begin .. end endfunction block \\[verilog-sk-input] Insert an input declaration, prompting for details \\[verilog-sk-output] Insert an output declaration, prompting for details \\[verilog-sk-state-machine] Insert a state machine definition, prompting for details! \\[verilog-sk-inout] Insert an inout declaration, prompting for details \\[verilog-sk-wire] Insert a wire declaration, prompting for details \\[verilog-sk-reg] Insert a register declaration, prompting for details \\[verilog-sk-define-signal] Define signal under point as a register at the top of the module" (interactive) (kill-all-local-variables) (use-local-map verilog-mode-map) (setq major-mode 'verilog-mode) (setq mode-name "Verilog") (setq local-abbrev-table verilog-mode-abbrev-table) (setq verilog-mode-syntax-table (make-syntax-table)) (verilog-populate-syntax-table verilog-mode-syntax-table) ;; add extra comment syntax (verilog-setup-dual-comments verilog-mode-syntax-table) (set-syntax-table verilog-mode-syntax-table) (make-local-variable 'indent-line-function) (setq indent-line-function 'verilog-indent-line-relative) (setq comment-indent-function 'verilog-comment-indent) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments nil) (make-local-variable 'comment-start) (make-local-variable 'comment-end) (make-local-variable 'comment-multi-line) (make-local-variable 'comment-start-skip) (setq comment-start "// " comment-end "" comment-start-skip "/\\*+ *\\|// *" comment-multi-line nil) ;; Set up for compilation (setq verilog-which-tool 1) (setq verilog-tool 'verilog-linter) (verilog-set-compile-command) (when (boundp 'hack-local-variables-hook) ;; Also modify any file-local-variables (add-hook 'hack-local-variables-hook 'verilog-modify-compile-command t)) ;; Setting up things for font-lock (if verilog-running-on-xemacs (progn (if (and current-menubar (not (assoc "Verilog" current-menubar))) (progn ;; (set-buffer-menubar (copy-sequence current-menubar)) (add-submenu nil verilog-xemacs-menu) (add-submenu nil verilog-stmt-menu) ) ) )) ;; Stuff for GNU emacs (make-local-variable 'font-lock-defaults) ;;------------------------------------------------------------ ;; now hook in 'verilog-colorize-include-files (eldo-mode.el&spice-mode.el) ;; all buffer local: (make-local-hook 'font-lock-mode-hook) (make-local-hook 'font-lock-after-fontify-buffer-hook); doesn't exist in emacs 20 (add-hook 'font-lock-mode-hook 'verilog-colorize-include-files-buffer t t) (add-hook 'font-lock-after-fontify-buffer-hook 'verilog-colorize-include-files-buffer t t) ; not in emacs 20 (make-local-hook 'after-change-functions) (add-hook 'after-change-functions 'verilog-colorize-include-files t t) ;; Tell imenu how to handle verilog. (make-local-variable 'imenu-generic-expression) (setq imenu-generic-expression verilog-imenu-generic-expression) ;; Stuff for autos (add-hook 'write-contents-hooks 'verilog-auto-save-check) ; already local (verilog-auto-reeval-locals t) ; Save locals in case user changes them (verilog-getopt-flags) (run-hooks 'verilog-mode-hook)) ;; ;; Electric functions ;; (defun electric-verilog-terminate-line (&optional arg) "Terminate line and indent next line. With optional ARG, remove existing end of line comments." (interactive) ;; before that see if we are in a comment (let ((state (save-excursion (parse-partial-sexp (point-min) (point))))) (cond ((nth 7 state) ; Inside // comment (if (eolp) (progn (delete-horizontal-space) (newline)) (progn (newline) (insert-string "// ") (beginning-of-line))) (verilog-indent-line)) ((nth 4 state) ; Inside any comment (hence /**/) (newline) (verilog-more-comment)) ((eolp) ;; First, check if current line should be indented (if (save-excursion (delete-horizontal-space) (beginning-of-line) (skip-chars-forward " \t") (if (looking-at verilog-autoindent-lines-re) (let ((indent-str (verilog-indent-line))) ;; Maybe we should set some endcomments (if verilog-auto-endcomments (verilog-set-auto-endcomments indent-str arg)) (end-of-line) (delete-horizontal-space) (if arg () (newline)) nil) (progn (end-of-line) (delete-horizontal-space) 't ) ) ) ;; see if we should line up assignments (progn (if (or (memq 'all verilog-auto-lineup) (memq 'assignments verilog-auto-lineup)) (verilog-pretty-expr) ) (newline) ) (forward-line 1) ) ;; Indent next line (if verilog-auto-indent-on-newline (verilog-indent-line)) ) (t (newline)) ))) (defun electric-verilog-semi () "Insert `;' character and reindent the line." (interactive) (insert last-command-char) (if (or (verilog-in-comment-or-string-p) (verilog-in-escaped-name-p)) () (save-excursion (beginning-of-line) (verilog-forward-ws&directives) (verilog-indent-line) ) (if (and verilog-auto-newline (not (verilog-parenthesis-depth))) (electric-verilog-terminate-line)))) (defun electric-verilog-semi-with-comment () "Insert `;' character, reindent the line and indent for comment." (interactive) (insert "\;") (save-excursion (beginning-of-line) (verilog-indent-line)) (indent-for-comment)) (defun electric-verilog-colon () "Insert `:' and do all indentations except line indent on this line." (interactive) (insert last-command-char) ;; Do nothing if within string. (if (or (verilog-within-string) (not (verilog-in-case-region-p))) () (save-excursion (let ((p (point)) (lim (progn (verilog-beg-of-statement) (point)))) (goto-char p) (verilog-backward-case-item lim) (verilog-indent-line))) ;; (let ((verilog-tab-always-indent nil)) ;; (verilog-indent-line)) )) ;;(defun electric-verilog-equal () ;; "Insert `=', and do indentation if within block." ;; (interactive) ;; (insert last-command-char) ;; Could auto line up expressions, but not yet ;; (if (eq (car (verilog-calculate-indent)) 'block) ;; (let ((verilog-tab-always-indent nil)) ;; (verilog-indent-command))) ;; ) (defun electric-verilog-tick () "Insert back-tick, and indent to column 0 if this is a CPP directive." (interactive) (insert last-command-char) (save-excursion (if (progn (beginning-of-line) (looking-at verilog-directive-re-1)) (verilog-indent-line)))) (defun electric-verilog-tab () "Function called when TAB is pressed in Verilog mode." (interactive) ;; If verilog-tab-always-indent, indent the beginning of the line. (if (or verilog-tab-always-indent (save-excursion (skip-chars-backward " \t") (bolp))) (let* ((oldpnt (point)) (boi-point (save-excursion (beginning-of-line) (skip-chars-forward " \t") (verilog-indent-line) (back-to-indentation) (point)))) (if (< (point) boi-point) (back-to-indentation) (cond ((not verilog-tab-to-comment)) ((not (eolp)) (end-of-line)) (t (indent-for-comment) (when (and (eolp) (= oldpnt (point))) ; kill existing comment (beginning-of-line) (re-search-forward comment-start-skip oldpnt 'move) (goto-char (match-beginning 0)) (skip-chars-backward " \t") (kill-region (point) oldpnt) )))) ) (progn (insert "\t")))) ;; ;; Interactive functions ;; (defun verilog-indent-buffer () "Indent-region the entire buffer as Verilog code." (interactive) (verilog-mode) (indent-region (point-min) (point-max) nil)) (defun verilog-insert-block () "Insert Verilog begin ... end; block in the code with right indentation." (interactive) (verilog-indent-line) (insert "begin") (electric-verilog-terminate-line) (save-excursion (electric-verilog-terminate-line) (insert "end") (beginning-of-line) (verilog-indent-line))) (defun verilog-star-comment () "Insert Verilog star comment at point." (interactive) (verilog-indent-line) (insert "/*") (save-excursion (newline) (insert " */")) (newline) (insert " * ")) (defun verilog-insert-indices (MAX) "Insert a set of indices at into the rectangle. The upper left corner is defined by the current point. Indices always begin with 0 and extend to the MAX - 1. If no prefix arg is given, the user is prompted for a value. The indices are surrounded by square brackets []. For example, the following code with the point located after the first 'a' gives: a = b a[ 0] = b a = b a[ 1] = b a = b a[ 2] = b a = b a[ 3] = b a = b ==> insert-indices ==> a[ 4] = b a = b a[ 5] = b a = b a[ 6] = b a = b a[ 7] = b a = b a[ 8] = b" (interactive "NMAX?") (save-excursion (let ((n 0)) (while (< n MAX) (save-excursion (insert (format "[%3d]" n))) (next-line 1) (setq n (1+ n)))))) (defun verilog-generate-numbers (MAX) "Insert a set of generated numbers into a rectangle. The upper left corner is defined by point. The numbers are padded to three digits, starting with 000 and extending to (MAX - 1). If no prefix argument is supplied, then the user is prompted for the MAX number. consider the following code fragment: buf buf buf buf000 buf buf buf buf001 buf buf buf buf002 buf buf buf buf003 buf buf ==> insert-indices ==> buf buf004 buf buf buf buf005 buf buf buf buf006 buf buf buf buf007 buf buf buf buf008" (interactive "NMAX?") (save-excursion (let ((n 0)) (while (< n MAX) (save-excursion (insert (format "%3.3d" n))) (next-line 1) (setq n (1+ n)))))) (defun verilog-mark-defun () "Mark the current verilog function (or procedure). This puts the mark at the end, and point at the beginning." (interactive) (push-mark (point)) (verilog-end-of-defun) (push-mark (point)) (verilog-beg-of-defun) (zmacs-activate-region)) (defun verilog-comment-region (start end) ; checkdoc-params: (start end) "Put the region into a Verilog comment. The comments that are in this area are \"deformed\": `*)' becomes `!(*' and `}' becomes `!{'. These deformed comments are returned to normal if you use \\[verilog-uncomment-region] to undo the commenting. The commented area starts with `verilog-exclude-str-start', and ends with `verilog-include-str-end'. But if you change these variables, \\[verilog-uncomment-region] won't recognize the comments." (interactive "r") (save-excursion ;; Insert start and endcomments (goto-char end) (if (and (save-excursion (skip-chars-forward " \t") (eolp)) (not (save-excursion (skip-chars-backward " \t") (bolp)))) (forward-line 1) (beginning-of-line)) (insert verilog-exclude-str-end) (setq end (point)) (newline) (goto-char start) (beginning-of-line) (insert verilog-exclude-str-start) (newline) ;; Replace end-comments within commented area (goto-char end) (save-excursion (while (re-search-backward "\\*/" start t) (replace-match "*-/" t t))) (save-excursion (let ((s+1 (1+ start))) (while (re-search-backward "/\\*" s+1 t) (replace-match "/-*" t t)))) )) (defun verilog-uncomment-region () "Uncomment a commented area; change deformed comments back to normal. This command does nothing if the pointer is not in a commented area. See also `verilog-comment-region'." (interactive) (save-excursion (let ((start (point)) (end (point))) ;; Find the boundaries of the comment (save-excursion (setq start (progn (search-backward verilog-exclude-str-start nil t) (point))) (setq end (progn (search-forward verilog-exclude-str-end nil t) (point)))) ;; Check if we're really inside a comment (if (or (equal start (point)) (<= end (point))) (message "Not standing within commented area.") (progn ;; Remove endcomment (goto-char end) (beginning-of-line) (let ((pos (point))) (end-of-line) (delete-region pos (1+ (point)))) ;; Change comments back to normal (save-excursion (while (re-search-backward "\\*-/" start t) (replace-match "*/" t t))) (save-excursion (while (re-search-backward "/-\\*" start t) (replace-match "/*" t t))) ;; Remove start comment (goto-char start) (beginning-of-line) (let ((pos (point))) (end-of-line) (delete-region pos (1+ (point))))))))) (defun verilog-beg-of-defun () "Move backward to the beginning of the current function or procedure." (interactive) (verilog-re-search-backward verilog-defun-re nil 'move)) (defun verilog-end-of-defun () "Move forward to the end of the current function or procedure." (interactive) (verilog-re-search-forward verilog-end-defun-re nil 'move)) (defun verilog-get-beg-of-defun (&optional warn) (save-excursion (cond ((verilog-re-search-forward-quick verilog-defun-re nil t) (point)) (t (error "%s: Can't find module beginning" (verilog-point-text)) (point-max))))) (defun verilog-get-end-of-defun (&optional warn) (save-excursion (cond ((verilog-re-search-forward-quick verilog-end-defun-re nil t) (point)) (t (error "%s: Can't find endmodule" (verilog-point-text)) (point-max))))) (defun verilog-label-be (&optional arg) "Label matching begin ... end, fork ... join and case ... endcase statements. With ARG, first kill any existing labels." (interactive) (let ((cnt 0) (oldpos (point)) (b (progn (verilog-beg-of-defun) (point-marker))) (e (progn (verilog-end-of-defun) (point-marker))) ) (goto-char (marker-position b)) (if (> (- e b) 200) (message "Relabeling module...")) (while (and (> (marker-position e) (point)) (verilog-re-search-forward (concat "\\" "\\|\\(`endif\\)\\|\\(`else\\)") nil 'move)) (goto-char (match-beginning 0)) (let ((indent-str (verilog-indent-line))) (verilog-set-auto-endcomments indent-str 't) (end-of-line) (delete-horizontal-space) ) (setq cnt (1+ cnt)) (if (= 9 (% cnt 10)) (message "%d..." cnt)) ) (goto-char oldpos) (if (or (> (- e b) 200) (> cnt 20)) (message "%d lines auto commented" cnt)) )) (defun verilog-beg-of-statement () "Move backward to beginning of statement." (interactive) (while (save-excursion (and (or (and (looking-at "\\") (save-excursion (verilog-backward-token) (looking-at "extern"))) (not (looking-at verilog-complete-reg))) (verilog-backward-syntactic-ws) (not (or (bolp) (= (preceding-char) ?\;))) )) (skip-chars-backward " \t") (verilog-backward-token)) (let ((last (point))) (while (progn (setq last (point)) (and (not (looking-at verilog-complete-reg)) (verilog-continued-line)))) (goto-char last) (verilog-forward-syntactic-ws))) (defun verilog-beg-of-statement-1 () "Move backward to beginning of statement." (interactive) (let ((pt (point))) (while (and (not (looking-at verilog-complete-reg)) (setq pt (point)) (verilog-backward-token) (not (looking-at verilog-complete-reg)) (verilog-backward-syntactic-ws) (setq pt (point)) (not (bolp)) (not (= (preceding-char) ?\;)))) ; (while (progn ; (setq pt (point)) ; (and (not (looking-at verilog-complete-reg)) ; (not (= (preceding-char) ?\;)) ; (verilog-continued-line)))) (goto-char pt) (verilog-forward-ws&directives))) (defun verilog-end-of-statement () "Move forward to end of current statement." (interactive) (let ((nest 0) pos) (or (looking-at verilog-beg-block-re) ;; Skip to end of statement (setq pos (catch 'found (while t (forward-sexp 1) (verilog-skip-forward-comment-or-string) (cond ((looking-at "[ \t]*;") (skip-chars-forward "^;") (forward-char 1) (throw 'found (point))) ((save-excursion (forward-sexp -1) (looking-at verilog-beg-block-re)) (goto-char (match-beginning 0)) (throw 'found nil)) ((eobp) (throw 'found (point)))))))) (if (not pos) ;; Skip a whole block (catch 'found (while t (verilog-re-search-forward verilog-end-statement-re nil 'move) (setq nest (if (match-end 1) (1+ nest) (1- nest))) (cond ((eobp) (throw 'found (point))) ((= 0 nest) (throw 'found (verilog-end-of-statement)))))) pos))) (defun verilog-in-case-region-p () "Return TRUE if in a case region; more specifically, point @ in the line foo : @ begin" (interactive) (save-excursion (if (and (progn (verilog-forward-syntactic-ws) (looking-at "\\")) (progn (verilog-backward-syntactic-ws) (= (preceding-char) ?\:))) (catch 'found (let ((nest 1)) (while t (verilog-re-search-backward (concat "\\(\\\\)\\|\\(\\\\|\\[^:]\\)\\|" "\\(\\\\)\\>") nil 'move) (cond ((match-end 3) (setq nest (1+ nest))) ((match-end 2) (if (= nest 1) (throw 'found 1)) (setq nest (1- nest))) (t (throw 'found (= nest 0))) )))) nil))) (defun verilog-in-struct-region-p () "Return TRUE if in a struct region; more specifically, in a list after a struct|union keyword" (interactive) (save-excursion (let* ((state (parse-partial-sexp (point-min) (point))) (depth (nth 0 state))) (if depth (progn (backward-up-list depth) (verilog-beg-of-statement) (looking-at "\\?\\s-*\\") ) ) ) ) ) (defun verilog-in-generate-region-p () "Return TRUE if in a generate region; more specifically, after a generate and before an endgenerate" (interactive) (let ((lim (save-excursion (verilog-beg-of-defun) (point))) (nest 1) ) (save-excursion (while (and (/= nest 0) (verilog-re-search-backward "\\<\\(generate\\)\\|\\(endgenerate\\)\\>" lim 'move) (cond ((match-end 1) ; generate (setq nest (1- nest))) ((match-end 2) ; endgenerate (setq nest (1+ nest))) )) )) (= nest 0) )) ; return nest (defun verilog-in-fork-region-p () "Return true if between a fork and join." (interactive) (let ((lim (save-excursion (verilog-beg-of-defun) (point))) (nest 1) ) (save-excursion (while (and (/= nest 0) (verilog-re-search-backward "\\<\\(fork\\)\\|\\(join\\(_any\\|_none\\)?\\)\\>" lim 'move) (cond ((match-end 1) ; fork (setq nest (1- nest))) ((match-end 2) ; join (setq nest (1+ nest))) )) )) (= nest 0) )) ; return nest (defun verilog-backward-case-item (lim) "Skip backward to nearest enclosing case item. Limit search to point LIM." (interactive) (let ((str 'nil) (lim1 (progn (save-excursion (verilog-re-search-backward verilog-endcomment-reason-re lim 'move) (point))))) ;; Try to find the real : (if (save-excursion (search-backward ":" lim1 t)) (let ((colon 0) b e ) (while (and (< colon 1) (verilog-re-search-backward "\\(\\[\\)\\|\\(\\]\\)\\|\\(:\\)" lim1 'move)) (cond ((match-end 1) ;; [ (setq colon (1+ colon)) (if (>= colon 0) (error "%s: unbalanced [" (verilog-point-text)))) ((match-end 2) ;; ] (setq colon (1- colon))) ((match-end 3) ;; : (setq colon (1+ colon))) )) ;; Skip back to beginning of case item (skip-chars-backward "\t ") (verilog-skip-backward-comment-or-string) (setq e (point)) (setq b (progn (if (verilog-re-search-backward "\\<\\(case[zx]?\\)\\>\\|;\\|\\" nil 'move) (progn (cond ((match-end 1) (goto-char (match-end 1)) (verilog-forward-ws&directives) (if (looking-at "(") (progn (forward-sexp) (verilog-forward-ws&directives))) (point)) (t (goto-char (match-end 0)) (verilog-forward-ws&directives) (point)) )) (error "Malformed case item") ))) (setq str (buffer-substring b e)) (if (setq e (string-match "[ \t]*\\(\\(\n\\)\\|\\(//\\)\\|\\(/\\*\\)\\)" str)) (setq str (concat (substring str 0 e) "..."))) str) 'nil))) ;; ;; Other functions ;; (defun kill-existing-comment () "Kill auto comment on this line." (save-excursion (let* ( (e (progn (end-of-line) (point))) (b (progn (beginning-of-line) (search-forward "//" e t)))) (if b (delete-region (- b 2) e))))) (defconst verilog-directive-nest-re (concat "\\(`else\\>\\)\\|" "\\(`endif\\>\\)\\|" "\\(`if\\>\\)\\|" "\\(`ifdef\\>\\)\\|" "\\(`ifndef\\>\\)")) (defun verilog-set-auto-endcomments (indent-str kill-existing-comment) "Add ending comment with given INDENT-STR. With KILL-EXISTING-COMMENT, remove what was there before. Insert `// case: 7 ' or `// NAME ' on this line if appropriate. Insert `// case expr ' if this line ends a case block. Insert `// ifdef FOO ' if this line ends code conditional on FOO. Insert `// NAME ' if this line ends a function, task, module, primitive or interface named NAME." (save-excursion (cond (; Comment close preprocessor directives (and (looking-at "\\(`endif\\)\\|\\(`else\\)") (or kill-existing-comment (not (save-excursion (end-of-line) (search-backward "//" (verilog-get-beg-of-line) t))))) (let ((nest 1) b e m (else (if (match-end 2) "!" " ")) ) (end-of-line) (if kill-existing-comment (kill-existing-comment)) (delete-horizontal-space) (save-excursion (backward-sexp 1) (while (and (/= nest 0) (verilog-re-search-backward verilog-directive-nest-re nil 'move)) (cond ((match-end 1) ; `else (if (= nest 1) (setq else "!"))) ((match-end 2) ; `endif (setq nest (1+ nest))) ((match-end 3) ; `if (setq nest (1- nest))) ((match-end 4) ; `ifdef (setq nest (1- nest))) ((match-end 5) ; `ifndef (setq nest (1- nest))) )) (if (match-end 0) (setq m (buffer-substring (match-beginning 0) (match-end 0)) b (progn (skip-chars-forward "^ \t") (verilog-forward-syntactic-ws) (point)) e (progn (skip-chars-forward "a-zA-Z0-9_") (point) )))) (if b (if (> (count-lines (point) b) verilog-minimum-comment-distance) (insert (concat " // " else m " " (buffer-substring b e)))) (progn (insert " // unmatched `else or `endif") (ding 't)) ))) (; Comment close case/class/function/task/module and named block (and (looking-at "\\") (setq str "randcase") (setq err nil) ) ((match-end 0) (goto-char (match-end 1)) (setq str (concat (buffer-substring (match-beginning 1) (match-end 1)) (verilog-get-expr))) (setq err nil)))) (end-of-line) (if kill-existing-comment (kill-existing-comment)) (delete-horizontal-space) (insert (concat " // " str )) (if err (ding 't)) )) (;- This is a begin..end block (match-end 2) ;; of verilog-enders-re (let ((str " // UNMATCHED !!") (err 't) (here (point)) there cntx ) (save-excursion (verilog-leap-to-head) (setq there (point)) (if (not (match-end 0)) (progn (goto-char here) (end-of-line) (if kill-existing-comment (kill-existing-comment)) (delete-horizontal-space) (insert str) (ding 't) ) (let ((lim (save-excursion (verilog-beg-of-defun) (point))) (here (point)) ) (cond (;-- handle named block differently (looking-at verilog-named-block-re) (search-forward ":") (setq there (point)) (setq str (verilog-get-expr)) (setq err nil) (setq str (concat " // block: " str ))) ((verilog-in-case-region-p) ;-- handle case item differently (goto-char here) (setq str (verilog-backward-case-item lim)) (setq there (point)) (setq err nil) (setq str (concat " // case: " str ))) (;- try to find "reason" for this begin (cond (; (eq here (progn (verilog-backward-token) (verilog-beg-of-statement-1) (point))) (setq err nil) (setq str "")) ((looking-at verilog-endcomment-reason-re) (setq there (match-end 0)) (setq cntx (concat (buffer-substring (match-beginning 0) (match-end 0)) " ")) (cond (;- begin (match-end 2) (setq err nil) (save-excursion (if (and (verilog-continued-line) (looking-at "\\\\|\\\\|\\")) (progn (goto-char (match-end 0)) (setq there (point)) (setq str (concat " // " (buffer-substring (match-beginning 0) (match-end 0)) " " (verilog-get-expr)))) (setq str "")))) (;- else (match-end 4) (let ((nest 0) ( reg "\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)") ) (catch 'skip (while (verilog-re-search-backward reg nil 'move) (cond ((match-end 1) ; begin (setq nest (1- nest))) ((match-end 2) ; end (setq nest (1+ nest))) ((match-end 3) (if (= 0 nest) (progn (goto-char (match-end 0)) (setq there (point)) (setq err nil) (setq str (verilog-get-expr)) (setq str (concat " // else: !if" str )) (throw 'skip 1)) ))) )))) (;- end else (match-end 5) (goto-char there) (let ((nest 0) ( reg "\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)") ) (catch 'skip (while (verilog-re-search-backward reg nil 'move) (cond ((match-end 1) ; begin (setq nest (1- nest))) ((match-end 2) ; end (setq nest (1+ nest))) ((match-end 3) (if (= 0 nest) (progn (goto-char (match-end 0)) (setq there (point)) (setq err nil) (setq str (verilog-get-expr)) (setq str (concat " // else: !if" str )) (throw 'skip 1)) ))) )))) (;- task/function/initial et cetera t (match-end 0) (goto-char (match-end 0)) (setq there (point)) (setq err nil) (setq str (verilog-get-expr)) (setq str (concat " // " cntx str ))) (;-- otherwise... (setq str " // auto-endcomment confused ")) )) ((and (verilog-in-case-region-p) ;-- handle case item differently (progn (setq there (point)) (goto-char here) (setq str (verilog-backward-case-item lim)))) (setq err nil) (setq str (concat " // case: " str ))) ((verilog-in-fork-region-p) (setq err nil) (setq str " // fork branch" )) ((looking-at "\\") ;; HERE (forward-word 1) (verilog-forward-syntactic-ws) (setq err nil) (setq str (verilog-get-expr)) (setq str (concat " // " cntx str ))) )))) (goto-char here) (end-of-line) (if kill-existing-comment (kill-existing-comment)) (delete-horizontal-space) (if (or err (> (count-lines here there) verilog-minimum-comment-distance)) (insert str)) (if err (ding 't)) )))) (;- this is endclass, which can be nested (match-end 11) ;; of verilog-enders-re ;;(goto-char there) (let ((nest 0) ( reg "\\<\\(class\\)\\|\\(endclass\\)\\|\\(package\\|primitive\\|\\(macro\\)?module\\)\\>") string ) (save-excursion (catch 'skip (while (verilog-re-search-backward reg nil 'move) (cond ((match-end 3) ; endclass (ding 't) (setq string "unmatched endclass") (throw 'skip 1)) ((match-end 2) ; endclass (setq nest (1+ nest))) ((match-end 1) ; class (setq nest (1- nest)) (if (< nest 0) (progn (goto-char (match-end 0)) (let (b e) (setq b (progn (skip-chars-forward "^ \t") (verilog-forward-ws&directives) (point)) e (progn (skip-chars-forward "a-zA-Z0-9_") (point))) (setq string (buffer-substring b e))) (throw 'skip 1)))) )))) (end-of-line) (insert (concat " // " string ))) ) (;- this is end{function,generate,task,module,primitive,table,generate} ;- which can not be nested. t (let (string reg (width nil)) (end-of-line) (if kill-existing-comment (save-match-data (kill-existing-comment))) (delete-horizontal-space) (backward-sexp) (cond ((match-end 5) ;; of verilog-enders-re (setq reg "\\(\\\\)\\|\\(\\<\\(endfunction\\|task\\|\\(macro\\)?module\\|primitive\\)\\>\\)") (setq width "\\(\\s-*\\(\\[[^]]*\\]\\)\\|\\(real\\(time\\)?\\)\\|\\(integer\\)\\|\\(time\\)\\)?") ) ((match-end 6) ;; of verilog-enders-re (setq reg "\\(\\\\)\\|\\(\\<\\(endtask\\|function\\|\\(macro\\)?module\\|primitive\\)\\>\\)")) ((match-end 7) ;; of verilog-enders-re (setq reg "\\(\\<\\(macro\\)?module\\>\\)\\|\\")) ((match-end 8) ;; of verilog-enders-re (setq reg "\\(\\\\)\\|\\(\\<\\(endprimitive\\|package\\|interface\\|\\(macro\\)?module\\)\\>\\)")) ((match-end 9) ;; of verilog-enders-re (setq reg "\\(\\\\)\\|\\(\\<\\(endinterface\\|package\\|primitive\\|\\(macro\\)?module\\)\\>\\)")) ((match-end 10) ;; of verilog-enders-re (setq reg "\\(\\\\)\\|\\(\\<\\(endpackage\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)")) ) (let (b e) (save-excursion (verilog-re-search-backward reg nil 'move) (cond ((match-end 1) (setq b (progn (skip-chars-forward "^ \t") (verilog-forward-ws&directives) (if (and width (looking-at width)) (progn (goto-char (match-end 0)) (verilog-forward-ws&directives) )) (point)) e (progn (skip-chars-forward "a-zA-Z0-9_") (point))) (setq string (buffer-substring b e))) (t (ding 't) (setq string "unmatched end(function|task|module|primitive|interface|package|class)"))))) (end-of-line) (insert (concat " // " string ))) )))))))))) (defun verilog-get-expr() "Grab expression at point, e.g, case ( a | b & (c ^d))" (let* ((b (progn (verilog-forward-syntactic-ws) (skip-chars-forward " \t") (point))) (e (let ((par 1)) (cond ((looking-at "@") (forward-char 1) (verilog-forward-syntactic-ws) (if (looking-at "(") (progn (forward-char 1) (while (and (/= par 0) (verilog-re-search-forward "\\((\\)\\|\\()\\)" nil 'move)) (cond ((match-end 1) (setq par (1+ par))) ((match-end 2) (setq par (1- par))))))) (point)) ((looking-at "(") (forward-char 1) (while (and (/= par 0) (verilog-re-search-forward "\\((\\)\\|\\()\\)" nil 'move)) (cond ((match-end 1) (setq par (1+ par))) ((match-end 2) (setq par (1- par))))) (point)) ((looking-at "\\[") (forward-char 1) (while (and (/= par 0) (verilog-re-search-forward "\\(\\[\\)\\|\\(\\]\\)" nil 'move)) (cond ((match-end 1) (setq par (1+ par))) ((match-end 2) (setq par (1- par))))) (verilog-forward-syntactic-ws) (skip-chars-forward "^ \t\n\f") (point)) ((looking-at "/[/\\*]") b) ('t (skip-chars-forward "^: \t\n\f") (point) )))) (str (buffer-substring b e))) (if (setq e (string-match "[ \t]*\\(\\(\n\\)\\|\\(//\\)\\|\\(/\\*\\)\\)" str)) (setq str (concat (substring str 0 e) "..."))) str)) (defun verilog-expand-vector () "Take a signal vector on the current line and expand it to multiple lines. Useful for creating tri's and other expanded fields." (interactive) (verilog-expand-vector-internal "[" "]")) (defun verilog-expand-vector-internal (bra ket) "Given BRA, the start brace and KET, the end brace, expand one line into many lines." (save-excursion (forward-line 0) (let ((signal-string (buffer-substring (point) (progn (end-of-line) (point))))) (if (string-match (concat "\\(.*\\)" (regexp-quote bra) "\\([0-9]*\\)\\(:[0-9]*\\|\\)\\(::[0-9---]*\\|\\)" (regexp-quote ket) "\\(.*\\)$") signal-string) (let* ((sig-head (match-string 1 signal-string)) (vec-start (string-to-int (match-string 2 signal-string))) (vec-end (if (= (match-beginning 3) (match-end 3)) vec-start (string-to-int (substring signal-string (1+ (match-beginning 3)) (match-end 3))))) (vec-range (if (= (match-beginning 4) (match-end 4)) 1 (string-to-int (substring signal-string (+ 2 (match-beginning 4)) (match-end 4))))) (sig-tail (match-string 5 signal-string)) vec) ;; Decode vectors (setq vec nil) (if (< vec-range 0) (let ((tmp vec-start)) (setq vec-start vec-end vec-end tmp vec-range (- vec-range)))) (if (< vec-end vec-start) (while (<= vec-end vec-start) (setq vec (append vec (list vec-start))) (setq vec-start (- vec-start vec-range))) (while (<= vec-start vec-end) (setq vec (append vec (list vec-start))) (setq vec-start (+ vec-start vec-range)))) ;; ;; Delete current line (delete-region (point) (progn (forward-line 0) (point))) ;; ;; Expand vector (while vec (insert (concat sig-head bra (int-to-string (car vec)) ket sig-tail "\n")) (setq vec (cdr vec))) (delete-char -1) ;; ))))) (defun verilog-strip-comments () "Strip all comments from the verilog code." (interactive) (goto-char (point-min)) (while (re-search-forward "//" nil t) (let ((bpt (- (point) 2))) (end-of-line) (delete-region bpt (point)))) ;; (goto-char (point-min)) (while (re-search-forward "/\\*" nil t) (let ((bpt (- (point) 2))) (re-search-forward "\\*/") (delete-region bpt (point))))) (defun verilog-one-line () "Convert structural verilog instances to occupy one line." (interactive) (goto-char (point-min)) (while (re-search-forward "\\([^;]\\)[ \t]*\n[ \t]*" nil t) (replace-match "\\1 " nil nil))) (defun verilog-linter-name () "Return name of linter, either surelint or verilint." (let ((compile-word1 (verilog-string-replace-matches "\\s .*$" "" nil nil compile-command)) (lint-word1 (verilog-string-replace-matches "\\s .*$" "" nil nil verilog-linter))) (cond ((equal compile-word1 "surelint") `surelint) ((equal compile-word1 "verilint") `verilint) ((equal lint-word1 "surelint") `surelint) ((equal lint-word1 "verilint") `verilint) (t `surelint)))) ;; back compatibility (defun verilog-lint-off () "Convert a Verilog linter warning line into a disable statement. For example: pci_bfm_null.v, line 46: Unused input: pci_rst_ becomes a comment for the appropriate tool. The first word of the `compile-command' or `verilog-linter' variables are used to determine which product is being used. See \\[verilog-surelint-off] and \\[verilog-verilint-off]." (interactive) (let ((linter (verilog-linter-name))) (cond ((equal linter `surelint) (verilog-surelint-off)) ((equal linter `verilint) (verilog-verilint-off)) (t (error "Linter name not set"))))) (defun verilog-surelint-off () "Convert a SureLint warning line into a disable statement. Run from Verilog source window; assumes there is a *compile* buffer with point set appropriately. For example: WARNING [STD-UDDONX]: xx.v, line 8: output out is never assigned. becomes: // surefire lint_line_off UDDONX" (interactive) (save-excursion (switch-to-buffer compilation-last-buffer) (beginning-of-line) (when (looking-at "\\(INFO\\|WARNING\\|ERROR\\) \\[[^-]+-\\([^]]+\\)\\]: \\([^,]+\\), line \\([0-9]+\\): \\(.*\\)$") (let* ((code (match-string 2)) (file (match-string 3)) (line (match-string 4)) (buffer (get-file-buffer file)) dir filename) (unless buffer (progn (setq buffer (and (file-exists-p file) (find-file-noselect file))) (or buffer (let* ((pop-up-windows t)) (let ((name (expand-file-name (read-file-name (format "Find this error in: (default %s) " file) dir file t)))) (if (file-directory-p name) (setq name (expand-file-name filename name))) (setq buffer (and (file-exists-p name) (find-file-noselect name)))))))) (switch-to-buffer buffer) (goto-line (string-to-number line)) (end-of-line) (catch 'already (cond ((verilog-in-slash-comment-p) (re-search-backward "//") (cond ((looking-at "// surefire lint_off_line ") (goto-char (match-end 0)) (let ((lim (save-excursion (end-of-line) (point)))) (if (re-search-forward code lim 'move) (throw 'already t) (insert-string (concat " " code))))) (t ))) ((verilog-in-star-comment-p) (re-search-backward "/\*") (insert-string (format " // surefire lint_off_line %6s" code )) ) (t (insert-string (format " // surefire lint_off_line %6s" code )) ))))))) (defun verilog-verilint-off () "Convert a Verilint warning line into a disable statement. For example: (W240) pci_bfm_null.v, line 46: Unused input: pci_rst_ becomes: //Verilint 240 off // WARNING: Unused input" (interactive) (save-excursion (beginning-of-line) (when (looking-at "\\(.*\\)([WE]\\([0-9A-Z]+\\)).*,\\s +line\\s +[0-9]+:\\s +\\([^:\n]+\\):?.*$") (replace-match (format ;; %3s makes numbers 1-999 line up nicely "\\1//Verilint %3s off // WARNING: \\3" (match-string 2))) (beginning-of-line) (verilog-indent-line)))) (defun verilog-auto-save-compile () "Update automatics with \\[verilog-auto], save the buffer, and compile." (interactive) (verilog-auto) ; Always do it for safety (save-buffer) (compile compile-command)) ;; ;; Batch ;; (defun verilog-batch-execute-func (funref) "Internal processing of a batch command, running FUNREF on all command arguments." ;; General globals needed (setq make-backup-files nil) (setq-default make-backup-files nil) (setq enable-local-variables t) (setq enable-local-eval t) ;; Make sure any sub-files we read get proper mode (setq default-major-mode `verilog-mode) ;; Ditto files already read in (mapcar '(lambda (buf) (when (buffer-file-name buf) (save-excursion (set-buffer buf) (verilog-mode)))) (buffer-list)) ;; Process the files (mapcar '(lambda (buf) (when (buffer-file-name buf) (save-excursion (message (concat "Processing " (buffer-file-name buf))) (set-buffer buf) (funcall funref) (save-buffer)))) (buffer-list))) (defun verilog-batch-auto () "For use with --batch, perform automatic expansions as a stand-alone tool. This sets up the appropriate Verilog-Mode environment, updates automatics with \\[verilog-auto] on all command-line files, and saves the buffers. For proper results, multiple filenames need to be passed on the command line in bottom-up order." (unless noninteractive (error "Use verilog-batch-auto only with --batch")) ;; Otherwise we'd mess up buffer modes (verilog-batch-execute-func `verilog-auto)) (defun verilog-batch-delete-auto () "For use with --batch, perform automatic deletion as a stand-alone tool. This sets up the appropriate Verilog-Mode environment, deletes automatics with \\[verilog-delete-auto] on all command-line files, and saves the buffers." (unless noninteractive (error "Use verilog-batch-delete-auto only with --batch")) ;; Otherwise we'd mess up buffer modes (verilog-batch-execute-func `verilog-delete-auto)) (defun verilog-batch-inject-auto () "For use with --batch, perform automatic injection as a stand-alone tool. This sets up the appropriate Verilog-Mode environment, injects new automatics with \\[verilog-inject-auto] on all command-line files, and saves the buffers. For proper results, multiple filenames need to be passed on the command line in bottom-up order." (unless noninteractive (error "Use verilog-batch-inject-auto only with --batch")) ;; Otherwise we'd mess up buffer modes (verilog-batch-execute-func `verilog-inject-auto)) ;; ;; Indentation ;; (defconst verilog-indent-alist '((block . (+ ind verilog-indent-level)) (case . (+ ind verilog-case-indent)) (cparenexp . (+ ind verilog-indent-level)) (cexp . (+ ind verilog-cexp-indent)) (defun . verilog-indent-level-module) (declaration . verilog-indent-level-declaration) (directive . (verilog-calculate-indent-directive)) (tf . verilog-indent-level) (behavioral . (+ verilog-indent-level-behavioral verilog-indent-level-module)) (statement . ind) (cpp . 0) (comment . (verilog-comment-indent)) (unknown . 3) (string . 0))) (defun verilog-continued-line-1 (lim) "Return true if this is a continued line. Set point to where line starts. Limit search to point LIM." (let ((continued 't)) (if (eq 0 (forward-line -1)) (progn (end-of-line) (verilog-backward-ws&directives lim) (if (bobp) (setq continued nil) (setq continued (verilog-backward-token)))) (setq continued nil)) continued)) (defun verilog-calculate-indent () "Calculate the indent of the current Verilog line. Examine previous lines. Once a line is found that is definitive as to the type of the current line, return that lines' indent level and its type. Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." (save-excursion (let* ((starting_position (point)) (par 0) (begin (looking-at "[ \t]*begin\\>")) (lim (save-excursion (verilog-re-search-backward "\\(\\\\)\\|\\(\\\\)" nil t))) (type (catch 'nesting ;; Keep working backwards until we can figure out ;; what type of statement this is. ;; Basically we need to figure out ;; 1) if this is a continuation of the previous line; ;; 2) are we in a block scope (begin..end) ;; if we are in a comment, done. (if (verilog-in-star-comment-p) (throw 'nesting 'comment)) ;; if we have a directive, done. (if (save-excursion (beginning-of-line) (looking-at verilog-directive-re-1)) (throw 'nesting 'directive)) ;; if we are in a parenthesized list, and the user likes to indent these, return. (if (verilog-in-paren) (if verilog-indent-lists (progn (setq par 1) (throw 'nesting 'block)) () ) ) ;; See if we are continuing a previous line (while t ;; trap out if we crawl off the top of the buffer (if (bobp) (throw 'nesting 'cpp)) (if (verilog-continued-line-1 lim) (let ((sp (point))) (if (and (not (looking-at verilog-complete-reg)) (verilog-continued-line-1 lim)) (progn (goto-char sp) (throw 'nesting 'cexp)) (goto-char sp)) (if (and begin (not verilog-indent-begin-after-if) (looking-at verilog-no-indent-begin-re)) (progn (beginning-of-line) (skip-chars-forward " \t") (throw 'nesting 'statement)) (progn (throw 'nesting 'cexp)))) ;; not a continued line (goto-char starting_position)) (if (looking-at "\\") ;; search back for governing if, striding across begin..end pairs ;; appropriately (let ((elsec 1)) (while (verilog-re-search-backward verilog-ends-re nil 'move) (cond ((match-end 1) ; else, we're in deep (setq elsec (1+ elsec))) ((match-end 2) ; if (setq elsec (1- elsec)) (if (= 0 elsec) (if verilog-align-ifelse (throw 'nesting 'statement) (progn ;; back up to first word on this line (beginning-of-line) (verilog-forward-syntactic-ws) (throw 'nesting 'statement))))) (t ; endblock ; try to leap back to matching outward block by striding across ; indent level changing tokens then immediately ; previous line governs indentation. (let (( reg) (nest 1)) ;; verilog-ends => else|if|end|join(_any|_none|)|endcase|endclass|endtable|endspecify|endfunction|endtask|endgenerate|endgroup (cond ((match-end 3) ; end ;; Search back for matching begin (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 4) ; endcase ;; Search back for matching case (setq reg "\\(\\\\|\\[^:]\\)\\|\\(\\\\)" )) ((match-end 5) ; endfunction ;; Search back for matching function (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 6) ; endtask ;; Search back for matching task (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 7) ; endspecify ;; Search back for matching specify (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 8) ; endtable ;; Search back for matching table (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 9) ; endgenerate ;; Search back for matching generate (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 10) ; joins ;; Search back for matching fork (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 11) ; class ;; Search back for matching class (setq reg "\\(\\\\)\\|\\(\\\\)" )) ((match-end 12) ; covergroup ;; Search back for matching covergroup (setq reg "\\(\\\\)\\|\\(\\\\)" )) ) (catch 'skip (while (verilog-re-search-backward reg nil 'move) (cond ((match-end 1) ; begin (setq nest (1- nest)) (if (= 0 nest) (throw 'skip 1))) ((match-end 2) ; end (setq nest (1+ nest))))) ) )) )))) (throw 'nesting (verilog-calc-1)) ) );; catch nesting );; type ) ;; Return type of block and indent level. (if (not type) (setq type 'cpp)) (if (> par 0) ; Unclosed Parenthesis (list 'cparenexp par) (cond ((eq type 'case) (list type (verilog-case-indent-level))) ((eq type 'statement) (list type (current-column))) ((eq type 'defun) (list type 0)) (t (list type (verilog-current-indent-level))))) ))) (defun verilog-wai () (interactive) (save-excursion (let ((nesting (verilog-calc-1))) (message "You are at nesting %s" nesting)))) (defun verilog-calc-1 () (catch 'nesting (while (verilog-re-search-backward verilog-indent-re nil 'move) (cond