;; bsv-mode.el --- major mode for editing bsv source in Emacs
;; Copyright (C) 1996-2012 Free Software Foundation, Inc.
;; Verilog Mode Author: Michael McNamara (mac@verilog.com),
;; Wilson Snyder (wsnyder@wsnyder.org)
;; Please see our web sites:
;; http://www.verilog.com
;; http://www.veripool.org
;;
;; Keywords: languages
;; This file is part of GNU Emacs.
;; GNU Emacs 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 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs 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 GNU Emacs. If not, see .
;;; Commentary:
;; This mode borrows heavily from the Pascal-mode and the cc-mode of Emacs
;; USAGE
;; =====
;; A major mode for editing BSV HDL source code. When you have
;; entered BSV mode, you may get more info by pressing C-h m. You
;; may also get online help describing various functions by: C-h f
;;
;; KNOWN BUGS / BUG REPORTS
;; =======================
;; This is beta code and likely has bugs.
;; Please report any issues to the BSC developers, by opening a ticket
;; in the issue database: https://github.com/B-Lang-org/bsc/issues
;; INSTALLING THE MODE
;; ===================
;; An older version of this mode may be already installed as a part of
;; your environment, and one method of updating would be to update
;; your Emacs environment. Sometimes this is difficult for local
;; political/control reasons, and hence you can always install a
;; private copy (or even a shared copy) which overrides the system
;; default.
;; 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 BSV 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 'bsv-mode "bsv-mode" "BSV mode" t )
; (setq auto-mode-alist (cons '("\\.bsv\\'" . bsv-mode) auto-mode-alist))
;; Be sure to examine at the help for bsv-auto, and the other
;; bsv-auto-* functions for some major coding time savers.
;;
;; If you want to customize BSV mode to fit your needs better,
;; you may add the below 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. If working as a member of a large team these settings
;; should be common across all users (in a site-start file), or set
;; in Local Variables in every file. Otherwise, different people's
;; AUTO expansion may result different whitespace changes.
;;
; ;; Enable syntax highlighting of **all** languages
; (global-font-lock-mode t)
;
; ;; User customization for BSV mode
; (setq bsv-indent-level 3
; bsv-indent-level-module 3
; bsv-indent-level-declaration 3
; bsv-indent-level-behavioral 3
; bsv-indent-level-directive 1
; bsv-case-indent 2
; bsv-auto-newline nil
; bsv-auto-indent-on-newline t
; bsv-tab-always-indent t
; bsv-auto-endcomments t
; bsv-minimum-comment-distance 40
; bsv-indent-begin-after-if t
; bsv-auto-lineup 'declarations
; bsv-highlight-p1800-keywords nil
; bsv-linter "my_lint_shell_command"
; )
;;
;;; History:
;;; Code:
(require 'cl)
;; This variable will always hold the version number of the mode
(defconst bsv-mode-version "725"
"Version of this BSV mode.")
(defconst bsv-mode-release-date "2011-11-27-GNU"
"Release date of this BSV mode.")
(defconst bsv-mode-release-emacs t
"If non-nil, this version of BSV mode was released with Emacs itself.")
(defun bsv-version ()
"Inform caller of the version of this file."
(interactive)
(message "Using bsv-mode version %s" bsv-mode-version))
;; Insure we have certain packages, and deal with it if we don't
;; Be sure to note which Emacs flavor and version added each feature.
(eval-when-compile
;; Provide stuff if we are XEmacs
(when (featurep 'xemacs)
(condition-case nil
(require 'easymenu)
(error nil))
(condition-case nil
(require 'regexp-opt)
(error nil))
;; Bug in 19.28 through 19.30 skeleton.el, not provided.
(condition-case nil
(load "skeleton")
(error nil))
(condition-case nil
(if (fboundp 'when)
nil ;; fab
(defmacro when (cond &rest body)
(list 'if cond (cons 'progn body))))
(error nil))
(condition-case nil
(if (fboundp 'unless)
nil ;; fab
(defmacro unless (cond &rest body)
(cons 'if (cons cond (cons 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 (fboundp 'char-before)
nil ;; great
(defmacro char-before (&rest body)
(char-after (1- (point)))))
(error nil))
(condition-case nil
(if (fboundp 'when)
nil ;; fab
(defsubst point-at-bol (&optional N)
(save-excursion (beginning-of-line N) (point))))
(error nil))
(condition-case nil
(if (fboundp 'when)
nil ;; fab
(defsubst point-at-eol (&optional N)
(save-excursion (end-of-line N) (point))))
(error nil))
(condition-case nil
(require 'custom)
(error nil))
(condition-case nil
(if (fboundp 'match-string-no-properties)
nil ;; great
(defsubst match-string-no-properties (num &optional string)
"Return string of text matched by last search, without text properties.
NUM specifies which parenthesized expression in the last regexp.
Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
Zero means the entire text matched by the whole regexp or whole string.
STRING should be given if the last search was by `string-match' on STRING."
(if (match-beginning num)
(if string
(let ((result
(substring string
(match-beginning num) (match-end num))))
(set-text-properties 0 (length result) nil result)
result)
(buffer-substring-no-properties (match-beginning num)
(match-end num)
(current-buffer)))))
)
(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 values 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))
)
(unless (boundp 'inhibit-point-motion-hooks)
(defvar inhibit-point-motion-hooks nil))
(unless (boundp 'deactivate-mark)
(defvar deactivate-mark nil))
)
;;
;; OK, do this stuff if we are NOT XEmacs:
(unless (featurep 'xemacs)
(unless (fboundp 'region-active-p)
(defmacro region-active-p ()
`(and transient-mark-mode mark-active))))
)
;; Provide a regular expression optimization routine, using regexp-opt
;; if provided by the user's elisp libraries
(eval-and-compile
;; The below were disabled when GNU Emacs 22 was released;
;; perhaps some still need to be there to support Emacs 21.
(if (featurep 'xemacs)
(if (fboundp 'regexp-opt)
;; regexp-opt is defined, does it take 3 or 2 arguments?
(if (fboundp 'function-max-args)
(let ((args (function-max-args `regexp-opt)))
(cond
((eq args 3) ;; It takes 3
(condition-case nil ; Hide this defun from emacses
;with just a two input regexp
(defun bsv-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))
)
((eq args 2) ;; It takes 2
(defun bsv-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 bsv-regexp-opt (a b)
"Call 'regexp-opt' on A and B."
(regexp-opt a b))
)
;; There is no regexp-opt, provide our own
(defun bsv-regexp-opt (strings &optional paren shy)
(let ((open (if paren "\\(" "")) (close (if paren "\\)" "")))
(concat open (mapconcat 'regexp-quote strings "\\|") close)))
)
;; Emacs.
(defalias 'bsv-regexp-opt 'regexp-opt)))
(eval-and-compile
;; Both xemacs and emacs
(condition-case nil
(require 'diff) ;; diff-command and diff-switches
(error nil))
(condition-case nil
(require 'compile) ;; compilation-error-regexp-alist-alist
(error nil))
(condition-case nil
(unless (fboundp 'buffer-chars-modified-tick) ;; Emacs 22 added
(defmacro buffer-chars-modified-tick () (buffer-modified-tick)))
(error nil))
;; Added in Emacs 24.1
(condition-case nil
(unless (fboundp 'prog-mode)
(define-derived-mode prog-mode fundamental-mode "Prog"))
(error nil)))
(eval-when-compile
(defun bsv-regexp-words (a)
"Call 'regexp-opt' with word delimiters for the words A."
(concat "\\<" (bsv-regexp-opt a t) "\\>")))
(defun bsv-regexp-words (a)
"Call 'regexp-opt' with word delimiters for the words A."
;; The FAQ references this function, so user LISP sometimes calls it
(concat "\\<" (bsv-regexp-opt a t) "\\>"))
(defun bsv-easy-menu-filter (menu)
"Filter `easy-menu-define' MENU to support new features."
(cond ((not (featurep 'xemacs))
menu) ;; GNU Emacs - passthru
;; XEmacs doesn't support :help. Strip it.
;; Recursively filter the a submenu
((listp menu)
(mapcar 'bsv-easy-menu-filter menu))
;; Look for [:help "blah"] and remove
((vectorp menu)
(let ((i 0) (out []))
(while (< i (length menu))
(if (equal `:help (aref menu i))
(setq i (+ 2 i))
(setq out (vconcat out (vector (aref menu i)))
i (1+ i))))
out))
(t menu))) ;; Default - ok
;;(bsv-easy-menu-filter
;; `("BSV" ("MA" ["SAA" nil :help "Help SAA"] ["SAB" nil :help "Help SAA"])
;; "----" ["MB" nil :help "Help MB"]))
(defun bsv-define-abbrev (table name expansion &optional hook)
"Filter `define-abbrev' TABLE NAME EXPANSION and call HOOK.
Provides SYSTEM-FLAG in newer Emacs."
(condition-case nil
(define-abbrev table name expansion hook 0 t)
(error
(define-abbrev table name expansion hook))))
(defun bsv-customize ()
"Customize variables and other settings used by BSV-Mode."
(interactive)
(customize-group 'bsv-mode))
(defun bsv-font-customize ()
"Customize fonts used by BSV-Mode."
(interactive)
(if (fboundp 'customize-apropos)
(customize-apropos "font-lock-*" 'faces)))
(defun bsv-booleanp (value)
"Return t if VALUE is boolean.
This implements GNU Emacs 22.1's `booleanp' function in earlier Emacs.
This function may be removed when Emacs 21 is no longer supported."
(or (equal value t) (equal value nil)))
(defun bsv-insert-last-command-event ()
"Insert the `last-command-event'."
(insert (if (featurep 'xemacs)
;; XEmacs 21.5 doesn't like last-command-event
last-command-char
;; And GNU Emacs 22 has obsoleted last-command-char
last-command-event)))
(defvar bsv-no-change-functions nil
"True if `after-change-functions' is disabled.
Use of `syntax-ppss' may break, as ppss's cache may get corrupted.")
(defvar bsv-in-hooks nil
"True when within a `bsv-run-hooks' block.")
(defmacro bsv-run-hooks (&rest hooks)
"Run each hook in HOOKS using `run-hooks'.
Set `bsv-in-hooks' during this time, to assist AUTO caches."
`(let ((bsv-in-hooks t))
(run-hooks ,@hooks)))
(defun bsv-syntax-ppss (&optional pos)
(when bsv-no-change-functions
(if bsv-in-hooks
(bsv-scan-cache-flush)
;; else don't let the AUTO code itself get away with flushing the cache,
;; as that'll make things very slow
(backtrace)
(error "%s: Internal problem; use of syntax-ppss when cache may be corrupt"
(bsv-point-text))))
(if (fboundp 'syntax-ppss)
(syntax-ppss pos)
(parse-partial-sexp (point-min) (or pos (point)))))
(defgroup bsv-mode nil
"Facilitates easy editing of BSV source text."
:version "22.2"
:group 'languages)
; (defgroup bsv-mode-fonts nil
; "Facilitates easy customization fonts used in BSV source text"
; :link '(customize-apropos "font-lock-*" 'faces)
; :group 'bsv-mode)
(defgroup bsv-mode-indent nil
"Customize indentation and highlighting of BSV source text."
:group 'bsv-mode)
(defgroup bsv-mode-actions nil
"Customize actions on BSV source text."
:group 'bsv-mode)
(defgroup bsv-mode-auto nil
"Customize AUTO actions when expanding BSV source text."
:group 'bsv-mode)
(defvar bsv-debug nil
"If set, enable debug messages for `bsv-mode' internals.")
(defcustom bsv-linter
"echo 'No bsv-linter set, see \"M-x describe-variable bsv-linter\"'"
"*Unix program and arguments to call to run a lint checker on BSV source.
Depending on the `bsv-set-compile-command', this may be invoked when
you type \\[compile]. When the compile completes, \\[next-error] will take
you to the next lint error."
:type 'string
:group 'bsv-mode-actions)
;; We don't mark it safe, as it's used as a shell command
(defcustom bsv-coverage
"echo 'No bsv-coverage set, see \"M-x describe-variable bsv-coverage\"'"
"*Program and arguments to use to annotate for coverage BSV source.
Depending on the `bsv-set-compile-command', this may be invoked when
you type \\[compile]. When the compile completes, \\[next-error] will take
you to the next lint error."
:type 'string
:group 'bsv-mode-actions)
;; We don't mark it safe, as it's used as a shell command
(defcustom bsv-simulator "bsc -sim "
"*Program and arguments to use to interpret bsv source."
:type 'string
:group 'bsv-mode-actions)
;; We don't mark it safe, as it's used as a shell command
(defcustom bsv-compiler "bsc -verilog "
"*Program and arguments to use to compile bsv source."
:type 'string
:group 'bsv-mode-actions)
;; We don't mark it safe, as it's used as a shell command
(defcustom bsv-preprocessor
;; Very few tools give preprocessed output, so we'll default to BSV-Perl
"vppreproc __FLAGS__ __FILE__"
"*Program and arguments to use to preprocess BSV source.
This is invoked with `bsv-preprocess', and depending on the
`bsv-set-compile-command', may also be invoked when you type
\\[compile]. When the compile completes, \\[next-error] will
take you to the next lint error."
:type 'string
:group 'bsv-mode-actions)
;; We don't mark it safe, as it's used as a shell command
(defvar bsv-preprocess-history nil
"History for `bsv-preprocess'.")
(defvar bsv-tool 'bsv-compiler)
(defcustom bsv-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 `bsv-font-lock-translate-off-face').
Note: This will slow down on-the-fly fontification (and thus editing).
Note: Activate the new setting in a BSV buffer by re-fontifying it (menu
entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
:type 'boolean
:group 'bsv-mode-indent)
;; Note we don't use :safe, as that would break on Emacsen before 22.0.
(put 'bsv-highlight-translate-off 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-lineup 'declarations
"*Type of statements to lineup across multiple lines.
If 'all' is selected, then all line ups described below are done.
If 'declaration', then just declarations are lined up with any
preceding declarations, taking into account widths and the like,
so or example the code:
reg [31:0] a;
reg b;
would become
reg [31:0] a;
reg b;
If '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;
In order to speed up editing, large blocks of statements are lined up
only when a \\[bsv-pretty-expr] is typed; and large blocks of declarations
are lineup only when \\[bsv-pretty-declarations] is typed."
:type '(radio (const :tag "Line up Assignments and Declarations" all)
(const :tag "Line up Assignment statements" assignments )
(const :tag "Line up Declarations" declarations)
(function :tag "Other"))
:group 'bsv-mode-indent )
(defcustom bsv-indent-level 3
"*Indentation of BSV statements with respect to containing block."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-indent-level 'safe-local-variable 'integerp)
(defcustom bsv-indent-level-module 3
"*Indentation of Module level BSV statements (eg always, initial).
Set to 0 to get initial and always statements lined up on the left side of
your screen."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-indent-level-module 'safe-local-variable 'integerp)
(defcustom bsv-indent-level-declaration 3
"*Indentation of declarations with respect to containing block.
Set to 0 to get them list right under containing block."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-indent-level-declaration 'safe-local-variable 'integerp)
(defcustom bsv-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 'bsv-mode-indent
:type 'boolean)
(put 'bsv-indent-declaration-macros 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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 'bsv-mode-indent
:type 'boolean)
(put 'bsv-indent-lists 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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 'bsv-mode-indent
:type 'integer)
(put 'bsv-indent-level-behavioral 'safe-local-variable 'integerp)
(defcustom bsv-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 'bsv-mode-indent
:type 'integer)
(put 'bsv-indent-level-directive 'safe-local-variable 'integerp)
(defcustom bsv-cexp-indent 2
"*Indentation of BSV statements split across lines."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-cexp-indent 'safe-local-variable 'integerp)
(defcustom bsv-case-indent 2
"*Indentation for case statements."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-case-indent 'safe-local-variable 'integerp)
(defcustom bsv-auto-newline nil
"*True means automatically newline after semicolons."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-auto-newline 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-indent-on-newline t
"*True means automatically indent line after newline."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-auto-indent-on-newline 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-tab-always-indent t
"*True means TAB should always re-indent the current line.
A nil value means TAB will only reindent when at the beginning of the line."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-tab-always-indent 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-tab-to-comment nil
"*True means TAB moves to the right hand column in preparation for a comment."
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-tab-to-comment 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-indent-begin-after-if t
"*If true, indent begin statements following if, else, while, for and repeat.
Otherwise, line them up."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-indent-begin-after-if 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-align-ifelse nil
"*If true, align `else' under matching `if'.
Otherwise else is lined up with first character on line holding matching if."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-align-ifelse 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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 'bsv-mode-indent
:type 'integer)
(put 'bsv-minimum-comment-distance 'safe-local-variable 'integerp)
(defcustom bsv-highlight-p1800-keywords nil
"*True means highlight words newly reserved by IEEE-1800.
These will appear in `bsv-font-lock-p1800-face' in order to gently
suggest changing where these words are used as variables to something else.
A nil value means highlight these words as appropriate for the SystemBSV
IEEE-1800 standard. Note that changing this will require restarting Emacs
to see the effect as font color choices are cached by Emacs."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-highlight-p1800-keywords 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-highlight-grouping-keywords nil
"*True means highlight grouping keywords 'begin' and 'end' more dramatically.
If false, these words are in the `font-lock-type-face'; if True then they are in
`bsv-font-lock-ams-face'. Some find that special highlighting on these
grouping constructs allow the structure of the code to be understood at a glance."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-highlight-grouping-keywords 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-highlight-modules nil
"*True means highlight module statements for `bsv-load-file-at-point'.
When true, mousing over module names will allow jumping to the
module definition. If false, this is not supported. Setting
this is experimental, and may lead to bad performance."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-highlight-modules 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-highlight-includes t
"*True means highlight module statements for `bsv-load-file-at-point'.
When true, mousing over include file names will allow jumping to the
file referenced. If false, this is not supported."
:group 'bsv-mode-indent
:type 'boolean)
(put 'bsv-highlight-includes 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-declare-nettype nil
"*Non-nil specifies the data type to use with `bsv-auto-input' etc.
Set this to \"wire\" if the BSV code uses \"`default_nettype
none\". Note using `default_nettype none isn't recommended practice; this
mode is experimental."
:version "24.1"
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-declare-nettype 'safe-local-variable `stringp)
(defcustom bsv-auto-wire-type nil
"*Non-nil specifies the data type to use with `bsv-auto-wire' etc.
Set this to \"logic\" for SystemBSV code, or use `bsv-auto-logic'."
:version "24.1"
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-wire-type 'safe-local-variable `stringp)
(defcustom bsv-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 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-endcomments 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-delete-trailing-whitespace nil
"*True means to `delete-trailing-whitespace' in `bsv-auto'."
:version "24.1"
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-delete-trailing-whitespace 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-ignore-concat nil
"*True means ignore signals in {...} concatenations for AUTOWIRE etc.
This will exclude signals referenced as pin connections in {...}
from AUTOWIRE, AUTOOUTPUT and friends. This flag should be set
for backward compatibility only and not set in new designs; it
may be removed in future versions."
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-ignore-concat 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-read-includes nil
"*True means to automatically read includes before AUTOs.
This will do a `bsv-read-defines' and `bsv-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 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-read-includes 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-save-policy nil
"*Non-nil indicates action to take when saving a BSV buffer with AUTOs.
A value of `force' will always do a \\[bsv-auto] automatically if
needed on every save. A value of `detect' will do \\[bsv-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 'bsv-mode-actions
:type '(choice (const nil) (const ask) (const detect) (const force)))
(defcustom bsv-auto-star-expand t
"*Non-nil indicates to expand a SystemBSV .* instance ports.
They will be expanded in the same way as if there was a AUTOINST in the
instantiation. See also `bsv-auto-star' and `bsv-auto-star-save'."
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-star-expand 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-star-save nil
"*Non-nil indicates to save to disk SystemBSV .* instance expansions.
A nil value indicates direct connections will be removed before saving.
Only meaningful to those created due to `bsv-auto-star-expand' being set.
Instead of setting this, you may want to use /*AUTOINST*/, which will
always be saved."
:group 'bsv-mode-actions
:type 'boolean)
(put 'bsv-auto-star-save 'safe-local-variable 'bsv-booleanp)
(defvar bsv-auto-update-tick nil
"Modification tick at which autos were last performed.")
(defvar bsv-auto-last-file-locals nil
"Text from file-local-variables during last evaluation.")
(defvar bsv-diff-function 'bsv-diff-report
"*Function to run when `bsv-diff-auto' detects differences.
Function takes three arguments, the original buffer, the
difference buffer, and the point in original buffer with the
first difference.")
;;; Compile support
(require 'compile)
(defvar bsv-error-regexp-added nil)
(defvar bsv-error-regexp-emacs-alist
'(
(bsc-xl-1a
"Error: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\)" 1 2 )
(bsc-xl-1b
"Warning: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\)" 1 2 )
(bsc-xl-1c
"Error: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\), column \\([0-9]+\\)" 1 2 3)
(bsc-xl-1d
"Warning: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\), column \\([0-9]+\\)" 1 2 3)
(verilog-xl-1
"\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 3)
(verilog-xl-2
"([WE][0-9A-Z]+)[ \t]+\\([^ \t\n,]+\\)[, \t]+\\(line[ \t]+\\)?\\([0-9]+\\):.*$" 1 3)
(verilog-IES
".*\\*[WE],[0-9A-Z]+\\(\[[0-9A-Z_,]+\]\\)? (\\([^ \t,]+\\),\\([0-9]+\\)" 2 3)
(verilog-surefire-1
"[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 1 2)
(verilog-surefire-2
"\\(WARNING\\|ERROR\\|INFO\\)[^:]*: \\([^,]+\\),\\s-+\\(line \\)?\\([0-9]+\\):" 2 4 )
(verilog-verbose
"\
\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\
:\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5)
(verilog-xsim
"\\(Error\\|Warning\\).*in file (\\([^ \t]+\\) at line *\\([0-9]+\\))" 2 3)
(verilog-vcs-1
"\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 2 3)
(verilog-vcs-2
"Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 2)
(verilog-vcs-3
"\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 2 3)
(verilog-vcs-4
"syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 1 2)
(verilog-verilator
"%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 3 4)
(verilog-leda
"^In file \\([^ \t]+\\)[ \t]+line[ \t]+\\([0-9]+\\):\n[^\n]*\n[^\n]*\n\\(Warning\\|Error\\|Failure\\)[^\n]*" 1 2)
)
"List of regexps for BSV compilers.
See `compilation-error-regexp-alist' for the formatting. For Emacs 22+.")
(defvar bsv-error-regexp-xemacs-alist
;; Emacs form is '((v-tool "re" 1 2) ...)
;; XEmacs form is '(bsv ("re" 1 2) ...)
;; So we can just map from Emacs to XEmacs
(cons 'bsv (mapcar 'cdr bsv-error-regexp-emacs-alist))
"List of regexps for BSV compilers.
See `compilation-error-regexp-alist-alist' for the formatting. For XEmacs.")
(defvar bsv-error-font-lock-keywords
'(
;; bsv-xl-1
("\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 bold t)
("\\(Error\\|Warning\\)!.*\n?.*\"\\([^\"]+\\)\", \\([0-9]+\\)" 2 bold t)
;; bsv-xl-2
("([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]+\\):.*$" 3 bold t)
;; bsv-IES (nc-bsv)
(".*\\*[WE],[0-9A-Z]+\\(\[[0-9A-Z_,]+\]\\)? (\\([^ \t,]+\\),\\([0-9]+\\)|" 2 bold t)
(".*\\*[WE],[0-9A-Z]+\\(\[[0-9A-Z_,]+\]\\)? (\\([^ \t,]+\\),\\([0-9]+\\)|" 3 bold t)
;; bsv-surefire-1
("[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 1 bold t)
("[^\n]*\\[\\([^:]+\\):\\([0-9]+\\)\\]" 2 bold t)
;; bsv-surefire-2
("\\(WARNING\\|ERROR\\|INFO\\): \\([^,]+\\), line \\([0-9]+\\):" 2 bold t)
("\\(WARNING\\|ERROR\\|INFO\\): \\([^,]+\\), line \\([0-9]+\\):" 3 bold t)
;; bsv-verbose
("\
\\([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)
;; bsv-vcs-1
("\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 2 bold t)
("\\(Error\\|Warning\\):[^(]*(\\([^ \t]+\\) line *\\([0-9]+\\))" 3 bold t)
;; bsv-vcs-2
("Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 bold t)
("Warning:.*(port.*(\\([^ \t]+\\) line \\([0-9]+\\))" 1 bold t)
;; bsv-vcs-3
("\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 2 bold t)
("\\(Error\\|Warning\\):[\n.]*\\([^ \t]+\\) *\\([0-9]+\\):" 3 bold t)
;; bsv-vcs-4
("syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 1 bold t)
("syntax error:.*\n\\([^ \t]+\\) *\\([0-9]+\\):" 2 bold t)
;; bsv-verilator
(".*%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 3 bold t)
(".*%?\\(Error\\|Warning\\)\\(-[^:]+\\|\\):[\n ]*\\([^ \t:]+\\):\\([0-9]+\\):" 4 bold t)
;; bsv-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 BSV *compilation* buffers.
Only used in XEmacs; GNU Emacs uses `bsv-error-regexp-emacs-alist'.")
(defcustom bsv-library-flags '("")
"*List of standard BSV arguments to use for /*AUTOINST*/.
These arguments are used to find files for `bsv-auto', and match
the flags accepted by a standard BSV-XL simulator.
-f filename Reads more `bsv-library-flags' from the filename.
+incdir+dir Adds the directory to `bsv-library-directories'.
-Idir Adds the directory to `bsv-library-directories'.
-y dir Adds the directory to `bsv-library-directories'.
+libext+.v Adds the extensions to `bsv-library-extensions'.
-v filename Adds the filename to `bsv-library-files'.
filename Adds the filename to `bsv-library-files'.
This is not recommended, -v is a better choice.
You might want these defined in each file; put at the *END* of your file
something like:
// Local Variables:
// bsv-library-flags:(\"-y dir -y otherdir\")
// End:
bsv-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 'bsv-mode-auto
:type '(repeat string))
(put 'bsv-library-flags 'safe-local-variable 'listp)
(defcustom bsv-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:
// bsv-library-directories:(\".\" \"subdir\" \"subdir2\")
// End:
bsv-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 `bsv-library-flags', `bsv-library-files'
and `bsv-library-extensions'."
:group 'bsv-mode-auto
:type '(repeat file))
(put 'bsv-library-directories 'safe-local-variable 'listp)
(defcustom bsv-library-files '()
"*List of files to search for modules.
AUTOINST will use this when it needs to resolve a module name.
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:
// bsv-library-files:(\"/some/path/technology.v\" \"/some/path/tech2.v\")
// End:
bsv-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 `bsv-library-flags', `bsv-library-directories'."
:group 'bsv-mode-auto
:type '(repeat directory))
(put 'bsv-library-files 'safe-local-variable 'listp)
(defcustom bsv-library-extensions '(".v" ".sv")
"*List of extensions to use when looking for files for /*AUTOINST*/.
See also `bsv-library-flags', `bsv-library-directories'."
:type '(repeat string)
:group 'bsv-mode-auto)
(put 'bsv-library-extensions 'safe-local-variable 'listp)
(defcustom bsv-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 `bsv-auto-reset-widths' set."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-active-low-regexp 'safe-local-variable 'stringp)
(defcustom bsv-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."
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-sense-include-inputs 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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 BSV file that requires it, rather than being set globally."
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-sense-defines-constant 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-reset-blocking-in-non t
"*If true, AUTORESET will reset those signals which were
assigned with blocking assignments (=) even in a block with
non-blocking assignments (<=).
If nil, all blocking assigned signals are ignored when any
non-blocking assignment is in the AUTORESET block. This allows
blocking assignments to be used for temporary values and not have
those temporaries reset. See example in `bsv-auto-reset'."
:version "24.1"
:type 'boolean
:group 'bsv-mode-auto)
(put 'bsv-auto-reset-blocking-in-non 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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 an AUTORESET."
:type 'boolean
:group 'bsv-mode-auto)
(put 'bsv-auto-reset-widths 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-assignment-delay ""
"*Text used for delays in delayed assignments. Add a trailing space if set."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-assignment-delay 'safe-local-variable 'stringp)
(defcustom bsv-auto-arg-sort nil
"*If set, AUTOARG signal names will be sorted, not in declaration order.
Declaration order is advantageous with order based instantiations
and is the default for backward compatibility. Sorted order
reduces changes when declarations are moved around in a file, and
it's bad practice to rely on order based instantiations anyhow.
See also `bsv-auto-inst-sort'."
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-arg-sort 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-inst-dot-name nil
"*If true, when creating ports with AUTOINST, use .name syntax.
This will use \".port\" instead of \".port(port)\" when possible.
This is only legal in SystemBSV files, and will confuse older
simulators. Setting `bsv-auto-inst-vector' to nil may also
be desirable to increase how often .name will be used."
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-inst-dot-name 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-inst-param-value nil
"*If set, AUTOINST will replace parameters with the parameter value.
If nil, leave parameters as symbolic names.
Parameters must be in BSV 2001 format #(...), and if a parameter is not
listed as such there (as when the default value is acceptable), it will not
be replaced, and will remain symbolic.
For example, imagine a submodule uses parameters to declare the size of its
inputs. This is then used by a upper module:
module InstModule (o,i);
parameter WIDTH;
input [WIDTH-1:0] i;
endmodule
module ExampInst;
InstModule
#(PARAM(10))
instName
(/*AUTOINST*/
.i (i[PARAM-1:0]));
Note even though PARAM=10, the AUTOINST has left the parameter as a
symbolic name. If `bsv-auto-inst-param-value' is set, this will
instead expand to:
module ExampInst;
InstModule
#(PARAM(10))
instName
(/*AUTOINST*/
.i (i[9:0]));"
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-inst-param-value 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-inst-sort nil
"*If set, AUTOINST signal names will be sorted, not in declaration order.
Also affects AUTOINSTPARAM. Declaration order is the default for
backward compatibility, and as some teams prefer signals that are
declared together to remain together. Sorted order reduces
changes when declarations are moved around in a file.
See also `bsv-auto-arg-sort'."
:version "24.1"
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-inst-sort 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-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.) Setting this to nil may
speed up some simulators, but is less general and harder to read, so avoid."
:group 'bsv-mode-auto
:type 'boolean)
(put 'bsv-auto-inst-vector 'safe-local-variable 'bsv-booleanp)
(defcustom bsv-auto-inst-template-numbers nil
"*If true, when creating templated ports with AUTOINST, add a comment.
If t, the comment will add the line number of the template that
was used for that port declaration. This setting is suggested
only for debugging use, as regular use may cause a large numbers
of merge conflicts.
If 'lhs', the comment will show the left hand side of the
AUTO_TEMPLATE rule that is matched. This is less precise than
numbering (t) when multiple rules have the same pin name, but
won't merge conflict."
:group 'bsv-mode-auto
:type '(choice (const nil) (const t) (const lhs)))
(put 'bsv-auto-inst-template-numbers 'safe-local-variable
'(lambda (x) (memq x '(nil t lhs))))
(defcustom bsv-auto-inst-column 40
"*Indent-to column number for net name part of AUTOINST created pin."
:group 'bsv-mode-indent
:type 'integer)
(put 'bsv-auto-inst-column 'safe-local-variable 'integerp)
(defcustom bsv-auto-input-ignore-regexp nil
"*If set, when creating AUTOINPUT list, ignore signals matching this regexp.
See the \\[bsv-faq] for examples on using this."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-input-ignore-regexp 'safe-local-variable 'stringp)
(defcustom bsv-auto-inout-ignore-regexp nil
"*If set, when creating AUTOINOUT list, ignore signals matching this regexp.
See the \\[bsv-faq] for examples on using this."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-inout-ignore-regexp 'safe-local-variable 'stringp)
(defcustom bsv-auto-output-ignore-regexp nil
"*If set, when creating AUTOOUTPUT list, ignore signals matching this regexp.
See the \\[bsv-faq] for examples on using this."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-output-ignore-regexp 'safe-local-variable 'stringp)
(defcustom bsv-auto-tieoff-declaration "wire"
"*Data type used for the declaration for AUTOTIEOFF. If \"wire\" then
create a wire, if \"assign\" create an assignment, else the data type for
variable creation."
:version "24.1"
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-tieoff-declaration 'safe-local-variable 'stringp)
(defcustom bsv-auto-tieoff-ignore-regexp nil
"*If set, when creating AUTOTIEOFF list, ignore signals matching this regexp.
See the \\[bsv-faq] for examples on using this."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-tieoff-ignore-regexp 'safe-local-variable 'stringp)
(defcustom bsv-auto-unused-ignore-regexp nil
"*If set, when creating AUTOUNUSED list, ignore signals matching this regexp.
See the \\[bsv-faq] for examples on using this."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-auto-unused-ignore-regexp 'safe-local-variable 'stringp)
(defcustom bsv-typedef-regexp nil
"*If non-nil, regular expression that matches BSV-2001 typedef names.
For example, \"_t$\" matches typedefs named with _t, as in the C language."
:group 'bsv-mode-auto
:type 'string)
(put 'bsv-typedef-regexp 'safe-local-variable 'stringp)
(defcustom bsv-mode-hook 'bsv-set-compile-command
"*Hook run after BSV mode is loaded."
:type 'hook
:group 'bsv-mode)
(defcustom bsv-auto-hook nil
"*Hook run after `bsv-mode' updates AUTOs."
:group 'bsv-mode-auto
:type 'hook)
(defcustom bsv-before-auto-hook nil
"*Hook run before `bsv-mode' updates AUTOs."
:group 'bsv-mode-auto
:type 'hook)
(defcustom bsv-delete-auto-hook nil
"*Hook run after `bsv-mode' deletes AUTOs."
:group 'bsv-mode-auto
:type 'hook)
(defcustom bsv-before-delete-auto-hook nil
"*Hook run before `bsv-mode' deletes AUTOs."
:group 'bsv-mode-auto
:type 'hook)
(defcustom bsv-getopt-flags-hook nil
"*Hook run after `bsv-getopt-flags' determines the BSV option lists."
:group 'bsv-mode-auto
:type 'hook)
(defcustom bsv-before-getopt-flags-hook nil
"*Hook run before `bsv-getopt-flags' determines the BSV option lists."
:group 'bsv-mode-auto
:type 'hook)
(defvar bsv-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 BSV mode. See `imenu-generic-expression'.")
;;
;; provide a bsv-header function.
;; Customization variables:
;;
(defvar bsv-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 bsv-company nil
"*Default name of Company for BSV header.
If set will become buffer local.")
(make-variable-buffer-local 'bsv-company)
(defvar bsv-project nil
"*Default name of Project for BSV header.
If set will become buffer local.")
(make-variable-buffer-local 'bsv-project)
(defvar bsv-mode-map
(let ((map (make-sparse-keymap)))
(define-key map ";" 'electric-bsv-semi)
(define-key map [(control 59)] 'electric-bsv-semi-with-comment)
(define-key map ":" 'electric-bsv-colon)
;;(define-key map "=" 'electric-bsv-equal)
(define-key map "\`" 'electric-bsv-tick)
;; (define-key map "\t" 'electric-bsv-tab)
(define-key map "\t" 'bsv-complete-or-indent-command)
(define-key map "\r" 'electric-bsv-terminate-line)
;; backspace/delete key bindings
(define-key map [backspace] 'backward-delete-char-untabify)
(unless (boundp 'delete-key-deletes-forward) ; XEmacs variable
(define-key map [delete] 'delete-char)
(define-key map [(meta delete)] 'kill-word))
(define-key map "\M-\C-b" 'electric-bsv-backward-sexp)
(define-key map "\M-\C-f" 'electric-bsv-forward-sexp)
(define-key map "\M-\r" `electric-bsv-terminate-and-indent)
(define-key map "\M-\t" 'bsv-complete-word)
(define-key map "\M-?" 'bsv-show-completions)
;; Note \C-c and letter are reserved for users
(define-key map "\C-c\`" 'bsv-lint-off)
(define-key map "\C-c\*" 'bsv-delete-auto-star-implicit)
(define-key map "\C-c\?" 'bsv-diff-auto)
(define-key map "\C-c\C-r" 'bsv-label-be)
(define-key map "\C-c\C-i" 'bsv-pretty-declarations)
(define-key map "\C-c=" 'bsv-pretty-expr)
(define-key map "\M-*" 'bsv-star-comment)
(define-key map "\C-c\C-c" 'bsv-comment-region)
(define-key map "\C-c\C-u" 'bsv-uncomment-region)
(when (featurep 'xemacs)
(define-key map [(meta control h)] 'bsv-mark-defun)
(define-key map "\M-\C-a" 'bsv-beg-of-defun)
(define-key map "\M-\C-e" 'bsv-end-of-defun))
(define-key map "\C-c\C-d" 'bsv-goto-defun)
(define-key map "\C-c\C-k" 'bsv-delete-auto)
(define-key map "\C-c\C-a" 'bsv-auto)
(define-key map "\C-c\C-s" 'bsv-auto-save-compile)
(define-key map "\C-c\C-p" 'bsv-preprocess)
(define-key map "\C-c\C-z" 'bsv-inject-auto)
(define-key map "\C-c\C-e" 'bsv-expand-vector)
(define-key map "\C-c\C-h" 'bsv-header)
(define-key map "\C-c\C-c" 'bsv-add-comment-bar)
(define-key map "\C-l" 'bsv-recenter-and-font-lock-fontify-buffer)
map)
"Keymap used in BSV mode.")
;; menus
(easy-menu-define
bsv-menu bsv-mode-map "Menu for BSV mode"
(bsv-easy-menu-filter
'("BSV"
("Choose Compilation Action"
["None"
(progn
(setq bsv-tool nil)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool nil)
:help "When invoking compilation, use compile-command"]
["Lint"
(progn
(setq bsv-tool 'bsv-linter)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool `bsv-linter)
:help "When invoking compilation, use lint checker"]
["Coverage"
(progn
(setq bsv-tool 'bsv-coverage)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool `bsv-coverage)
:help "When invoking compilation, annotate for coverage"]
["Simulator"
(progn
(setq bsv-tool 'bsv-simulator)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool `bsv-simulator)
:help "When invoking compilation, interpret BSV source"]
["Compiler"
(progn
(setq bsv-tool 'bsv-compiler)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool `bsv-compiler)
:help "When invoking compilation, compile BSV source"]
["Preprocessor"
(progn
(setq bsv-tool 'bsv-preprocessor)
(bsv-set-compile-command))
:style radio
:selected (equal bsv-tool `bsv-preprocessor)
:help "When invoking compilation, preprocess BSV source, see also `bsv-preprocess'"]
)
("Move"
["Beginning of function" bsv-beg-of-defun
:keys "C-M-a"
:help "Move backward to the beginning of the current function or procedure"]
["End of function" bsv-end-of-defun
:keys "C-M-e"
:help "Move forward to the end of the current function or procedure"]
["Mark function" bsv-mark-defun
:keys "C-M-h"
:help "Mark the current BSV function or procedure"]
["Goto function/module" bsv-goto-defun
:help "Move to specified BSV module/task/function"]
["Move to beginning of block" electric-bsv-backward-sexp
:help "Move backward over one balanced expression"]
["Move to end of block" electric-bsv-forward-sexp
:help "Move forward over one balanced expression"]
)
("Comments"
["Comment Region" bsv-comment-region
:help "Put marked area into a comment"]
["UnComment Region" bsv-uncomment-region
:help "Uncomment an area commented with Comment Region"]
["Multi-line comment insert" bsv-star-comment
:help "Insert BSV /* */ comment at point"]
["Lint error to comment" bsv-lint-off
:help "Convert a BSV linter warning line into a disable statement"]
)
"----"
["Compile" compile
:help "Perform compilation-action (above) on the current buffer"]
["AUTO, Save, Compile" bsv-auto-save-compile
:help "Recompute AUTOs, save buffer, and compile"]
["Next Compile Error" next-error
:help "Visit next compilation error message and corresponding source code"]
["Ignore Lint Warning at point" bsv-lint-off
:help "Convert a BSV linter warning line into a disable statement"]
"----"
["Line up declarations around point" bsv-pretty-declarations
:help "Line up declarations around point"]
["Line up equations around point" bsv-pretty-expr
:help "Line up expressions around point"]
["Redo/insert comments on every end" bsv-label-be
:help "Label matching begin ... end statements"]
["Expand [x:y] vector line" bsv-expand-vector
:help "Take a signal vector on the current line and expand it to multiple lines"]
["Insert begin-end block" bsv-insert-block
:help "Insert begin ... end"]
["Complete word" bsv-complete-word
:help "Complete word at point"]
"----"
["Recompute AUTOs" bsv-auto
:help "Expand AUTO meta-comment statements"]
["Kill AUTOs" bsv-delete-auto
:help "Remove AUTO expansions"]
["Diff AUTOs" bsv-diff-auto
:help "Show differences in AUTO expansions"]
["Inject AUTOs" bsv-inject-auto
:help "Inject AUTOs into legacy non-AUTO buffer"]
("AUTO Help..."
["AUTO General" (describe-function 'bsv-auto)
:help "Help introduction on AUTOs"]
["AUTO Library Flags" (describe-variable 'bsv-library-flags)
:help "Help on bsv-library-flags"]
["AUTO Library Path" (describe-variable 'bsv-library-directories)
:help "Help on bsv-library-directories"]
["AUTO Library Files" (describe-variable 'bsv-library-files)
:help "Help on bsv-library-files"]
["AUTO Library Extensions" (describe-variable 'bsv-library-extensions)
:help "Help on bsv-library-extensions"]
["AUTO `define Reading" (describe-function 'bsv-read-defines)
:help "Help on reading `defines"]
["AUTO `include Reading" (describe-function 'bsv-read-includes)
:help "Help on parsing `includes"]
["AUTOARG" (describe-function 'bsv-auto-arg)
:help "Help on AUTOARG - declaring module port list"]
["AUTOASCIIENUM" (describe-function 'bsv-auto-ascii-enum)
:help "Help on AUTOASCIIENUM - creating ASCII for enumerations"]
["AUTOINOUTCOMP" (describe-function 'bsv-auto-inout-comp)
:help "Help on AUTOINOUTCOMP - copying complemented i/o from another file"]
["AUTOINOUTIN" (describe-function 'bsv-auto-inout-in)
:help "Help on AUTOINOUTCOMP - copying i/o from another file as all inputs"]
["AUTOINOUTMODULE" (describe-function 'bsv-auto-inout-module)
:help "Help on AUTOINOUTMODULE - copying i/o from another file"]
["AUTOINSERTLISP" (describe-function 'bsv-auto-insert-lisp)
:help "Help on AUTOINSERTLISP - insert text from a lisp function"]
["AUTOINOUT" (describe-function 'bsv-auto-inout)
:help "Help on AUTOINOUT - adding inouts from cells"]
["AUTOINPUT" (describe-function 'bsv-auto-input)
:help "Help on AUTOINPUT - adding inputs from cells"]
["AUTOINST" (describe-function 'bsv-auto-inst)
:help "Help on AUTOINST - adding pins for cells"]
["AUTOINST (.*)" (describe-function 'bsv-auto-star)
:help "Help on expanding BSV-2001 .* pins"]
["AUTOINSTPARAM" (describe-function 'bsv-auto-inst-param)
:help "Help on AUTOINSTPARAM - adding parameter pins to cells"]
["AUTOLOGIC" (describe-function 'bsv-auto-logic)
:help "Help on AUTOLOGIC - declaring logic signals"]
["AUTOOUTPUT" (describe-function 'bsv-auto-output)
:help "Help on AUTOOUTPUT - adding outputs from cells"]
["AUTOOUTPUTEVERY" (describe-function 'bsv-auto-output-every)
:help "Help on AUTOOUTPUTEVERY - adding outputs of all signals"]
["AUTOREG" (describe-function 'bsv-auto-reg)
:help "Help on AUTOREG - declaring registers for non-wires"]
["AUTOREGINPUT" (describe-function 'bsv-auto-reg-input)
:help "Help on AUTOREGINPUT - declaring inputs for non-wires"]
["AUTORESET" (describe-function 'bsv-auto-reset)
:help "Help on AUTORESET - resetting always blocks"]
["AUTOSENSE" (describe-function 'bsv-auto-sense)
:help "Help on AUTOSENSE - sensitivity lists for always blocks"]
["AUTOTIEOFF" (describe-function 'bsv-auto-tieoff)
:help "Help on AUTOTIEOFF - tying off unused outputs"]
["AUTOUNUSED" (describe-function 'bsv-auto-unused)
:help "Help on AUTOUNUSED - terminating unused inputs"]
["AUTOWIRE" (describe-function 'bsv-auto-wire)
:help "Help on AUTOWIRE - declaring wires for cells"]
)
"----"
["Version and FAQ" bsv-faq
:help "Show the current version, and where to get the FAQ etc"]
["Customize BSV Mode..." bsv-customize
:help "Customize variables and other settings used by BSV-Mode"]
["Customize BSV Fonts & Colors" bsv-font-customize
:help "Customize fonts used by BSV-Mode."])))
(easy-menu-define
bsv-stmt-menu bsv-mode-map "Menu for statement templates in BSV."
(bsv-easy-menu-filter
'("Statements"
["Header" bsv-sk-header
:help "Insert a header block at the top of file"]
["Comment" bsv-sk-comment
:help "Insert a comment block"]
"----"
["Module" bsv-sk-module
:help "Insert a module .. (/*AUTOARG*/);.. endmodule block"]
["OVM Class" bsv-sk-ovm-class
:help "Insert an OVM class block"]
["UVM Class" bsv-sk-uvm-class
:help "Insert an UVM class block"]
["Primitive" bsv-sk-primitive
:help "Insert a primitive .. (.. );.. endprimitive block"]
"----"
["Input" bsv-sk-input
:help "Insert an input declaration"]
["Output" bsv-sk-output
:help "Insert an output declaration"]
["Inout" bsv-sk-inout
:help "Insert an inout declaration"]
["Wire" bsv-sk-wire
:help "Insert a wire declaration"]
["Reg" bsv-sk-reg
:help "Insert a register declaration"]
["Define thing under point as a register" bsv-sk-define-signal
:help "Define signal under point as a register at the top of the module"]
"----"
["Initial" bsv-sk-initial
:help "Insert an initial begin .. end block"]
["Always" bsv-sk-always
:help "Insert an always @(AS) begin .. end block"]
["Function" bsv-sk-function
:help "Insert a function .. begin .. end endfunction block"]
["Task" bsv-sk-task
:help "Insert a task .. begin .. end endtask block"]
["Specify" bsv-sk-specify
:help "Insert a specify .. endspecify block"]
["Generate" bsv-sk-generate
:help "Insert a generate .. endgenerate block"]
"----"
["Begin" bsv-sk-begin
:help "Insert a begin .. end block"]
["If" bsv-sk-if
:help "Insert an if (..) begin .. end block"]
["(if) else" bsv-sk-else-if
:help "Insert an else if (..) begin .. end block"]
["For" bsv-sk-for
:help "Insert a for (...) begin .. end block"]
["While" bsv-sk-while
:help "Insert a while (...) begin .. end block"]
["Fork" bsv-sk-fork
:help "Insert a fork begin .. end .. join block"]
["Repeat" bsv-sk-repeat
:help "Insert a repeat (..) begin .. end block"]
["Case" bsv-sk-case
:help "Insert a case block, prompting for details"]
["Casex" bsv-sk-casex
:help "Insert a casex (...) item: begin.. end endcase block"]
["Casez" bsv-sk-casez
:help "Insert a casez (...) item: begin.. end endcase block"])))
(defvar bsv-mode-abbrev-table nil
"Abbrev table in use in bsv-mode buffers.")
(define-abbrev-table 'bsv-mode-abbrev-table ())
(bsv-define-abbrev bsv-mode-abbrev-table "class" "" 'bsv-sk-ovm-class)
(bsv-define-abbrev bsv-mode-abbrev-table "always" "" 'bsv-sk-always)
(bsv-define-abbrev bsv-mode-abbrev-table "begin" nil `bsv-sk-begin)
(bsv-define-abbrev bsv-mode-abbrev-table "case" "" `bsv-sk-case)
(bsv-define-abbrev bsv-mode-abbrev-table "for" "" `bsv-sk-for)
(bsv-define-abbrev bsv-mode-abbrev-table "generate" "" `bsv-sk-generate)
(bsv-define-abbrev bsv-mode-abbrev-table "initial" "" `bsv-sk-initial)
(bsv-define-abbrev bsv-mode-abbrev-table "fork" "" `bsv-sk-fork)
(bsv-define-abbrev bsv-mode-abbrev-table "module" "" `bsv-sk-module)
(bsv-define-abbrev bsv-mode-abbrev-table "primitive" "" `bsv-sk-primitive)
(bsv-define-abbrev bsv-mode-abbrev-table "repeat" "" `bsv-sk-repeat)
(bsv-define-abbrev bsv-mode-abbrev-table "specify" "" `bsv-sk-specify)
(bsv-define-abbrev bsv-mode-abbrev-table "task" "" `bsv-sk-task)
(bsv-define-abbrev bsv-mode-abbrev-table "while" "" `bsv-sk-while)
(bsv-define-abbrev bsv-mode-abbrev-table "casex" "" `bsv-sk-casex)
(bsv-define-abbrev bsv-mode-abbrev-table "casez" "" `bsv-sk-casez)
(bsv-define-abbrev bsv-mode-abbrev-table "if" "" `bsv-sk-if)
(bsv-define-abbrev bsv-mode-abbrev-table "else if" "" `bsv-sk-else-if)
(bsv-define-abbrev bsv-mode-abbrev-table "assign" "" `bsv-sk-assign)
(bsv-define-abbrev bsv-mode-abbrev-table "function" "" `bsv-sk-function)
(bsv-define-abbrev bsv-mode-abbrev-table "input" "" `bsv-sk-input)
(bsv-define-abbrev bsv-mode-abbrev-table "output" "" `bsv-sk-output)
(bsv-define-abbrev bsv-mode-abbrev-table "inout" "" `bsv-sk-inout)
(bsv-define-abbrev bsv-mode-abbrev-table "wire" "" `bsv-sk-wire)
(bsv-define-abbrev bsv-mode-abbrev-table "reg" "" `bsv-sk-reg)
;;
;; Macros
;;
(defsubst bsv-within-string ()
(nth 3 (parse-partial-sexp (point-at-bol) (point))))
(defsubst bsv-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 (bsv-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
;; Also note \ in the replacement prevent multiple replacements; IE
;; (bsv-string-replace-matches "@" "\\\\([0-9]+\\\\)" nil nil "wire@_@")
;; Gives "wire\([0-9]+\)_@" not "wire\([0-9]+\)_\([0-9]+\)"
(let ((start 0))
(while (string-match from-string string start)
(setq string (replace-match to-string fixedcase literal string)
start (min (length string) (+ (match-beginning 0) (length to-string)))))
string))
(defsubst bsv-string-remove-spaces (string)
"Remove spaces surrounding STRING."
(save-match-data
(setq string (bsv-string-replace-matches "^\\s-+" "" nil nil string))
(setq string (bsv-string-replace-matches "\\s-+$" "" nil nil string))
string))
(defsubst bsv-re-search-forward (REGEXP BOUND NOERROR)
; checkdoc-params: (REGEXP BOUND NOERROR)
"Like `re-search-forward', but skips over match in comments or strings."
(let ((mdata '(nil nil))) ;; So match-end will return nil if no matches found
(while (and
(re-search-forward REGEXP BOUND NOERROR)
(setq mdata (match-data))
(and (bsv-skip-forward-comment-or-string)
(progn
(setq mdata '(nil nil))
(if BOUND
(< (point) BOUND)
t)))))
(store-match-data mdata)
(match-end 0)))
(defsubst bsv-re-search-backward (REGEXP BOUND NOERROR)
; checkdoc-params: (REGEXP BOUND NOERROR)
"Like `re-search-backward', but skips over match in comments or strings."
(let ((mdata '(nil nil))) ;; So match-end will return nil if no matches found
(while (and
(re-search-backward REGEXP BOUND NOERROR)
(setq mdata (match-data))
(and (bsv-skip-backward-comment-or-string)
(progn
(setq mdata '(nil nil))
(if BOUND
(> (point) BOUND)
t)))))
(store-match-data mdata)
(match-end 0)))
(defsubst bsv-re-search-forward-quick (regexp bound noerror)
"Like `bsv-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 uses `bsv-scan' and 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 (bsv-inside-comment-or-string-p)
(re-search-forward "[/\"\n]" nil t) ;; Only way a comment or quote can end
(setq pt (match-end 0))))
pt))
(defsubst bsv-re-search-backward-quick (regexp bound noerror)
; checkdoc-params: (REGEXP BOUND NOERROR)
"Like `bsv-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 uses `bsv-scan' and 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 (bsv-inside-comment-or-string-p)
(re-search-backward "[/\"]" nil t) ;; Only way a comment or quote can begin
(setq pt (match-beginning 0))))
pt))
(defsubst bsv-re-search-forward-substr (substr regexp bound noerror)
"Like `re-search-forward', but first search for SUBSTR constant.
Then searched for the normal REGEXP (which contains SUBSTR), with given
BOUND and NOERROR. The REGEXP must fit within a single line.
This speeds up complicated regexp matches."
;; Problem with overlap: search-forward BAR then FOOBARBAZ won't match.
;; thus require matches to be on one line, and use beginning-of-line.
(let (done)
(while (and (not done)
(search-forward substr bound noerror))
(save-excursion
(beginning-of-line)
(setq done (re-search-forward regexp (point-at-eol) noerror)))
(unless (and (<= (match-beginning 0) (point))
(>= (match-end 0) (point)))
(setq done nil)))
(when done (goto-char done))
done))
;;(bsv-re-search-forward-substr "-end" "get-end-of" nil t) ;;-end (test bait)
(defsubst bsv-re-search-backward-substr (substr regexp bound noerror)
"Like `re-search-backward', but first search for SUBSTR constant.
Then searched for the normal REGEXP (which contains SUBSTR), with given
BOUND and NOERROR. The REGEXP must fit within a single line.
This speeds up complicated regexp matches."
;; Problem with overlap: search-backward BAR then FOOBARBAZ won't match.
;; thus require matches to be on one line, and use beginning-of-line.
(let (done)
(while (and (not done)
(search-backward substr bound noerror))
(save-excursion
(end-of-line)
(setq done (re-search-backward regexp (point-at-bol) noerror)))
(unless (and (<= (match-beginning 0) (point))
(>= (match-end 0) (point)))
(setq done nil)))
(when done (goto-char done))
done))
;;(bsv-re-search-backward-substr "-end" "get-end-of" nil t) ;;-end (test bait)
(defun bsv-delete-trailing-whitespace ()
"Delete trailing spaces or tabs, but not newlines nor linefeeds."
;; Similar to `delete-trailing-whitespace' but that's not present in XEmacs
(save-excursion
(goto-char (point-min))
(while (re-search-forward "[ \t]+$" nil t) ;; Not syntactic WS as no formfeed
(replace-match "" nil nil))))
(defvar compile-command)
;; compilation program
(defun bsv-set-compile-command ()
"Function to compute shell command to compile BSV.
This reads `bsv-tool' and sets `compile-command'. This specifies the
program that executes when you type \\[compile] or
\\[bsv-auto-save-compile].
By default `bsv-tool' uses a Makefile if one exists in the
current directory. If not, it is set to the `bsv-linter',
`bsv-compiler', `bsv-coverage', `bsv-preprocessor',
or `bsv-simulator' variables, as selected with the BSV ->
\"Choose Compilation Action\" menu.
You should set `bsv-tool' or the other variables to the path and
arguments for your BSV simulator. For example:
\"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 `bsv-tool'; in the later, the path to the current buffer is
substituted for the %s.
Where __FLAGS__ appears in the string `bsv-current-flags'
will be substituted.
Where __FILE__ appears in the string, the variable
`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"))
(set (make-local-variable 'compile-command) "make "))
(t
(set (make-local-variable 'compile-command)
(if bsv-tool
(if (string-match "%s" (eval bsv-tool))
(format (eval bsv-tool) (or buffer-file-name ""))
(concat (eval bsv-tool) " " (or buffer-file-name "")))
""))))
(bsv-modify-compile-command))
(defun bsv-expand-command (command)
"Replace meta-information in COMMAND and return it.
Where __FLAGS__ appears in the string `bsv-current-flags'
will be substituted. Where __FILE__ appears in the string, the
current buffer's file-name, without the directory portion, will
be substituted."
(setq command (bsv-string-replace-matches
;; Note \\b only works if under bsv syntax table
"\\b__FLAGS__\\b" (bsv-current-flags)
t t command))
(setq command (bsv-string-replace-matches
"\\b__FILE__\\b" (file-name-nondirectory
(or (buffer-file-name) ""))
t t command))
command)
(defun bsv-modify-compile-command ()
"Update `compile-command' using `bsv-expand-command'."
(when (and
(stringp compile-command)
(string-match "\\b\\(__FLAGS__\\|__FILE__\\)\\b" compile-command))
(set (make-local-variable 'compile-command)
(bsv-expand-command compile-command))))
(if (featurep 'xemacs)
;; Following code only gets called from compilation-mode-hook on XEmacs to add error handling.
(defun bsv-error-regexp-add-xemacs ()
"Teach XEmacs about bsv errors.
Called by `compilation-mode-hook'. This allows \\[next-error] to
find the errors."
(interactive)
(if (boundp 'compilation-error-regexp-systems-alist)
(if (and
(not (equal compilation-error-regexp-systems-list 'all))
(not (member compilation-error-regexp-systems-list 'bsv)))
(push 'bsv compilation-error-regexp-systems-list)))
(if (boundp 'compilation-error-regexp-alist-alist)
(if (not (assoc 'bsv compilation-error-regexp-alist-alist))
(setcdr compilation-error-regexp-alist-alist
(cons bsv-error-regexp-xemacs-alist
(cdr compilation-error-regexp-alist-alist)))))
(if (boundp 'compilation-font-lock-keywords)
(progn
(set (make-local-variable 'compilation-font-lock-keywords)
bsv-error-font-lock-keywords)
(font-lock-set-defaults)))
;; Need to re-run compilation-error-regexp builder
(if (fboundp 'compilation-build-compilation-error-regexp-alist)
(compilation-build-compilation-error-regexp-alist))
))
(defvar bsv-error-regexp-add-didit nil)
(defvar bsv-error-regexp nil)
(setq bsv-error-regexp-add-didit nil
bsv-error-regexp
'(
; Bluespec compiler
;; ("\\(Error\\|Warning\\):.*\n?.*\"\\([^\"]+\\)\",line \\([0-9]+\\)" 2 3)
("Error: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\)" 1 2 )
("Warning: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\)" 1 2 )
("Error: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\), column \\([0-9]+\\)" 1 2 3)
("Warning: \"\\([A-Za-z0-9\._/]+\\)\", line \\([0-9]+\\), column \\([0-9]+\\)" 1 2 3)))
(if (< emacs-major-version 24)
(progn
(defun bsv-error-regexp-add-emacs ()
"Add the messages to the `compilation-error-regexp-alist'.
Called by `compilation-mode-hook'. This allows \\[next-error] to find the errors."
(progn
(setq-default compilation-error-regexp-alist
(append
bsv-error-regexp
nil ;; (default-value 'compilation-error-regexp-alist)
))
))
(if (not bsv-error-regexp-add-didit)
(progn
(setq bsv-error-regexp-add-didit t)
(setq-default compilation-error-regexp-alist
(append
bsv-error-regexp
nil ;; (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))
))
)
;; Following code only gets called from compilation-mode-hook on Emacs to add error handling.
(defun bsv-error-regexp-add-emacs ()
"Tell Emacs compile that we are BSV.
Called by `compilation-mode-hook'. This allows \\[next-error] to
find the errors."
(interactive)
(if (boundp 'compilation-error-regexp-alist-alist)
(progn
(if (not (assoc 'bsv-xl-1 compilation-error-regexp-alist-alist))
(mapcar
(lambda (item)
(push (car item) compilation-error-regexp-alist)
(push item compilation-error-regexp-alist-alist)
)
bsv-error-regexp-emacs-alist)))))
)
(if (featurep 'xemacs) (add-hook 'compilation-mode-hook 'bsv-error-regexp-add-xemacs))
(if (featurep 'emacs) (add-hook 'compilation-mode-hook 'bsv-error-regexp-add-emacs))
(defconst bsv-directive-re
(eval-when-compile
(bsv-regexp-words
'(
"`case" "`default" "`define" "`else" "`elsif" "`endfor" "`endif"
"`endprotect" "`endswitch" "`endwhile" "`for" "`format" "`if" "`ifdef"
"`ifndef" "`include" "`let" "`protect" "`switch" "`timescale"
"`time_scale" "`undef" "`while" ))))
(defconst bsv-directive-re-1
(concat "[ \t]*" bsv-directive-re))
(defconst bsv-directive-begin
"\\<`\\(for\\|i\\(f\\|fdef\\|fndef\\)\\|switch\\|while\\)\\>")
(defconst bsv-directive-middle
"\\<`\\(else\\|elsif\\|default\\|case\\)\\>")
(defconst bsv-directive-end
"`\\(endfor\\|endif\\|endswitch\\|endwhile\\)\\>")
(defconst bsv-ovm-begin-re
(eval-when-compile
(bsv-regexp-opt
'(
"`ovm_component_utils_begin"
"`ovm_component_param_utils_begin"
"`ovm_field_utils_begin"
"`ovm_object_utils_begin"
"`ovm_object_param_utils_begin"
"`ovm_sequence_utils_begin"
"`ovm_sequencer_utils_begin"
) nil )))
(defconst bsv-ovm-end-re
(eval-when-compile
(bsv-regexp-opt
'(
"`ovm_component_utils_end"
"`ovm_field_utils_end"
"`ovm_object_utils_end"
"`ovm_sequence_utils_end"
"`ovm_sequencer_utils_end"
) nil )))
(defconst bsv-uvm-begin-re
(eval-when-compile
(bsv-regexp-opt
'(
"`uvm_component_utils_begin"
"`uvm_component_param_utils_begin"
"`uvm_field_utils_begin"
"`uvm_object_utils_begin"
"`uvm_object_param_utils_begin"
"`uvm_sequence_utils_begin"
"`uvm_sequencer_utils_begin"
) nil )))
(defconst bsv-uvm-end-re
(eval-when-compile
(bsv-regexp-opt
'(
"`uvm_component_utils_end"
"`uvm_field_utils_end"
"`uvm_object_utils_end"
"`uvm_sequence_utils_end"
"`uvm_sequencer_utils_end"
) nil )))
(defconst bsv-vmm-begin-re
(eval-when-compile
(bsv-regexp-opt
'(
"`vmm_data_member_begin"
"`vmm_env_member_begin"
"`vmm_scenario_member_begin"
"`vmm_subenv_member_begin"
"`vmm_xactor_member_begin"
) nil ) ) )
(defconst bsv-vmm-end-re
(eval-when-compile
(bsv-regexp-opt
'(
"`vmm_data_member_end"
"`vmm_env_member_end"
"`vmm_scenario_member_end"
"`vmm_subenv_member_end"
"`vmm_xactor_member_end"
) nil ) ) )
(defconst bsv-vmm-statement-re
(eval-when-compile
(bsv-regexp-opt
'(
;; "`vmm_xactor_member_enum_array"
"`vmm_\\(data\\|env\\|scenario\\|subenv\\|xactor\\)_member_\\(scalar\\|string\\|enum\\|vmm_data\\|channel\\|xactor\\|subenv\\|user_defined\\)\\(_array\\)?"
;; "`vmm_xactor_member_scalar_array"
;; "`vmm_xactor_member_scalar"
) nil )))
(defconst bsv-ovm-statement-re
(eval-when-compile
(bsv-regexp-opt
'(
;; Statements
"`DUT_ERROR"
"`MESSAGE"
"`dut_error"
"`message"
"`ovm_analysis_imp_decl"
"`ovm_blocking_get_imp_decl"
"`ovm_blocking_get_peek_imp_decl"
"`ovm_blocking_master_imp_decl"
"`ovm_blocking_peek_imp_decl"
"`ovm_blocking_put_imp_decl"
"`ovm_blocking_slave_imp_decl"
"`ovm_blocking_transport_imp_decl"
"`ovm_component_registry"
"`ovm_component_registry_param"
"`ovm_component_utils"
"`ovm_create"
"`ovm_create_seq"
"`ovm_declare_sequence_lib"
"`ovm_do"
"`ovm_do_seq"
"`ovm_do_seq_with"
"`ovm_do_with"
"`ovm_error"
"`ovm_fatal"
"`ovm_field_aa_int_byte"
"`ovm_field_aa_int_byte_unsigned"
"`ovm_field_aa_int_int"
"`ovm_field_aa_int_int_unsigned"
"`ovm_field_aa_int_integer"
"`ovm_field_aa_int_integer_unsigned"
"`ovm_field_aa_int_key"
"`ovm_field_aa_int_longint"
"`ovm_field_aa_int_longint_unsigned"
"`ovm_field_aa_int_shortint"
"`ovm_field_aa_int_shortint_unsigned"
"`ovm_field_aa_int_string"
"`ovm_field_aa_object_int"
"`ovm_field_aa_object_string"
"`ovm_field_aa_string_int"
"`ovm_field_aa_string_string"
"`ovm_field_array_int"
"`ovm_field_array_object"
"`ovm_field_array_string"
"`ovm_field_enum"
"`ovm_field_event"
"`ovm_field_int"
"`ovm_field_object"
"`ovm_field_queue_int"
"`ovm_field_queue_object"
"`ovm_field_queue_string"
"`ovm_field_sarray_int"
"`ovm_field_string"
"`ovm_field_utils"
"`ovm_file"
"`ovm_get_imp_decl"
"`ovm_get_peek_imp_decl"
"`ovm_info"
"`ovm_info1"
"`ovm_info2"
"`ovm_info3"
"`ovm_info4"
"`ovm_line"
"`ovm_master_imp_decl"
"`ovm_msg_detail"
"`ovm_non_blocking_transport_imp_decl"
"`ovm_nonblocking_get_imp_decl"
"`ovm_nonblocking_get_peek_imp_decl"
"`ovm_nonblocking_master_imp_decl"
"`ovm_nonblocking_peek_imp_decl"
"`ovm_nonblocking_put_imp_decl"
"`ovm_nonblocking_slave_imp_decl"
"`ovm_object_registry"
"`ovm_object_registry_param"
"`ovm_object_utils"
"`ovm_peek_imp_decl"
"`ovm_phase_func_decl"
"`ovm_phase_task_decl"
"`ovm_print_aa_int_object"
"`ovm_print_aa_string_int"
"`ovm_print_aa_string_object"
"`ovm_print_aa_string_string"
"`ovm_print_array_int"
"`ovm_print_array_object"
"`ovm_print_array_string"
"`ovm_print_object_queue"
"`ovm_print_queue_int"
"`ovm_print_string_queue"
"`ovm_put_imp_decl"
"`ovm_rand_send"
"`ovm_rand_send_with"
"`ovm_send"
"`ovm_sequence_utils"
"`ovm_slave_imp_decl"
"`ovm_transport_imp_decl"
"`ovm_update_sequence_lib"
"`ovm_update_sequence_lib_and_item"
"`ovm_warning"
"`static_dut_error"
"`static_message") nil )))
(defconst bsv-uvm-statement-re
(eval-when-compile
(bsv-regexp-opt
'(
;; Statements
"`uvm_analysis_imp_decl"
"`uvm_blocking_get_imp_decl"
"`uvm_blocking_get_peek_imp_decl"
"`uvm_blocking_master_imp_decl"
"`uvm_blocking_peek_imp_decl"
"`uvm_blocking_put_imp_decl"
"`uvm_blocking_slave_imp_decl"
"`uvm_blocking_transport_imp_decl"
"`uvm_component_param_utils"
"`uvm_component_registry"
"`uvm_component_registry_param"
"`uvm_component_utils"
"`uvm_create"
"`uvm_create_on"
"`uvm_create_seq" ;; Undocumented in 1.1
"`uvm_declare_p_sequencer"
"`uvm_declare_sequence_lib" ;; Deprecated in 1.1
"`uvm_do"
"`uvm_do_callbacks"
"`uvm_do_callbacks_exit_on"
"`uvm_do_obj_callbacks"
"`uvm_do_obj_callbacks_exit_on"
"`uvm_do_on"
"`uvm_do_on_pri"
"`uvm_do_on_pri_with"
"`uvm_do_on_with"
"`uvm_do_pri"
"`uvm_do_pri_with"
"`uvm_do_seq" ;; Undocumented in 1.1
"`uvm_do_seq_with" ;; Undocumented in 1.1
"`uvm_do_with"
"`uvm_error"
"`uvm_error_context"
"`uvm_fatal"
"`uvm_fatal_context"
"`uvm_field_aa_int_byte"
"`uvm_field_aa_int_byte_unsigned"
"`uvm_field_aa_int_enum"
"`uvm_field_aa_int_int"
"`uvm_field_aa_int_int_unsigned"
"`uvm_field_aa_int_integer"
"`uvm_field_aa_int_integer_unsigned"
"`uvm_field_aa_int_key"
"`uvm_field_aa_int_longint"
"`uvm_field_aa_int_longint_unsigned"
"`uvm_field_aa_int_shortint"
"`uvm_field_aa_int_shortint_unsigned"
"`uvm_field_aa_int_string"
"`uvm_field_aa_object_int"
"`uvm_field_aa_object_string"
"`uvm_field_aa_string_int"
"`uvm_field_aa_string_string"
"`uvm_field_array_enum"
"`uvm_field_array_int"
"`uvm_field_array_object"
"`uvm_field_array_string"
"`uvm_field_enum"
"`uvm_field_event"
"`uvm_field_int"
"`uvm_field_object"
"`uvm_field_queue_enum"
"`uvm_field_queue_int"
"`uvm_field_queue_object"
"`uvm_field_queue_string"
"`uvm_field_real"
"`uvm_field_sarray_enum"
"`uvm_field_sarray_int"
"`uvm_field_sarray_object"
"`uvm_field_sarray_string"
"`uvm_field_string"
"`uvm_field_utils"
"`uvm_file" ;; Undocumented in 1.1, use `__FILE__
"`uvm_get_imp_decl"
"`uvm_get_peek_imp_decl"
"`uvm_info"
"`uvm_info_context"
"`uvm_line" ;; Undocumented in 1.1, use `__LINE__
"`uvm_master_imp_decl"
"`uvm_non_blocking_transport_imp_decl" ;; Deprecated in 1.1
"`uvm_nonblocking_get_imp_decl"
"`uvm_nonblocking_get_peek_imp_decl"
"`uvm_nonblocking_master_imp_decl"
"`uvm_nonblocking_peek_imp_decl"
"`uvm_nonblocking_put_imp_decl"
"`uvm_nonblocking_slave_imp_decl"
"`uvm_nonblocking_transport_imp_decl"
"`uvm_object_param_utils"
"`uvm_object_registry"
"`uvm_object_registry_param" ;; Undocumented in 1.1
"`uvm_object_utils"
"`uvm_pack_array"
"`uvm_pack_arrayN"
"`uvm_pack_enum"
"`uvm_pack_enumN"
"`uvm_pack_int"
"`uvm_pack_intN"
"`uvm_pack_queue"
"`uvm_pack_queueN"
"`uvm_pack_real"
"`uvm_pack_sarray"
"`uvm_pack_sarrayN"
"`uvm_pack_string"
"`uvm_peek_imp_decl"
"`uvm_put_imp_decl"
"`uvm_rand_send"
"`uvm_rand_send_pri"
"`uvm_rand_send_pri_with"
"`uvm_rand_send_with"
"`uvm_record_attribute"
"`uvm_record_field"
"`uvm_register_cb"
"`uvm_send"
"`uvm_send_pri"
"`uvm_sequence_utils" ;; Deprecated in 1.1
"`uvm_set_super_type"
"`uvm_slave_imp_decl"
"`uvm_transport_imp_decl"
"`uvm_unpack_array"
"`uvm_unpack_arrayN"
"`uvm_unpack_enum"
"`uvm_unpack_enumN"
"`uvm_unpack_int"
"`uvm_unpack_intN"
"`uvm_unpack_queue"
"`uvm_unpack_queueN"
"`uvm_unpack_real"
"`uvm_unpack_sarray"
"`uvm_unpack_sarrayN"
"`uvm_unpack_string"
"`uvm_update_sequence_lib" ;; Deprecated in 1.1
"`uvm_update_sequence_lib_and_item" ;; Deprecated in 1.1
"`uvm_warning"
"`uvm_warning_context") nil )))
;;
;; Regular expressions used to calculate indent, etc.
;;
(defconst bsv-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>")
;; Want to match
;; aa :
;; aa,bb :
;; a[34:32] :
;; a,
;; b :
(defconst bsv-assignment-operator-re
(eval-when-compile
(bsv-regexp-opt
`(
;; blocking assignment_operator
"=" "+=" "-=" "*=" "/=" "%=" "&=" "|=" "^=" "<<=" ">>=" "<<<=" ">>>="
;; non blocking assignment operator
"<="
;; comparison
"==" "!=" "===" "!===" "<=" ">=" "==\?" "!=\?"
;; event_trigger
"->" "->>"
;; property_expr
"|->" "|=>"
;; Is this a legal bsv operator?
":="
) 't
)))
(defconst bsv-assignment-operation-re
(concat
; "\\(^\\s-*[A-Za-z0-9_]+\\(\\[\\([A-Za-z0-9_]+\\)\\]\\)*\\s-*\\)"
; "\\(^\\s-*[^=<>+-*/%&|^:\\s-]+[^=<>+-*/%&|^\n]*?\\)"
"\\(^.*?\\)" "\\B" bsv-assignment-operator-re "\\B" ))
(defconst bsv-label-re (concat bsv-symbol-re "\\s-*:\\s-*"))
(defconst bsv-property-re
(concat "\\(" bsv-label-re "\\)?"
"\\(\\(assert\\|assume\\|cover\\)\\>\\s-+\\\\)\\|\\(assert\\)"))
;; "\\(assert\\|assume\\|cover\\)\\s-+property\\>"
(defconst bsv-no-indent-begin-re
"\\<\\(if\\|else\\|while\\|for\\|repeat\\|always\\|always_comb\\|always_ff\\|always_latch\\)\\>")
(defconst bsv-ends-re
;; Parenthesis indicate type of keyword found
(concat
"\\(\\\\)\\|" ; 1
"\\(\\\\)\\|" ; 2
"\\(\\\\)\\|" ; 3
"\\(\\\\)\\|" ; 3.1
"\\(\\\\)\\|" ; 4
"\\(\\\\)\\|" ; 5
"\\(\\\\)\\|" ; 6
"\\(\\\\)\\|" ; 7
"\\(\\\\)\\|" ; 8
"\\(\\\\)\\|" ; 9
"\\(\\\\)\\|" ; 10
"\\(\\\\)\\|" ; 11
"\\(\\\\)\\|" ; 12
;; BSV
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
;; VMM
"\\(\\<`vmm_data_member_end\\>\\)\\|"
"\\(\\<`vmm_env_member_end\\>\\)\\|"
"\\(\\<`vmm_scenario_member_end\\>\\)\\|"
"\\(\\<`vmm_subenv_member_end\\>\\)\\|"
"\\(\\<`vmm_xactor_member_end\\>\\)\\|"
;; OVM
"\\(\\<`ovm_component_utils_end\\>\\)\\|"
"\\(\\<`ovm_field_utils_end\\>\\)\\|"
"\\(\\<`ovm_object_utils_end\\>\\)\\|"
"\\(\\<`ovm_sequence_utils_end\\>\\)\\|"
"\\(\\<`ovm_sequencer_utils_end\\>\\)"
;; UVM
"\\(\\<`uvm_component_utils_end\\>\\)\\|"
"\\(\\<`uvm_field_utils_end\\>\\)\\|"
"\\(\\<`uvm_object_utils_end\\>\\)\\|"
"\\(\\<`uvm_sequence_utils_end\\>\\)\\|"
"\\(\\<`uvm_sequencer_utils_end\\>\\)"
))
(defconst bsv-auto-end-comment-lines-re
;; Matches to names in this list cause auto-end-commenting
(concat "\\("
bsv-directive-re "\\)\\|\\("
(eval-when-compile
(bsv-regexp-words
`( "begin"
"else"
"end"
"endcase"
"endclass"
"endclocking"
"endgroup"
"endfunction"
"endmodule"
"endprogram"
"endprimitive"
"endinterface"
"endpackage"
"endsequence"
"endspecify"
"endtable"
"endtask"
"join"
"join_any"
"join_none"
"module"
"macromodule"
"primitive"
"interface"
"package"
"endinterface"
"endmethod"
"endrule"
"endaction")))
"\\)"))
;;; NOTE: bsv-leap-to-head expects that bsv-end-block-re and
;;; bsv-end-block-ordered-re matches exactly the same strings.
(defconst bsv-end-block-ordered-re
;; Parenthesis indicate type of keyword found
(concat "\\(\\\\)\\|" ; 1
"\\(\\\\)\\|" ; 2
"\\(\\\\)"))
(defconst bsv-end-block-re
(eval-when-compile
(bsv-regexp-words
`("end" ;; closes begin
"endcase" ;; closes any of case, casex casez or randcase
"join" "join_any" "join_none" ;; closes fork
"endclass"
"endtable"
"endspecify"
"endfunction"
"endgenerate"
"endmethod"
"endrule"
"endaction"
"endtask"
"endgroup"
"endproperty"
"endinterface"
"endpackage"
"endprogram"
"endsequence"
"endclocking"
;; OVM
"`ovm_component_utils_end"
"`ovm_field_utils_end"
"`ovm_object_utils_end"
"`ovm_sequence_utils_end"
"`ovm_sequencer_utils_end"
;; UVM
"`uvm_component_utils_end"
"`uvm_field_utils_end"
"`uvm_object_utils_end"
"`uvm_sequence_utils_end"
"`uvm_sequencer_utils_end"
;; VMM
"`vmm_data_member_end"
"`vmm_env_member_end"
"`vmm_scenario_member_end"
"`vmm_subenv_member_end"
"`vmm_xactor_member_end"
))))
(defconst bsv-endcomment-reason-re
;; Parenthesis indicate type of keyword found
(concat
"\\(\\\\)\\|" ; 1
"\\(\\\\)\\|" ; 2
"\\(\\\\s-+\\\\)\\|" ; 3
"\\(\\\\(\[ \t\]*@\\)?\\)\\|" ; 4
"\\(\\\\(\[ \t\]*@\\)?\\)\\|" ; 5
"\\(\\\\(\[ \t\]*@\\)?\\)\\|" ; 6
"\\(\\\\)\\|" ; 7
"\\(\\\\(\[ \t\]*@\\)?\\)\\|"
"\\(\\\\)\\|"
bsv-property-re "\\|"
"\\(\\(" bsv-label-re "\\)?\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(@\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|\\(\\\\)\\|"
"#"))
(defconst bsv-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 bsv-beg-block-re
(eval-when-compile
(bsv-regexp-words
`("begin"
"case" "casex" "casez" "randcase"
"clocking"
"generate"
"method"
"rule"
"action"
"fork"
"function"
"property"
"specify"
"table"
"task"
;; OVM
"`ovm_component_utils_begin"
"`ovm_component_param_utils_begin"
"`ovm_field_utils_begin"
"`ovm_object_utils_begin"
"`ovm_object_param_utils_begin"
"`ovm_sequence_utils_begin"
"`ovm_sequencer_utils_begin"
;; UVM
"`uvm_component_utils_begin"
"`uvm_component_param_utils_begin"
"`uvm_field_utils_begin"
"`uvm_object_utils_begin"
"`uvm_object_param_utils_begin"
"`uvm_sequence_utils_begin"
"`uvm_sequencer_utils_begin"
;; VMM
"`vmm_data_member_begin"
"`vmm_env_member_begin"
"`vmm_scenario_member_begin"
"`vmm_subenv_member_begin"
"`vmm_xactor_member_begin"
))))
;; These are the same words, in a specific order in the regular
;; expression so that matching will work nicely for
;; bsv-forward-sexp and bsv-calc-indent
(defconst bsv-beg-block-re-ordered
( concat "\\(\\\\)" ;1
"\\|\\(\\\\|\\(\\\\)" ; 2,3
"\\|\\(\\(\\\\s-+\\|\\\\s-+\\)?fork\\>\\)" ;4,5
"\\|\\(\\\\)" ;6
"\\|\\(\\\\)" ;7
"\\|\\(\\\\)" ;8
"\\|\\(\\\\)" ;9
"\\|\\(\\(\\(\\\\s-+\\)\\|\\(\\\\s-+\\)\\)*\\\\)" ;10
"\\|\\(\\\\)" ;14
"\\|\\(\\(\\(\\\\s-+\\)\\|\\(\\\\s-+\\)\\)*\\\\)" ;15
"\\|\\(\\\\)" ;18
"\\|\\(\\\\)" ;16 20
"\\|\\(\\(\\(\\\\s-+\\)\\|\\(\\\\s-+\\)\\)*\\\\)" ;17 21
"\\|\\(\\<\\(rand\\)?sequence\\>\\)" ;21 25
"\\|\\(\\\\)" ;22 27
"\\|\\(\\<`[ou]vm_[a-z_]+_begin\\>\\)" ;28
"\\|\\(\\<`vmm_[a-z_]+_member_begin\\>\\)"
"\\|\\(\\\\)"
"\\|\\(\\\\)"
"\\|\\(\\\\)"
;;
))
(defconst bsv-end-block-ordered-rry
[ "\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)"
"\\(\\\\|\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\<\\(rand\\)?sequence\\>\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
"\\(\\\\)\\|\\(\\\\)"
] )
(defconst bsv-nameable-item-re
(eval-when-compile
(bsv-regexp-words
`("begin"
"fork"
"join" "join_any" "join_none"
"end"
"endcase"
"endconfig"
"endclass"
"endclocking"
"endfunction"
"endgenerate"
"endmethod"
"endrule"
"endaction"
"endmodule"
"endprimitive"
"endinterface"
"endpackage"
"endspecify"
"endtable"
"endtask" )
)))
(defconst bsv-declaration-opener
(eval-when-compile
(bsv-regexp-words
`("module" "begin" "task" "function"))))
(defconst bsv-declaration-prefix-re
(eval-when-compile
(bsv-regexp-words
`(
;; port direction
"inout" "input" "output" "ref"
;; changeableness
"const" "static" "protected" "local"
;; parameters
"localparam" "parameterx" "var"
;; type creation
"typedef"
))))
(defconst bsv-declaration-core-re
(eval-when-compile
(bsv-regexp-words
`(
;; port direction (by themselves)
"inout" "input" "output"
;; integer_atom_type
"byte" "shortint" "int" "longint" "integer" "time"
;; integer_vector_type
"bit" "logic" "reg"
;; non_integer_type
"shortreal" "real" "realtime"
;; net_type
"supply0" "supply1" "tri" "triand" "trior" "trireg" "tri0" "tri1" "uwire" "wire" "wand" "wor"
;; misc
"string" "event" "chandle" "virtual" "enum" "genvar"
"struct" "union"
;; builtin classes
"mailbox" "semaphore"
))))
(defconst bsv-declaration-re
(concat "\\(" bsv-declaration-prefix-re "\\s-*\\)?" bsv-declaration-core-re))
(defconst bsv-range-re "\\(\\[[^]]*\\]\\s-*\\)+")
(defconst bsv-optional-signed-re "\\s-*\\(signed\\)?")
(defconst bsv-optional-signed-range-re
(concat
"\\s-*\\(\\<\\(reg\\|wire\\)\\>\\s-*\\)?\\(\\\\s-*\\)?\\(" bsv-range-re "\\)?"))
(defconst bsv-macroexp-re "`\\sw+")
(defconst bsv-delay-re "#\\s-*\\(\\([0-9_]+\\('s?[hdxbo][0-9a-fA-F_xz]+\\)?\\)\\|\\(([^()]*)\\)\\|\\(\\sw+\\)\\)")
(defconst bsv-declaration-re-2-no-macro
(concat "\\s-*" bsv-declaration-re
"\\s-*\\(\\(" bsv-optional-signed-range-re "\\)\\|\\(" bsv-delay-re "\\)"
"\\)?"))
(defconst bsv-declaration-re-2-macro
(concat "\\s-*" bsv-declaration-re
"\\s-*\\(\\(" bsv-optional-signed-range-re "\\)\\|\\(" bsv-delay-re "\\)"
"\\|\\(" bsv-macroexp-re "\\)"
"\\)?"))
(defconst bsv-declaration-re-1-macro
(concat "^" bsv-declaration-re-2-macro))
(defconst bsv-declaration-re-1-no-macro (concat "^" bsv-declaration-re-2-no-macro))
(defconst bsv-defun-re
(eval-when-compile (bsv-regexp-words `("macromodule" "module" "class" "program" "interface" "package" "primitive" "config"))))
(defconst bsv-end-defun-re
(eval-when-compile (bsv-regexp-words `("endmodule" "endclass" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig"))))
(defconst bsv-zero-indent-re
(concat bsv-defun-re "\\|" bsv-end-defun-re))
(defconst bsv-inst-comment-re
(eval-when-compile (bsv-regexp-words `("Outputs" "Inouts" "Inputs" "Interfaces" "Interfaced"))))
(defconst bsv-behavioral-block-beg-re
(eval-when-compile (bsv-regexp-words `("initial" "final" "always" "always_comb" "always_latch" "always_ff"
"function" "task"))))
(defconst bsv-coverpoint-re "\\w+\\s*:\\s*\\(coverpoint\\|cross\\constraint\\)" )
(defconst bsv-indent-re
(eval-when-compile
(bsv-regexp-words
`(
"{"
"always" "always_latch" "always_ff" "always_comb"
"begin" "end"
; "unique" "priority"
"case" "casex" "casez" "randcase" "endcase"
"class" "endclass"
"clocking" "endclocking"
"config" "endconfig"
"covergroup" "endgroup"
"fork" "join" "join_any" "join_none"
"function" "endfunction"
"final"
"generate" "endgenerate"
"method" "endmethod"
"rule" "endrule"
"action" "endaction"
"initial"
"interface" "endinterface"
"module" "macromodule" "endmodule"
"package" "endpackage"
"primitive" "endprimitive"
"program" "endprogram"
"property" "endproperty"
"sequence" "randsequence" "endsequence"
"specify" "endspecify"
"table" "endtable"
"task" "endtask"
"virtual"
"`case"
"`default"
"`define" "`undef"
"`if" "`ifdef" "`ifndef" "`else" "`elsif" "`endif"
"`while" "`endwhile"
"`for" "`endfor"
"`format"
"`include"
"`let"
"`protect" "`endprotect"
"`switch" "`endswitch"
"`timescale"
"`time_scale"
;; OVM Begin tokens
"`ovm_component_utils_begin"
"`ovm_component_param_utils_begin"
"`ovm_field_utils_begin"
"`ovm_object_utils_begin"
"`ovm_object_param_utils_begin"
"`ovm_sequence_utils_begin"
"`ovm_sequencer_utils_begin"
;; OVM End tokens
"`ovm_component_utils_end"
"`ovm_field_utils_end"
"`ovm_object_utils_end"
"`ovm_sequence_utils_end"
"`ovm_sequencer_utils_end"
;; UVM Begin tokens
"`uvm_component_utils_begin"
"`uvm_component_param_utils_begin"
"`uvm_field_utils_begin"
"`uvm_object_utils_begin"
"`uvm_object_param_utils_begin"
"`uvm_sequence_utils_begin"
"`uvm_sequencer_utils_begin"
;; UVM End tokens
"`uvm_component_utils_end" ;; Typo in spec, it's not uvm_component_end
"`uvm_field_utils_end"
"`uvm_object_utils_end"
"`uvm_sequence_utils_end"
"`uvm_sequencer_utils_end"
;; VMM Begin tokens
"`vmm_data_member_begin"
"`vmm_env_member_begin"
"`vmm_scenario_member_begin"
"`vmm_subenv_member_begin"
"`vmm_xactor_member_begin"
;; VMM End tokens
"`vmm_data_member_end"
"`vmm_env_member_end"
"`vmm_scenario_member_end"
"`vmm_subenv_member_end"
"`vmm_xactor_member_end"
))))
(defconst bsv-defun-level-not-generate-re
(eval-when-compile
(bsv-regexp-words
`( "module" "macromodule" "primitive" "class" "program"
"interface" "package" "config"))))
(defconst bsv-defun-level-re
(eval-when-compile
(bsv-regexp-words
(append
`( "module" "macromodule" "primitive" "class" "program"
"interface" "package" "config")
`( "initial" "final" "always" "always_comb" "always_ff"
"always_latch" "endtask" "endfunction" )))))
(defconst bsv-defun-level-generate-only-re
(eval-when-compile
(bsv-regexp-words
`( "initial" "final" "always" "always_comb" "always_ff"
"always_latch" "endtask" "endfunction"))))
(defconst bsv-cpp-level-re
(eval-when-compile
(bsv-regexp-words
`(
"endmodule" "endprimitive" "endinterface" "endpackage" "endprogram" "endclass"
))))
(defconst bsv-disable-fork-re "\\(disable\\|wait\\)\\s-+fork\\>")
(defconst bsv-extended-case-re "\\(unique\\s-+\\|priority\\s-+\\)?case[xz]?")
(defconst bsv-extended-complete-re
(concat "\\(\\\\s-+\\)?virtual\\s-+\\|\\\\|\\\\)"
"\\|\\(\\\\s-+\\)*\\(\\\\|\\\\|\\\\)"
"\\|\\(\\\\s-+\\)?\"DPI-C\"\\s-+\\(function\\>\\|task\\>\\)"
"\\|" bsv-extended-case-re ))
(defconst bsv-basic-complete-re
(eval-when-compile
(bsv-regexp-words
`(
"always" "assign" "always_latch" "always_ff" "always_comb" "constraint"
"import" "initial" "final" "module" "macromodule" "repeat" "randcase" "while"
"if" "for" "forever" "foreach" "else" "parameterx" "do" "localparam" "assert"
))))
(defconst bsv-complete-reg
(concat
bsv-extended-complete-re
"\\|"
bsv-basic-complete-re))
(defconst bsv-end-statement-re
(concat "\\(" bsv-beg-block-re "\\)\\|\\("
bsv-end-block-re "\\)"))
(defconst bsv-endcase-re
(concat bsv-extended-case-re "\\|"
"\\(endcase\\)\\|"
bsv-defun-re
))
(defconst bsv-exclude-str-start "/* -----\\/----- EXCLUDED -----\\/-----"
"String used to mark beginning of excluded text.")
(defconst bsv-exclude-str-end " -----/\\----- EXCLUDED -----/\\----- */"
"String used to mark end of excluded text.")
(defconst bsv-preprocessor-re
(eval-when-compile
(bsv-regexp-words
`(
"`define" "`include" "`ifdef" "`ifndef" "`if" "`endif" "`else"
))))
(defconst bsv-keywords
'( "`case" "`default" "`define" "`else" "`endfor" "`endif"
"`endprotect" "`endswitch" "`endwhile" "`for" "`format" "`if" "`ifdef"
"`ifndef" "`include" "`let" "`protect" "`switch" "`timescale"
"`time_scale" "`undef" "`while"
"method" "endmethod" "rule" "endrule" "action" "endaction"
"seq" "endseq" "par" "endpar" "rules" "endrules"
"provisos" "return" "parameterx" "deriving"
"typeclass" "endtypeclass" "instance" "endinstance"
"after" "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" "mailbox" "matches" "medium" "modport" "module"
"nand" "negedge" "new" "nmos" "nor" "noshowcancelled" "not"
"notif0" "notif1" "null" "or" "output" "package" "packed"
"parameterx" "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" "semaphore" "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" "uwire" "var" "vectored" "virtual" "void"
"wait" "wait_order" "wand" "weak0" "weak1" "while" "wildcard"
"wire" "with" "within" "wor" "xnor" "xor"
;; 1800-2009
"accept_on" "checker" "endchecker" "eventually" "global" "implies"
"let" "nexttime" "reject_on" "restrict" "s_always" "s_eventually"
"s_nexttime" "s_until" "s_until_with" "strong" "sync_accept_on"
"sync_reject_on" "unique0" "until" "until_with" "untyped" "weak"
)
"List of BSV keywords.")
(defconst bsv-comment-start-regexp "//\\|/\\*"
"Dual comment value for `comment-start-regexp'.")
(defvar bsv-mode-syntax-table
(let ((table (make-syntax-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)
;; Set up TABLE to handle block and line style comments.
(if (featurep 'xemacs)
(progn
;; XEmacs (formerly Lucid) has the best implementation
(modify-syntax-entry ?/ ". 1456" table)
(modify-syntax-entry ?* ". 23" table)
(modify-syntax-entry ?\n "> b" table))
;; Emacs 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))
table)
"Syntax table used in BSV mode buffers.")
(defvar bsv-font-lock-keywords nil
"Default highlighting for BSV mode.")
(defvar bsv-font-lock-keywords-1 nil
"Subdued level highlighting for BSV mode.")
(defvar bsv-font-lock-keywords-2 nil
"Medium level highlighting for BSV mode.
See also `bsv-font-lock-extra-types'.")
(defvar bsv-font-lock-keywords-3 nil
"Gaudy level highlighting for BSV mode.
See also `bsv-font-lock-extra-types'.")
(defvar bsv-font-lock-translate-off-face
'bsv-font-lock-translate-off-face
"Font to use for translated off regions.")
(defface bsv-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 bsv-font-lock-p1800-face
'bsv-font-lock-p1800-face
"Font to use for p1800 keywords.")
(defface bsv-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)
(defvar bsv-font-lock-ams-face
'bsv-font-lock-ams-face
"Font to use for Analog/Mixed Signal keywords.")
(defface bsv-font-lock-ams-face
'((((class color)
(background light))
(:foreground "Purple" :bold t ))
(((class color)
(background dark))
(:foreground "orange1" :bold t ))
(t (:italic t)))
"Font lock mode face used to highlight AMS keywords."
:group 'font-lock-highlighting-faces)
(defvar bsv-font-grouping-keywords-face
'bsv-font-lock-grouping-keywords-face
"Font to use for BSV Grouping Keywords (such as begin..end).")
(defface bsv-font-lock-grouping-keywords-face
'((((class color)
(background light))
(:foreground "red4" :bold t ))
(((class color)
(background dark))
(:foreground "red4" :bold t ))
(t (:italic t)))
"Font lock mode face used to highlight bsv grouping keywords."
:group 'font-lock-highlighting-faces)
(let* ((bsv-type-font-keywords
(eval-when-compile
(bsv-regexp-opt
'(
"and" "bit" "buf" "bufif0" "bufif1" "cmos" "defparam"
"event" "genvar" "inout" "input" "integer" "localparam"
"logic" "mailbox" "nand" "nmos" "not" "notif0" "notif1" "or"
"output" "parameterx" "pmos" "pull0" "pull1" "pulldown" "pullup"
"rcmos" "real" "realtime" "reg" "rnmos" "rpmos" "rtran"
"rtranif0" "rtranif1" "semaphore" "signed" "struct" "supply"
"supply0" "supply1" "time" "tran" "tranif0" "tranif1"
"tri" "tri0" "tri1" "triand" "trior" "trireg" "typedef"
"uwire" "vectored" "wand" "wire" "wor" "xnor" "xor"
) nil )))
(bsv-type-types
(eval-when-compile
(bsv-regexp-opt
'(
"enum"
) nil )))
(bsv-pragma-keywords
(eval-when-compile
(bsv-regexp-opt
'("surefire" "synopsys" "rtl_synthesis" "verilint" "leda" "0in") nil
)))
(bsv-attr-keywords
(eval-when-compile
(bsv-regexp-opt
'("synthesize" "noinline" "always_enabled" "always_ready" "preempts"
"parameter"
"no_implicit_conditions" "fire_when_enabled"
"clocked_by" "reset_by"
"aggressive_implicit_conditions" "options") nil
)))
(bsv-1800-2005-keywords
(eval-when-compile
(bsv-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 )))
(bsv-1800-2009-keywords
(eval-when-compile
(bsv-regexp-opt
'("accept_on" "checker" "endchecker" "eventually" "global"
"implies" "let" "nexttime" "reject_on" "restrict" "s_always"
"s_eventually" "s_nexttime" "s_until" "s_until_with" "strong"
"sync_accept_on" "sync_reject_on" "unique0" "until"
"until_with" "untyped" "weak" ) nil )))
(bsv-ams-keywords
(eval-when-compile
(bsv-regexp-opt
'("above" "abs" "absdelay" "acos" "acosh" "ac_stim"
"aliasparam" "analog" "analysis" "asin" "asinh" "atan" "atan2" "atanh"
"branch" "ceil" "connectmodule" "connectrules" "cos" "cosh" "ddt"
"ddx" "discipline" "driver_update" "enddiscipline" "endconnectrules"
"endnature" "endparamset" "exclude" "exp" "final_step" "flicker_noise"
"floor" "flow" "from" "ground" "hypot" "idt" "idtmod" "inf"
"initial_step" "laplace_nd" "laplace_np" "laplace_zd" "laplace_zp"
"last_crossing" "limexp" "ln" "log" "max" "min" "nature"
"net_resolution" "noise_table" "paramset" "potential" "pow" "sin"
"sinh" "slew" "sqrt" "tan" "tanh" "timer" "transition" "white_noise"
"wreal" "zi_nd" "zi_np" "zi_zd" ) nil )))
(bsv-font-keywords
(eval-when-compile
(bsv-regexp-opt
'(
"assign" "case" "casex" "casez" "randcase" "deassign"
"default" "disable" "else" "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"
"method" "endmethod" "rule" "endrule" "action" "endaction"
"seq" "endseq" "par" "endpar" "rules" "endrules"
"let" "begin" "end" "import" "type" "matches" "tagged" "union"
;; "Eq" "Bits" "Bounded" "FShow"
"typedef" "enum" "struct"
"provisos" "return" "parameterx" "deriving"
"typeclass" "endtypeclass" "instance" "endinstance"
) nil )))
(bsv-font-grouping-keywords
(eval-when-compile
(bsv-regexp-opt
'( "begin" "end" ) nil ))))
(setq bsv-font-lock-keywords
(list
;; Fontify all builtin keywords
(concat "\\<\\(" bsv-font-keywords "\\|"
;; And user/system tasks and functions
"\\$[a-zA-Z][a-zA-Z0-9_\\$]*"
"\\)\\>")
;; Fontify all types
(if bsv-highlight-grouping-keywords
(cons (concat "\\<\\(" bsv-font-grouping-keywords "\\)\\>")
'bsv-font-lock-ams-face)
(cons (concat "\\<\\(" bsv-font-grouping-keywords "\\)\\>")
'font-lock-type-face))
(cons (concat "\\<\\(" bsv-type-font-keywords "\\)\\>")
'font-lock-type-face)
;; Fontify IEEE-1800-2005 keywords appropriately
(if bsv-highlight-p1800-keywords
(cons (concat "\\<\\(" bsv-1800-2005-keywords "\\)\\>")
'bsv-font-lock-p1800-face)
(cons (concat "\\<\\(" bsv-1800-2005-keywords "\\)\\>")
'font-lock-type-face))
;; Fontify IEEE-1800-2009 keywords appropriately
(if bsv-highlight-p1800-keywords
(cons (concat "\\<\\(" bsv-1800-2009-keywords "\\)\\>")
'bsv-font-lock-p1800-face)
(cons (concat "\\<\\(" bsv-1800-2009-keywords "\\)\\>")
'font-lock-type-face))
;; Fontify BSV-AMS keywords
;; (cons (concat "\\<\\(" bsv-ams-keywords "\\)\\>")
;; 'bsv-font-lock-ams-face)
))
(setq bsv-font-lock-keywords-1
(append bsv-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-+\\([a-z]+\\sw+\\)" )
'(1 font-lock-keyword-face)
'(3 font-lock-constant-face prepend))
'("\\\\s-+\\(\\[[^]]+\\]\\)\\s-+\\([a-z]+\\sw+\\)"
(1 font-lock-keyword-face)
(2 font-lock-constant-face append))
'("\\\\s-+\\([a-z]+\\sw+\\)"
1 'font-lock-constant-face append))))
(setq bsv-font-lock-keywords-2
(append bsv-font-lock-keywords-1
(list
(cons (concat "\\<\\(" bsv-type-types "\\)\\>")
'font-lock-type-face)
;; Fontify bsv attributes
(cons (concat "\\<\\(" bsv-attr-keywords "\\)\\>")
'font-lock-constant-face)
;; Fontify pragmas
(concat "\\(//\\s-*" bsv-pragma-keywords "\\s-.*\\)")
;; Fontify escaped names
'("\\(\\\\\\S-*\\s-\\)" 0 font-lock-function-name-face)
; '("\\(//\\s-*synthesize\\)" 0 font-lock-constant-face)
;; Fontify macro definitions/ uses
'("`\\s-*[A-Za-z][A-Za-z0-9_]*" 0 (if (boundp 'font-lock-preprocessor-face)
'font-lock-preprocessor-face
'font-lock-type-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-z0-9_.]+\\([A-Za-z][A-Za-z0-9_]*\\)\\s-*(" 1 font-lock-function-name-face)
'("<-[^A-Za-z0-9_.]+\\([A-Za-z][A-Za-z0-9_]*\\)\\s-*;" 1 font-lock-function-name-face)
'("(+\\([A-Za-z][A-Za-z0-9_]*\\)\\s-*(" 1 font-lock-function-name-face)
'("rule\\s-+\\([A-Za-z][A-Za-z0-9_]*\\)\\s-+" 1 font-lock-function-name-face)
'("rule\\s-+\\([A-Za-z][A-Za-z0-9_]*\\);" 1 font-lock-function-name-face)
'("[^A-Za-z0-9_.]+\\([A-Z]+[A-Za-z0-9_]*\\)" 1 font-lock-type-face)
)))
(setq bsv-font-lock-keywords-3
(append bsv-font-lock-keywords-2
(when bsv-highlight-translate-off
(list
;; Fontify things in translate off regions
'(bsv-match-translate-off
(0 'bsv-font-lock-translate-off-face prepend))
)))))
;;
;; Buffer state preservation
(defmacro bsv-save-buffer-state (&rest body)
"Execute BODY forms, saving state around insignificant change.
Changes in text properties like `face' or `syntax-table' are
considered insignificant. This macro allows text properties to
be changed, even in a read-only buffer.
A change is considered significant if it affects the buffer text
in any way that isn't completely restored again. Any
user-visible changes to the buffer must not be within a
`bsv-save-buffer-state'."
;; From c-save-buffer-state
`(let* ((modified (buffer-modified-p))
(buffer-undo-list t)
(inhibit-read-only t)
(inhibit-point-motion-hooks t)
(bsv-no-change-functions t)
before-change-functions
after-change-functions
deactivate-mark
buffer-file-name ; Prevent primitives checking
buffer-file-truename) ; for file modification
(unwind-protect
(progn ,@body)
(and (not modified)
(buffer-modified-p)
(set-buffer-modified-p nil)))))
(defmacro bsv-save-no-change-functions (&rest body)
"Execute BODY forms, disabling all change hooks in BODY.
For insignificant changes, see instead `bsv-save-buffer-state'."
`(let* ((inhibit-point-motion-hooks t)
(bsv-no-change-functions t)
before-change-functions
after-change-functions)
(progn ,@body)))
;;
;; Comment detection and caching
(defvar bsv-scan-cache-preserving nil
"If set, the specified buffer's comment properties are static.
Buffer changes will be ignored. See `bsv-inside-comment-or-string-p'
and `bsv-scan'.")
(defvar bsv-scan-cache-tick nil
"Modification tick at which `bsv-scan' was last completed.")
(make-variable-buffer-local 'bsv-scan-cache-tick)
(defun bsv-scan-cache-flush ()
"Flush the `bsv-scan' cache."
(setq bsv-scan-cache-tick nil))
(defun bsv-scan-cache-ok-p ()
"Return t iff the scan cache is up to date."
(or (and bsv-scan-cache-preserving
(eq bsv-scan-cache-preserving (current-buffer))
bsv-scan-cache-tick)
(equal bsv-scan-cache-tick (buffer-chars-modified-tick))))
(defmacro bsv-save-scan-cache (&rest body)
"Execute the BODY forms, allowing scan cache preservation within BODY.
This requires that insertions must use `bsv-insert'."
;; If the buffer is out of date, trash it, as we'll not check later the tick
;; Note this must work properly if there's multiple layers of calls
;; to bsv-save-scan-cache even with differing ticks.
`(progn
(unless (bsv-scan-cache-ok-p) ;; Must be before let
(setq bsv-scan-cache-tick nil))
(let* ((bsv-scan-cache-preserving (current-buffer)))
(progn ,@body))))
(defun bsv-scan-region (beg end)
"Parse between BEG and END for `bsv-inside-comment-or-string-p'.
This creates v-cmts properties where comments are in force."
;; Why properties and not overlays? Overlays have much slower non O(1)
;; lookup times.
;; This function is warm - called on every bsv-insert
(save-excursion
(save-match-data
(bsv-save-buffer-state
(let (pt)
(goto-char beg)
(while (< (point) end)
(cond ((looking-at "//")
(setq pt (point))
(or (search-forward "\n" end t)
(goto-char end))
;; "1+": The leading // or /* itself isn't considered as
;; being "inside" the comment, so that a (search-backward)
;; that lands at the start of the // won't mis-indicate
;; it's inside a comment. Also otherwise it would be
;; hard to find a commented out /*AS*/ vs one that isn't
(put-text-property (1+ pt) (point) 'v-cmts t))
((looking-at "/\\*")
(setq pt (point))
(or (search-forward "*/" end t)
;; No error - let later code indicate it so we can
;; use inside functions on-the-fly
;;(error "%s: Unmatched /* */, at char %d"
;; (bsv-point-text) (point))
(goto-char end))
(put-text-property (1+ pt) (point) 'v-cmts t))
((looking-at "\"")
(setq pt (point))
(or (re-search-forward "[^\\]\"" end t) ;; don't forward-char first, since we look for a non backslash first
;; No error - let later code indicate it so we can
(goto-char end))
(put-text-property (1+ pt) (point) 'v-cmts t))
(t
(forward-char 1)
(if (re-search-forward "[/\"]" end t)
(backward-char 1)
(goto-char end))))))))))
(defun bsv-scan ()
"Parse the buffer, marking all comments with properties.
Also assumes any text inserted since `bsv-scan-cache-tick'
either is ok to parse as a non-comment, or `bsv-insert' was used."
;; See also `bsv-scan-debug' and `bsv-scan-and-debug'
(unless (bsv-scan-cache-ok-p)
(save-excursion
(bsv-save-buffer-state
(when bsv-debug
(message "Scanning %s cache=%s cachetick=%S tick=%S" (current-buffer)
bsv-scan-cache-preserving bsv-scan-cache-tick
(buffer-chars-modified-tick)))
(remove-text-properties (point-min) (point-max) '(v-cmts nil))
(bsv-scan-region (point-min) (point-max))
(setq bsv-scan-cache-tick (buffer-chars-modified-tick))
(when bsv-debug (message "Scanning... done"))))))
(defun bsv-scan-debug ()
"For debugging, show with display face results of `bsv-scan'."
(font-lock-mode 0)
;;(if dbg (setq dbg (concat dbg (format "bsv-scan-debug\n"))))
(save-excursion
(goto-char (point-min))
(remove-text-properties (point-min) (point-max) '(face nil))
(while (not (eobp))
(cond ((get-text-property (point) 'v-cmts)
(put-text-property (point) (1+ (point)) `face 'underline)
;;(if dbg (setq dbg (concat dbg (format " v-cmts at %S\n" (point)))))
(forward-char 1))
(t
(goto-char (or (next-property-change (point)) (point-max))))))))
(defun bsv-scan-and-debug ()
"For debugging, run `bsv-scan' and `bsv-scan-debug'."
(let (bsv-scan-cache-preserving
bsv-scan-cache-tick)
(goto-char (point-min))
(bsv-scan)
(bsv-scan-debug)))
(defun bsv-inside-comment-or-string-p (&optional pos)
"Check if optional point POS is inside a comment.
This may require a slow pre-parse of the buffer with `bsv-scan'
to establish comment properties on all text."
;; This function is very hot
(bsv-scan)
(if pos
(and (>= pos (point-min))
(get-text-property pos 'v-cmts))
(get-text-property (point) 'v-cmts)))
(defun bsv-insert (&rest stuff)
"Insert STUFF arguments, tracking for `bsv-inside-comment-or-string-p'.
Any insert that includes a comment must have the entire commente
inserted using a single call to `bsv-insert'."
(let ((pt (point)))
(while stuff
(insert (car stuff))
(setq stuff (cdr stuff)))
(bsv-scan-region pt (point))))
;; More searching
(defun bsv-declaration-end ()
(search-forward ";"))
(defun bsv-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 (1+ (count-lines (point-min) (or pointnum (point)))))))
(defun electric-bsv-backward-sexp ()
"Move backward over one balanced expression."
(interactive)
;; before that see if we are in a comment
(bsv-backward-sexp))
(defun electric-bsv-forward-sexp ()
"Move forward over one balanced expression."
(interactive)
;; before that see if we are in a comment
(bsv-forward-sexp))
;;;used by hs-minor-mode
(defun bsv-forward-sexp-function (arg)
(if (< arg 0)
(bsv-backward-sexp)
(bsv-forward-sexp)))
(defun bsv-backward-sexp ()
(let ((reg)
(elsec 1)
(found nil)
(st (point)))
(if (not (looking-at "\\<"))
(forward-word -1))
(cond
((bsv-skip-backward-comment-or-string))
((looking-at "\\")
(setq reg (concat
bsv-end-block-re
"\\|\\(\\\\)"
"\\|\\(\\\\)"))
(while (and (not found)
(bsv-re-search-backward reg nil 'move))
(cond
((match-end 1) ; matched bsv-end-block-re
; try to leap back to matching outward block by striding across
; indent level changing tokens then immediately
; previous line governs indentation.
(bsv-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 bsv-end-block-re)
(bsv-leap-to-head))
((looking-at "\\(endmodule\\>\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)")
(cond
((match-end 1)
(bsv-re-search-backward "\\<\\(macro\\)?module\\>" nil 'move))
((match-end 2)
(bsv-re-search-backward "\\" nil 'move))
((match-end 3)
(bsv-re-search-backward "\\" nil 'move))
((match-end 4)
(bsv-re-search-backward "\\" nil 'move))
((match-end 5)
(bsv-re-search-backward "\\" nil 'move))
((match-end 6)
(bsv-re-search-backward "\\" nil 'move))
(t
(goto-char st)
(backward-sexp 1))))
(t
(goto-char st)
(backward-sexp)))))
(defun bsv-forward-sexp ()
(let ((reg)
(md 2)
(st (point))
(nest 'yes))
(if (not (looking-at "\\<"))
(forward-word -1))
(cond
((bsv-skip-forward-comment-or-string)
(bsv-forward-syntactic-ws))
((looking-at bsv-beg-block-re-ordered)
(cond
((match-end 1);
;; Search forward for matching end
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 2)
;; Search forward for matching endcase
(setq reg "\\(\\\\|\\(\\\\s-+\\|\\\\s-+\\)?\\[^:]\\)\\|\\(\\\\)" )
(setq md 3) ;; ender is third item in regexp
)
((match-end 4)
;; might be "disable fork" or "wait fork"
(let
(here)
(if (or
(looking-at bsv-disable-fork-re)
(and (looking-at "fork")
(progn
(setq here (point)) ;; sometimes a fork is just a fork
(forward-word -1)
(looking-at bsv-disable-fork-re))))
(progn ;; it is a disable fork; ignore it
(goto-char (match-end 0))
(forward-word 1)
(setq reg nil))
(progn ;; it is a nice simple fork
(goto-char here) ;; return from looking for "disable fork"
;; Search forward for matching join
(setq reg "\\(\\\\)\\|\\(\\\\)" )))))
((match-end 6)
;; Search forward for matching endclass
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 7)
;; Search forward for matching endtable
(setq reg "\\" )
(setq nest 'no))
((match-end 8)
;; Search forward for matching endspecify
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 9)
;; Search forward for matching endfunction
(setq reg "\\" )
(setq nest 'no))
((match-end 10)
;; Search forward for matching endfunction
(setq reg "\\" )
(setq nest 'no))
((match-end 14)
;; Search forward for matching endtask
(setq reg "\\" )
(setq nest 'no))
((match-end 15)
;; Search forward for matching endtask
(setq reg "\\" )
(setq nest 'no))
((match-end 19)
;; Search forward for matching endgenerate
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 20)
;; Search forward for matching endgroup
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 21)
;; Search forward for matching endproperty
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 25)
;; Search forward for matching endsequence
(setq reg "\\(\\<\\(rand\\)?sequence\\>\\)\\|\\(\\\\)" )
(setq md 3)) ; 3 to get to endsequence in the reg above
((match-end 27)
;; Search forward for matching endclocking
(setq reg "\\(\\\\)\\|\\(\\\\)" )))
(if (and reg
(forward-word 1))
(catch 'skip
(if (eq nest 'yes)
(let ((depth 1)
here)
(while (bsv-re-search-forward reg nil 'move)
(cond
((match-end md) ; a closer in regular expression, so we are climbing out
(setq depth (1- depth))
(if (= 0 depth) ; we are out!
(throw 'skip 1)))
((match-end 1) ; an opener in the r-e, so we are in deeper now
(setq here (point)) ; remember where we started
(goto-char (match-beginning 1))
(cond
((if (or
(looking-at bsv-disable-fork-re)
(and (looking-at "fork")
(progn
(forward-word -1)
(looking-at bsv-disable-fork-re))))
(progn ;; it is a disable fork; another false alarm
(goto-char (match-end 0)))
(progn ;; it is a simple fork (or has nothing to do with fork)
(goto-char here)
(setq depth (1+ depth))))))))))
(if (bsv-re-search-forward reg nil 'move)
(throw 'skip 1))))))
((looking-at (concat
"\\(\\<\\(macro\\)?module\\>\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)\\|"
"\\(\\\\)"))
(cond
((match-end 1)
(bsv-re-search-forward "\\" nil 'move))
((match-end 2)
(bsv-re-search-forward "\\" nil 'move))
((match-end 3)
(bsv-re-search-forward "\\" nil 'move))
((match-end 4)
(bsv-re-search-forward "\\" nil 'move))
((match-end 5)
(bsv-re-search-forward "\\" nil 'move))
((match-end 6)
(bsv-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))))))
(defun bsv-declaration-beg ()
(bsv-re-search-backward bsv-declaration-re (bobp) t))
;;
;;
;; Mode
;;
(defvar bsv-which-tool 1)
;;;###autoload
(define-derived-mode bsv-mode prog-mode "BSV"
"Major mode for editing BSV code.
\\
See \\[describe-function] bsv-auto (\\[bsv-auto]) for details on how
AUTOs can improve coding efficiency.
Use \\[bsv-faq] for a pointer to frequently asked questions.
NEWLINE, TAB indents for BSV code.
Delete converts tabs to spaces as it moves back.
Supports highlighting.
Turning on BSV mode calls the value of the variable `bsv-mode-hook'
with no args, if that value is non-nil.
Variables controlling indentation/edit style:
variable `bsv-indent-level' (default 3)
Indentation of BSV statements with respect to containing block.
`bsv-indent-level-module' (default 3)
Absolute indentation of Module level BSV statements.
Set to 0 to get initial and always statements lined up
on the left side of your screen.
`bsv-indent-level-declaration' (default 3)
Indentation of declarations with respect to containing block.
Set to 0 to get them list right under containing block.
`bsv-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.
`bsv-indent-level-directive' (default 1)
Indentation of `ifdef/`endif blocks.
`bsv-cexp-indent' (default 1)
Indentation of BSV statements broken across lines i.e.:
if (a)
begin
`bsv-case-indent' (default 2)
Indentation for case statements.
`bsv-auto-newline' (default nil)
Non-nil means automatically newline after semicolons and the punctuation
mark after an end.
`bsv-auto-indent-on-newline' (default t)
Non-nil means automatically indent line after newline.
`bsv-tab-always-indent' (default t)
Non-nil means TAB in BSV mode should always reindent the current line,
regardless of where in the line point is when the TAB command is used.
`bsv-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 `bsv-cexp-indent'
otherwise you get:
if (a)
begin
`bsv-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.
`bsv-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.
`bsv-auto-lineup' (default 'declarations)
List of contexts where auto lineup of code should be done.
Variables controlling other actions:
`bsv-linter' (default surelint)
Unix program to call to run the lint checker. This is the default
command for \\[compile-command] and \\[bsv-auto-save-compile].
See \\[customize] for the complete list of variables.
AUTO expansion functions are, in part:
\\[bsv-auto] Expand AUTO statements.
\\[bsv-delete-auto] Remove the AUTOs.
\\[bsv-inject-auto] Insert AUTOs for the first time.
Some other functions are:
\\[bsv-complete-word] Complete word with appropriate possibilities.
\\[bsv-mark-defun] Mark function.
\\[bsv-beg-of-defun] Move to beginning of current function.
\\[bsv-end-of-defun] Move to end of current function.
\\[bsv-label-be] Label matching begin ... end, fork ... join, etc statements.
\\[bsv-comment-region] Put marked area in a comment.
\\[bsv-uncomment-region] Uncomment an area commented with \\[bsv-comment-region].
\\[bsv-insert-block] Insert begin ... end.
\\[bsv-star-comment] Insert /* ... */.
\\[bsv-sk-always] Insert an always @(AS) begin .. end block.
\\[bsv-sk-begin] Insert a begin .. end block.
\\[bsv-sk-case] Insert a case block, prompting for details.
\\[bsv-sk-for] Insert a for (...) begin .. end block, prompting for details.
\\[bsv-sk-generate] Insert a generate .. endgenerate block.
\\[bsv-sk-header] Insert a header block at the top of file.
\\[bsv-sk-initial] Insert an initial begin .. end block.
\\[bsv-sk-fork] Insert a fork begin .. end .. join block.
\\[bsv-sk-module] Insert a module .. (/*AUTOARG*/);.. endmodule block.
\\[bsv-sk-ovm-class] Insert an OVM Class block.
\\[bsv-sk-uvm-class] Insert an UVM Class block.
\\[bsv-sk-primitive] Insert a primitive .. (.. );.. endprimitive block.
\\[bsv-sk-repeat] Insert a repeat (..) begin .. end block.
\\[bsv-sk-specify] Insert a specify .. endspecify block.
\\[bsv-sk-task] Insert a task .. begin .. end endtask block.
\\[bsv-sk-while] Insert a while (...) begin .. end block, prompting for details.
\\[bsv-sk-casex] Insert a casex (...) item: begin.. end endcase block, prompting for details.
\\[bsv-sk-casez] Insert a casez (...) item: begin.. end endcase block, prompting for details.
\\[bsv-sk-if] Insert an if (..) begin .. end block.
\\[bsv-sk-else-if] Insert an else if (..) begin .. end block.
\\[bsv-sk-comment] Insert a comment block.
\\[bsv-sk-assign] Insert an assign .. = ..; statement.
\\[bsv-sk-function] Insert a function .. begin .. end endfunction block.
\\[bsv-sk-input] Insert an input declaration, prompting for details.
\\[bsv-sk-output] Insert an output declaration, prompting for details.
\\[bsv-sk-state-machine] Insert a state machine definition, prompting for details.
\\[bsv-sk-inout] Insert an inout declaration, prompting for details.
\\[bsv-sk-wire] Insert a wire declaration, prompting for details.
\\[bsv-sk-reg] Insert a register declaration, prompting for details.
\\[bsv-sk-define-signal] Define signal under point as a register at the top of the module.
All key bindings can be seen in a BSV-buffer with \\[describe-bindings].
Key bindings specific to `bsv-mode-map' are:
\\{bsv-mode-map}"
:abbrev-table bsv-mode-abbrev-table
(set (make-local-variable 'beginning-of-defun-function)
'bsv-beg-of-defun)
(set (make-local-variable 'end-of-defun-function)
'bsv-end-of-defun)
(set-syntax-table bsv-mode-syntax-table)
(set (make-local-variable 'indent-line-function)
#'bsv-indent-line)
(setq comment-indent-function 'bsv-comment-indent)
(set (make-local-variable 'parse-sexp-ignore-comments) nil)
(set (make-local-variable 'comment-start) "// ")
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
(set (make-local-variable 'comment-multi-line) nil)
;; Set up for compilation
(setq bsv-which-tool 1)
(setq bsv-tool 'bsv-compiler)
(bsv-set-compile-command)
(when (boundp 'hack-local-variables-hook) ;; Also modify any file-local-variables
(add-hook 'hack-local-variables-hook 'bsv-modify-compile-command t))
;; Setting up menus
(when (featurep 'xemacs)
(easy-menu-add bsv-stmt-menu)
(easy-menu-add bsv-menu)
(setq mode-popup-menu (cons "BSV Mode" bsv-stmt-menu)))
;; Stuff for GNU Emacs
(set (make-local-variable 'font-lock-defaults)
`((bsv-font-lock-keywords bsv-font-lock-keywords-1
bsv-font-lock-keywords-2
bsv-font-lock-keywords-3)
nil nil nil
,(if (functionp 'syntax-ppss)
;; bsv-beg-of-defun uses syntax-ppss, and syntax-ppss uses
;; font-lock-beginning-of-syntax-function, so
;; font-lock-beginning-of-syntax-function, can't use
;; bsv-beg-of-defun.
nil
'bsv-beg-of-defun)))
;;------------------------------------------------------------
;; now hook in 'bsv-highlight-include-files (eldo-mode.el&spice-mode.el)
;; all buffer local:
(unless noninteractive ;; Else can't see the result, and change hooks are slow
(when (featurep 'xemacs)
(make-local-hook 'font-lock-mode-hook)
(make-local-hook 'font-lock-after-fontify-buffer-hook); doesn't exist in Emacs
(make-local-hook 'after-change-functions))
(add-hook 'font-lock-mode-hook 'bsv-highlight-buffer t t)
(add-hook 'font-lock-after-fontify-buffer-hook 'bsv-highlight-buffer t t) ; not in Emacs
(add-hook 'after-change-functions 'bsv-highlight-region t t))
;; Tell imenu how to handle BSV.
(set (make-local-variable 'imenu-generic-expression)
bsv-imenu-generic-expression)
;; Tell which-func-modes that imenu knows about bsv
(when (boundp 'which-func-modes)
(add-to-list 'which-func-modes 'bsv-mode))
;; hideshow support
(when (boundp 'hs-special-modes-alist)
(unless (assq 'bsv-mode hs-special-modes-alist)
(setq hs-special-modes-alist
(cons '(bsv-mode-mode "\\" "\\" nil
bsv-forward-sexp-function)
hs-special-modes-alist))))
;; Stuff for autos
(add-hook 'write-contents-hooks 'bsv-auto-save-check nil 'local)
;; bsv-mode-hook call added by define-derived-mode
)
;;
;; Electric functions
;;
(defun electric-bsv-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 (bsv-syntax-ppss))))
(cond
((nth 7 state) ; Inside // comment
(if (eolp)
(progn
(delete-horizontal-space)
(newline))
(progn
(newline)
(insert "// ")
(beginning-of-line)))
(bsv-indent-line))
((nth 4 state) ; Inside any comment (hence /**/)
(newline)
(bsv-more-comment))
((eolp)
(newline)
(if bsv-auto-indent-on-newline
(bsv-indent-line)))
;; ((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 bsv-auto-end-comment-lines-re)
;; (let ((indent-str (bsv-indent-line)))
;; ;; Maybe we should set some endcomments
;; (if bsv-auto-endcomments
;; (bsv-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 (eq 'all bsv-auto-lineup)
;; (eq 'assignments bsv-auto-lineup))
;; (bsv-pretty-expr t "\\(<\\|:\\)?=" ))
;; (newline))
;; (forward-line 1))
;; ;; Indent next line
;; (if bsv-auto-indent-on-newline
;; (bsv-indent-line)))
(t
(newline)))))
(defun electric-bsv-terminate-and-indent ()
"Insert a newline and indent for the next statement."
(interactive)
(electric-bsv-terminate-line 1))
(defun electric-bsv-semi ()
"Insert `;' character and reindent the line."
(interactive)
(bsv-insert-last-command-event)
(if (or (bsv-in-comment-or-string-p)
(bsv-in-escaped-name-p))
()
(save-excursion
(beginning-of-line)
(bsv-forward-ws&directives)
(bsv-indent-line-conservative))
(if (and bsv-auto-newline
(not (bsv-parenthesis-depth)))
(electric-bsv-terminate-line))))
(defun electric-bsv-semi-with-comment ()
"Insert `;' character, reindent the line and indent for comment."
(interactive)
(insert "\;")
(save-excursion
(beginning-of-line)
(bsv-indent-line))
(indent-for-comment))
(defun electric-bsv-colon ()
"Insert `:' and do all indentations except line indent on this line."
(interactive)
(bsv-insert-last-command-event)
;; Do nothing if within string.
(if (or
(bsv-within-string)
(not (bsv-in-case-region-p)))
()
(save-excursion
(let ((p (point))
(lim (progn (bsv-beg-of-statement) (point))))
(goto-char p)
(bsv-backward-case-item lim)
(bsv-indent-line)))
;; (let ((bsv-tab-always-indent nil))
;; (bsv-indent-line))
))
;;(defun electric-bsv-equal ()
;; "Insert `=', and do indentation if within block."
;; (interactive)
;; (bsv-insert-last-command-event)
;; Could auto line up expressions, but not yet
;; (if (eq (car (bsv-calculate-indent)) 'block)
;; (let ((bsv-tab-always-indent nil))
;; (bsv-indent-command)))
;; )
(defun electric-bsv-tick ()
"Insert back-tick, and indent to column 0 if this is a CPP directive."
(interactive)
(bsv-insert-last-command-event)
(save-excursion
(if (bsv-in-directive-p)
(bsv-indent-line))))
(defun electric-bsv-tab ()
"Function called when TAB is pressed in BSV mode."
(interactive)
;; If bsv-tab-always-indent, indent the beginning of the line.
(cond
;; The region is active, indent it.
((and (region-active-p)
(not (eq (region-beginning) (region-end))))
(indent-region (region-beginning) (region-end) nil))
((or bsv-tab-always-indent
(save-excursion
(skip-chars-backward " \t")
(bolp)))
(let* ((oldpnt (point))
(boi-point
(save-excursion
(beginning-of-line)
(skip-chars-forward " \t")
(bsv-indent-line)
(back-to-indentation)
(point))))
(if (< (point) boi-point)
(back-to-indentation)
(cond ((not bsv-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)))))))
(t (progn (insert "\t")))))
;;
;; Interactive functions
;;
(defun bsv-indent-buffer ()
"Indent-region the entire buffer as BSV code.
To call this from the command line, see \\[bsv-batch-indent]."
(interactive)
(bsv-mode)
(indent-region (point-min) (point-max) nil))
(defun bsv-insert-block ()
"Insert BSV begin ... end; block in the code with right indentation."
(interactive)
(bsv-indent-line)
(insert "begin")
(electric-bsv-terminate-line)
(save-excursion
(electric-bsv-terminate-line)
(insert "end")
(beginning-of-line)
(bsv-indent-line)))
(defun bsv-star-comment ()
"Insert BSV star comment at point."
(interactive)
(bsv-indent-line)
(insert "/*")
(save-excursion
(newline)
(insert " */"))
(newline)
(insert " * "))
(defun bsv-insert-1 (fmt max)
"Use format string FMT to insert integers 0 to MAX - 1.
Inserts one integer per line, at the current column. Stops early
if it reaches the end of the buffer."
(let ((col (current-column))
(n 0))
(save-excursion
(while (< n max)
(insert (format fmt n))
(forward-line 1)
;; Note that this function does not bother to check for lines
;; shorter than col.
(if (eobp)
(setq n max)
(setq n (1+ n))
(move-to-column col))))))
(defun bsv-insert-indices (max)
"Insert a set of indices into a rectangle.
The upper left corner is defined by point. Indices 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: ")
(bsv-insert-1 "[%3d]" max))
(defun bsv-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 ==> generate-numbers ==> buf buf004
buf buf buf buf005
buf buf buf buf006
buf buf buf buf007
buf buf buf buf008"
(interactive "NMAX: ")
(bsv-insert-1 "%3.3d" max))
(defun bsv-mark-defun ()
"Mark the current BSV function (or procedure).
This puts the mark at the end, and point at the beginning."
(interactive)
(if (featurep 'xemacs)
(progn
(push-mark (point))
(bsv-end-of-defun)
(push-mark (point))
(bsv-beg-of-defun)
(if (fboundp 'zmacs-activate-region)
(zmacs-activate-region)))
(mark-defun)))
(defun bsv-comment-region (start end)
; checkdoc-params: (start end)
"Put the region into a BSV comment.
The comments that are in this area are \"deformed\":
`*)' becomes `!(*' and `}' becomes `!{'.
These deformed comments are returned to normal if you use
\\[bsv-uncomment-region] to undo the commenting.
The commented area starts with `bsv-exclude-str-start', and ends with
`bsv-exclude-str-end'. But if you change these variables,
\\[bsv-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 bsv-exclude-str-end)
(setq end (point))
(newline)
(goto-char start)
(beginning-of-line)
(insert bsv-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 bsv-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 `bsv-comment-region'."
(interactive)
(save-excursion
(let ((start (point))
(end (point)))
;; Find the boundaries of the comment
(save-excursion
(setq start (progn (search-backward bsv-exclude-str-start nil t)
(point)))
(setq end (progn (search-forward bsv-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 bsv-beg-of-defun ()
"Move backward to the beginning of the current function or procedure."
(interactive)
(bsv-re-search-backward bsv-defun-re nil 'move))
(defun bsv-beg-of-defun-quick ()
"Move backward to the beginning of the current function or procedure.
Uses `bsv-scan' cache."
(interactive)
(bsv-re-search-backward-quick bsv-defun-re nil 'move))
(defun bsv-end-of-defun ()
"Move forward to the end of the current function or procedure."
(interactive)
(bsv-re-search-forward bsv-end-defun-re nil 'move))
(defun bsv-get-beg-of-defun (&optional warn)
(save-excursion
(cond ((bsv-re-search-forward-quick bsv-defun-re nil t)
(point))
(t
(error "%s: Can't find module beginning" (bsv-point-text))
(point-max)))))
(defun bsv-get-end-of-defun (&optional warn)
(save-excursion
(cond ((bsv-re-search-forward-quick bsv-end-defun-re nil t)
(point))
(t
(error "%s: Can't find endmodule" (bsv-point-text))
(point-max)))))
(defun bsv-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
(bsv-beg-of-defun)
(point-marker)))
(e (progn
(bsv-end-of-defun)
(point-marker))))
(goto-char (marker-position b))
(if (> (- e b) 200)
(message "Relabeling module..."))
(while (and
(> (marker-position e) (point))
(bsv-re-search-forward
(concat
"\\"
"\\|\\(`endif\\)\\|\\(`else\\)")
nil 'move))
(goto-char (match-beginning 0))
(let ((indent-str (bsv-indent-line)))
(bsv-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 bsv-beg-of-statement ()
"Move backward to beginning of statement."
(interactive)
;; Move back token by token until we see the end
;; of some earlier line.
(let (h)
(while
;; If the current point does not begin a new
;; statement, as in the character ahead of us is a ';', or SOF
;; or the string after us unambiguously starts a statement,
;; or the token before us unambiguously ends a statement,
;; then move back a token and test again.
(not (or
;; stop if beginning of buffer
(bolp)
;; stop if we find a ;
(= (preceding-char) ?\;)
;; stop if we see a named coverpoint
(looking-at "\\w+\\W*:\\W*\\(coverpoint\\|cross\\|constraint\\)")
;; keep going if we are in the middle of a word
(not (or (looking-at "\\<") (forward-word -1)))
;; stop if we see an assertion (perhaps labeled)
(and
(looking-at "\\(\\<\\(assert\\|assume\\|cover\\)\\>\\s-+\\\\)\\|\\(\\\\)")
(progn
(setq h (point))
(save-excursion
(bsv-backward-token)
(if (looking-at bsv-label-re)
(setq h (point))))
(goto-char h)))
;; stop if we see a complete reg, perhaps an extended one
(and
(looking-at bsv-complete-reg)
(let* ((p (point)))
(while (and (looking-at bsv-extended-complete-re)
(progn (setq p (point))
(bsv-backward-token)
(/= p (point)))))
(goto-char p)))
;; stop if we see a complete reg (previous found extended ones)
(looking-at bsv-basic-complete-re)
;; stop if previous token is an ender
(save-excursion
(bsv-backward-token)
(or
(looking-at bsv-end-block-re)
(looking-at bsv-preprocessor-re))))) ;; end of test
(bsv-backward-syntactic-ws)
(bsv-backward-token))
;; Now point is where the previous line ended.
(bsv-forward-syntactic-ws)))
(defun bsv-beg-of-statement-1 ()
"Move backward to beginning of statement."
(interactive)
(if (bsv-in-comment-p)
(bsv-backward-syntactic-ws))
(let ((pt (point)))
(catch 'done
(while (not (looking-at bsv-complete-reg))
(setq pt (point))
(bsv-backward-syntactic-ws)
(if (or (bolp)
(= (preceding-char) ?\;)
(save-excursion
(bsv-backward-token)
(looking-at bsv-ends-re)))
(progn
(goto-char pt)
(throw 'done t))
(bsv-backward-token))))
(bsv-forward-syntactic-ws)))
;
; (while (and
; (not (looking-at bsv-complete-reg))
; (not (bolp))
; (not (= (preceding-char) ?\;)))
; (bsv-backward-token)
; (bsv-backward-syntactic-ws)
; (setq pt (point)))
; (goto-char pt)
; ;(bsv-forward-syntactic-ws)
(defun bsv-end-of-statement ()
"Move forward to end of current statement."
(interactive)
(let ((nest 0) pos)
(cond
((bsv-in-directive-p)
(forward-line 1)
(backward-char 1))
((looking-at bsv-beg-block-re)
(bsv-forward-sexp))
((equal (char-after) ?\})
(forward-char))
;; Skip to end of statement
((condition-case nil
(setq pos
(catch 'found
(while t
(forward-sexp 1)
(bsv-skip-forward-comment-or-string)
(if (eolp)
(forward-line 1))
(cond ((looking-at "[ \t]*;")
(skip-chars-forward "^;")
(forward-char 1)
(throw 'found (point)))
((save-excursion
(forward-sexp -1)
(looking-at bsv-beg-block-re))
(goto-char (match-beginning 0))
(throw 'found nil))
((looking-at "[ \t]*)")
(throw 'found (point)))
((eobp)
(throw 'found (point)))
)))
)
(error nil))
(if (not pos)
;; Skip a whole block
(catch 'found
(while t
(bsv-re-search-forward bsv-end-statement-re nil 'move)
(setq nest (if (match-end 1)
(1+ nest)
(1- nest)))
(cond ((eobp)
(throw 'found (point)))
((= 0 nest)
(throw 'found (bsv-end-of-statement))))))
pos)))))
(defun bsv-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 (bsv-forward-syntactic-ws)
(looking-at "\\"))
(progn (bsv-backward-syntactic-ws)
(= (preceding-char) ?\:)))
(catch 'found
(let ((nest 1))
(while t
(bsv-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 bsv-backward-up-list (arg)
"Like `backward-up-list', but deal with comments."
(let ((parse-sexp-ignore-comments t))
(backward-up-list arg)))
(defun bsv-forward-sexp-cmt (arg)
"Call `forward-sexp', inside comments."
(let ((parse-sexp-ignore-comments nil))
(forward-sexp arg)))
(defun bsv-forward-sexp-ign-cmt (arg)
"Call `forward-sexp', ignoring comments."
(let ((parse-sexp-ignore-comments t))
(forward-sexp arg)))
(defun bsv-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 (bsv-syntax-ppss))
(depth (nth 0 state)))
(if depth
(progn (bsv-backward-up-list depth)
(bsv-beg-of-statement)
(looking-at "\\?\\s-*\\"))))))
(defun bsv-in-generate-region-p ()
"Return true if in a generate region.
More specifically, after a generate and before an endgenerate."
(interactive)
(let ((nest 1))
(save-excursion
(catch 'done
(while (and
(/= nest 0)
(bsv-re-search-backward
"\\<\\(module\\)\\|\\(generate\\)\\|\\(endgenerate\\)\\>" nil 'move)
(cond
((match-end 1) ; module - we have crawled out
(throw 'done 1))
((match-end 2) ; generate
(setq nest (1- nest)))
((match-end 3) ; endgenerate
(setq nest (1+ nest))))))))
(= nest 0) )) ; return nest
(defun bsv-in-fork-region-p ()
"Return true if between a fork and join."
(interactive)
(let ((lim (save-excursion (bsv-beg-of-defun) (point)))
(nest 1))
(save-excursion
(while (and
(/= nest 0)
(bsv-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 bsv-backward-case-item (lim)
"Skip backward to nearest enclosing case item.
Limit search to point LIM."
(interactive)
(let ((str 'nil)
(lim1
(progn
(save-excursion
(bsv-re-search-backward bsv-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)
(bsv-re-search-backward "\\(\\[\\)\\|\\(\\]\\)\\|\\(:\\)"
lim1 'move))
(cond
((match-end 1) ;; [
(setq colon (1+ colon))
(if (>= colon 0)
(error "%s: unbalanced [" (bsv-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 ")
(bsv-skip-backward-comment-or-string)
(setq e (point))
(setq b
(progn
(if
(bsv-re-search-backward
"\\<\\(case[zx]?\\)\\>\\|;\\|\\" nil 'move)
(progn
(cond
((match-end 1)
(goto-char (match-end 1))
(bsv-forward-ws&directives)
(if (looking-at "(")
(progn
(forward-sexp)
(bsv-forward-ws&directives)))
(point))
(t
(goto-char (match-end 0))
(bsv-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 bsv-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 bsv-directive-nest-re
(concat "\\(`else\\>\\)\\|"
"\\(`endif\\>\\)\\|"
"\\(`if\\>\\)\\|"
"\\(`ifdef\\>\\)\\|"
"\\(`ifndef\\>\\)\\|"
"\\(`elsif\\>\\)"))
(defun bsv-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
((eq indent-str 0) nil)
(; Comment close preprocessor directives
(and
(looking-at "\\(`endif\\)\\|\\(`else\\)")
(or kill-existing-comment
(not (save-excursion
(end-of-line)
(search-backward "//" (point-at-bol) t)))))
(let ((nest 1) b e
m
(else (if (match-end 2) "!" " ")))
(end-of-line)
(if kill-existing-comment
(bsv-kill-existing-comment))
(delete-horizontal-space)
(save-excursion
(backward-sexp 1)
(while (and (/= nest 0)
(bsv-re-search-backward bsv-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)))
((match-end 6) ; `elsif
(if (= nest 1)
(progn
(setq else "!")
(setq nest 0))))))
(if (match-end 0)
(setq
m (buffer-substring
(match-beginning 0)
(match-end 0))
b (progn
(skip-chars-forward "^ \t")
(bsv-forward-syntactic-ws)
(point))
e (progn
(skip-chars-forward "a-zA-Z0-9_")
(point)))))
(if b
(if (> (count-lines (point) b) bsv-minimum-comment-distance)
(insert (concat " // " else m " " (buffer-substring b e))))
(progn
(insert " // unmatched `else, `elsif or `endif")
(ding 't)))))
(; Comment close case/class/function/task/module and named block
(and (looking-at "\\")
(setq str "randcase")
(setq err nil))
((looking-at "\\(\\(unique\\s-+\\|priority\\s-+\\)?case[xz]?\\)")
(goto-char (match-end 0))
(setq str (concat (match-string 0) " " (bsv-get-expr)))
(setq err nil))
))
(end-of-line)
(if kill-existing-comment
(bsv-kill-existing-comment))
(delete-horizontal-space)
(insert (concat " // " str ))
(if err (ding 't))))
(;- This is a begin..end block
(match-end 2) ;; of bsv-end-block-ordered-re
(let ((str " // UNMATCHED !!")
(err 't)
(here (point))
there
cntx)
(save-excursion
(bsv-leap-to-head)
(setq there (point))
(if (not (match-end 0))
(progn
(goto-char here)
(end-of-line)
(if kill-existing-comment
(bsv-kill-existing-comment))
(delete-horizontal-space)
(insert str)
(ding 't))
(let ((lim
(save-excursion (bsv-beg-of-defun) (point)))
(here (point)))
(cond
(;-- handle named block differently
(looking-at bsv-named-block-re)
(search-forward ":")
(setq there (point))
(setq str (bsv-get-expr))
(setq err nil)
(setq str (concat " // block: " str )))
((bsv-in-case-region-p) ;-- handle case item differently
(goto-char here)
(setq str (bsv-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
;; (bsv-backward-token)
(bsv-beg-of-statement)
(point)))
(setq err nil)
(setq str ""))
((looking-at bsv-endcomment-reason-re)
(setq there (match-end 0))
(setq cntx (concat (match-string 0) " "))
(cond
(;- begin
(match-end 1)
(setq err nil)
(save-excursion
(if (and (bsv-continued-line)
(looking-at "\\\\|\\\\|\\"))
(progn
(goto-char (match-end 0))
(setq there (point))
(setq str
(concat " // " (match-string 0) " " (bsv-get-expr))))
(setq str ""))))
(;- else
(match-end 2)
(let ((nest 0)
( reg "\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(assert\\)"))
(catch 'skip
(while (bsv-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 (bsv-get-expr))
(setq str (concat " // else: !if" str ))
(throw 'skip 1))))
((match-end 4)
(if (= 0 nest)
(progn
(goto-char (match-end 0))
(setq there (point))
(setq err nil)
(setq str (bsv-get-expr))
(setq str (concat " // else: !assert " str ))
(throw 'skip 1)))))))))
(;- end else
(match-end 3)
(goto-char there)
(let ((nest 0)
(reg "\\(\\\\)\\|\\(\\\\)\\|\\(\\\\)\\|\\(assert\\)"))
(catch 'skip
(while (bsv-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 (bsv-get-expr))
(setq str (concat " // else: !if" str ))
(throw 'skip 1))))
((match-end 4)
(if (= 0 nest)
(progn
(goto-char (match-end 0))
(setq there (point))
(setq err nil)
(setq str (bsv-get-expr))
(setq str (concat " // else: !assert " str ))
(throw 'skip 1)))))))))
(; always_comb, always_ff, always_latch
(or (match-end 4) (match-end 5) (match-end 6))
(goto-char (match-end 0))
(setq there (point))
(setq err nil)
(setq str (concat " // " cntx )))
(;- task/function/initial et cetera
t
(match-end 0)
(goto-char (match-end 0))
(setq there (point))
(setq err nil)
(setq str (concat " // " cntx (bsv-get-expr))))
(;-- otherwise...
(setq str " // auto-endcomment confused "))))
((and
(bsv-in-case-region-p) ;-- handle case item differently
(progn
(setq there (point))
(goto-char here)
(setq str (bsv-backward-case-item lim))))
(setq err nil)
(setq str (concat " // case: " str )))
((bsv-in-fork-region-p)
(setq err nil)
(setq str " // fork branch" ))
((looking-at "\\")
;; HERE
(forward-word 1)
(bsv-forward-syntactic-ws)
(setq err nil)
(setq str (bsv-get-expr))
(setq str (concat " // " cntx str )))
))))
(goto-char here)
(end-of-line)
(if kill-existing-comment
(bsv-kill-existing-comment))
(delete-horizontal-space)
(if (or err
(> (count-lines here there) bsv-minimum-comment-distance))
(insert str))
(if err (ding 't))
))))
(;- this is endclass, which can be nested
(match-end 11) ;; of bsv-end-block-ordered-re
;;(goto-char there)
(let ((nest 0)
(reg "\\<\\(class\\)\\|\\(endclass\\)\\|\\(package\\|primitive\\|\\(macro\\)?module\\)\\>")
string)
(save-excursion
(catch 'skip
(while (bsv-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")
(bsv-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 (name-re nil))
(end-of-line)
(if kill-existing-comment
(save-match-data
(bsv-kill-existing-comment)))
(delete-horizontal-space)
(backward-sexp)
(cond
((match-end 5) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endfunction\\|task\\|\\(macro\\)?module\\|primitive\\)\\>\\)")
(setq name-re "\\w+\\s-*(")
)
((match-end 6) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endtask\\|function\\|\\(macro\\)?module\\|primitive\\)\\>\\)"))
((match-end 7) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\<\\(macro\\)?module\\>\\)\\|\\"))
((match-end 8) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endprimitive\\|package\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 9) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endinterface\\|package\\|primitive\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 10) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endpackage\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 11) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endclass\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 12) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endcovergroup\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 13) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\(\\<\\(endprogram\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 14) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\<\\(rand\\)?sequence\\>\\)\\|\\(\\<\\(endsequence\\|primitive\\|interface\\|\\(macro\\)?module\\)\\>\\)"))
((match-end 15) ;; of bsv-end-block-ordered-re
(setq reg "\\(\\\\)\\|\\"))
(t (error "Problem in bsv-set-auto-endcomments")))
(let (b e)
(save-excursion
(bsv-re-search-backward reg nil 'move)
(cond
((match-end 1)
(setq b (progn
(skip-chars-forward "^ \t")
(bsv-forward-ws&directives)
(if (looking-at "static\\|automatic")
(progn
(goto-char (match-end 0))
(bsv-forward-ws&directives)))
(if (and name-re (bsv-re-search-forward name-re nil 'move))
(progn
(goto-char (match-beginning 0))
(bsv-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|clocking)")))))
(end-of-line)
(insert (concat " // " string )))
))))))))))
(defun bsv-get-expr()
"Grab expression at point, e.g, case ( a | b & (c ^d))."
(let* ((b (progn
(bsv-forward-syntactic-ws)
(skip-chars-forward " \t")
(point)))
(e (let ((par 1))
(cond
((looking-at "@")
(forward-char 1)
(bsv-forward-syntactic-ws)
(if (looking-at "(")
(progn
(forward-char 1)
(while (and (/= par 0)
(bsv-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)
(bsv-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)
(bsv-re-search-forward "\\(\\[\\)\\|\\(\\]\\)" nil 'move))
(cond
((match-end 1)
(setq par (1+ par)))
((match-end 2)
(setq par (1- par)))))
(bsv-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 bsv-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)
(bsv-expand-vector-internal "[" "]"))
(defun bsv-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-number (match-string 2 signal-string)))
(vec-end (if (= (match-beginning 3) (match-end 3))
vec-start
(string-to-number
(substring signal-string (1+ (match-beginning 3))
(match-end 3)))))
(vec-range
(if (= (match-beginning 4) (match-end 4))
1
(string-to-number
(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 bsv-strip-comments ()
"Strip all comments from the BSV code."
(interactive)
(goto-char (point-min))
(while (re-search-forward "//" nil t)
(if (bsv-within-string)
(re-search-forward "\"" nil t)
(if (bsv-in-star-comment-p)
(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)
(if (bsv-within-string)
(re-search-forward "\"" nil t)
(let ((bpt (- (point) 2)))
(re-search-forward "\\*/")
(delete-region bpt (point))))))
(defun bsv-one-line ()
"Convert structural BSV 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 bsv-linter-name ()
"Return name of linter, either surelint or verilint."
(let ((compile-word1 (bsv-string-replace-matches "\\s .*$" "" nil nil
compile-command))
(lint-word1 (bsv-string-replace-matches "\\s .*$" "" nil nil
bsv-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 bsv-lint-off ()
"Convert a BSV 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 `bsv-linter'
variables is used to determine which product is being used.
See \\[bsv-surelint-off] and \\[bsv-verilint-off]."
(interactive)
(let ((linter (bsv-linter-name)))
(cond ((equal linter `surelint)
(bsv-surelint-off))
((equal linter `verilint)
(bsv-verilint-off))
(t (error "Linter name not set")))))
(defvar compilation-last-buffer)
(defvar next-error-last-buffer)
(defun bsv-surelint-off ()
"Convert a SureLint warning line into a disable statement.
Run from BSV 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)
(let ((buff (if (boundp 'next-error-last-buffer)
next-error-last-buffer
compilation-last-buffer)))
(when (buffer-live-p buff)
(save-excursion
(switch-to-buffer buff)
(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-char (point-min))
(forward-line (- (string-to-number line)))
(end-of-line)
(catch 'already
(cond
((bsv-in-slash-comment-p)
(re-search-backward "//")
(cond
((looking-at "// surefire lint_off_line ")
(goto-char (match-end 0))
(let ((lim (point-at-eol)))
(if (re-search-forward code lim 'move)
(throw 'already t)
(insert (concat " " code)))))
(t
)))
((bsv-in-star-comment-p)
(re-search-backward "/\*")
(insert (format " // surefire lint_off_line %6s" code )))
(t
(insert (format " // surefire lint_off_line %6s" code ))
)))))))))
(defun bsv-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)
(bsv-indent-line))))
(defun bsv-auto-save-compile ()
"Update automatics with \\[bsv-auto], save the buffer, and compile."
(interactive)
(bsv-auto) ; Always do it for safety
(save-buffer)
(compile compile-command))
(defun bsv-preprocess (&optional command filename)
"Preprocess the buffer, similar to `compile', but leave output in BSV-Mode.
Takes optional COMMAND or defaults to `bsv-preprocessor', and
FILENAME or defaults to `buffer-file-name`."
(interactive
(list
(let ((default (bsv-expand-command bsv-preprocessor)))
(set (make-local-variable `bsv-preprocessor)
(read-from-minibuffer "Run Preprocessor (like this): "
default nil nil
'bsv-preprocess-history default)))))
(unless command (setq command (bsv-expand-command bsv-preprocessor)))
(let* ((fontlocked (and (boundp 'font-lock-mode) font-lock-mode))
(dir (file-name-directory (or filename buffer-file-name)))
(file (file-name-nondirectory (or filename buffer-file-name)))
(cmd (concat "cd " dir "; " command " " file)))
(with-output-to-temp-buffer "*BSV-Preprocessed*"
(with-current-buffer (get-buffer "*BSV-Preprocessed*")
(insert (concat "// " cmd "\n"))
(shell-command cmd "*BSV-Preprocessed*")
(bsv-mode)
;; Without this force, it takes a few idle seconds
;; to get the color, which is very jarring
(when fontlocked (font-lock-fontify-buffer))))))
;;
;; Batch
;;
(defmacro bsv-batch-error-wrapper (&rest body)
"Execute BODY and add error prefix to any errors found.
This lets programs calling batch mode to easily extract error messages."
`(condition-case err
(progn ,@body)
(error
(error "%%Error: %s%s" (error-message-string err)
(if (featurep 'xemacs) "\n" ""))))) ;; XEmacs forgets to add a newline
(defun bsv-batch-execute-func (funref &optional no-save)
"Internal processing of a batch command, running FUNREF on all command arguments.
Save the result unless optional NO-SAVE is t."
(bsv-batch-error-wrapper
;; Setting global variables like that is *VERY NASTY* !!! --Stef
;; However, this function is called only when Emacs is being used as
;; a standalone language instead of as an editor, so we'll live.
;;
;; 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 'bsv-mode)
;; Ditto files already read in
(mapc (lambda (buf)
(when (buffer-file-name buf)
(with-current-buffer buf
(bsv-mode))))
(buffer-list))
;; Process the files
(mapcar (lambda (buf)
(when (buffer-file-name buf)
(save-excursion
(if (not (file-exists-p (buffer-file-name buf)))
(error
(concat "File not found: " (buffer-file-name buf))))
(message (concat "Processing " (buffer-file-name buf)))
(set-buffer buf)
(funcall funref)
(unless no-save (save-buffer)))))
(buffer-list))))
(defun bsv-batch-auto ()
"For use with --batch, perform automatic expansions as a stand-alone tool.
This sets up the appropriate BSV mode environment, updates automatics
with \\[bsv-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 bsv-batch-auto only with --batch")) ;; Otherwise we'd mess up buffer modes
(bsv-batch-execute-func `bsv-auto))
(defun bsv-batch-delete-auto ()
"For use with --batch, perform automatic deletion as a stand-alone tool.
This sets up the appropriate BSV mode environment, deletes automatics
with \\[bsv-delete-auto] on all command-line files, and saves the buffers."
(unless noninteractive
(error "Use bsv-batch-delete-auto only with --batch")) ;; Otherwise we'd mess up buffer modes
(bsv-batch-execute-func `bsv-delete-auto))
(defun bsv-batch-diff-auto ()
"For use with --batch, perform automatic differences as a stand-alone tool.
This sets up the appropriate BSV mode environment, expand automatics
with \\[bsv-diff-auto] on all command-line files, and reports an error
if any differences are observed. This is appropriate for adding to regressions
to insure automatics are always properly maintained."
(unless noninteractive
(error "Use bsv-batch-diff-auto only with --batch")) ;; Otherwise we'd mess up buffer modes
(bsv-batch-execute-func `bsv-diff-auto t))
(defun bsv-batch-inject-auto ()
"For use with --batch, perform automatic injection as a stand-alone tool.
This sets up the appropriate BSV mode environment, injects new automatics
with \\[bsv-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 bsv-batch-inject-auto only with --batch")) ;; Otherwise we'd mess up buffer modes
(bsv-batch-execute-func `bsv-inject-auto))
(defun bsv-batch-indent ()
"For use with --batch, reindent an a entire file as a stand-alone tool.
This sets up the appropriate BSV mode environment, calls
\\[bsv-indent-buffer] on all command-line files, and saves the buffers."
(unless noninteractive
(error "Use bsv-batch-indent only with --batch")) ;; Otherwise we'd mess up buffer modes
(bsv-batch-execute-func `bsv-indent-buffer))
;;
;; Indentation
;;
(defconst bsv-indent-alist
'((block . (+ ind bsv-indent-level))
(case . (+ ind bsv-case-indent))
(cparenexp . (+ ind bsv-indent-level))
(cexp . (+ ind bsv-cexp-indent))
(defun . bsv-indent-level-module)
(declaration . bsv-indent-level-declaration)
(directive . (bsv-calculate-indent-directive))
(tf . bsv-indent-level)
(behavioral . (+ bsv-indent-level-behavioral bsv-indent-level-module))
(statement . ind)
(cpp . 0)
(comment . (bsv-comment-indent))
(unknown . 3)
(string . 0)))
(defun bsv-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)
(bsv-backward-ws&directives lim)
(if (bobp)
(setq continued nil)
(setq continued (bsv-backward-token))))
(setq continued nil))
continued))
(defun bsv-calculate-indent ()
"Calculate the indent of the current BSV 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 (bsv-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 (bsv-in-star-comment-p)
(throw 'nesting 'comment))
;; if we have a directive, done.
(if (save-excursion (beginning-of-line)
(and (looking-at bsv-directive-re-1)
(not (or (looking-at "[ \t]*`[ou]vm_")
(looking-at "[ \t]*`vmm_")))))
(throw 'nesting 'directive))
;; indent structs as if there were module level
(if (bsv-in-struct-p)
(throw 'nesting 'block))
;; if we are in a parenthesized list, and the user likes to indent these, return.
;; unless we are in the newfangled coverpoint or constraint blocks
(if (and
bsv-indent-lists
(bsv-in-paren)
(not (bsv-in-coverage-p))
)
(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 (bsv-continued-line-1 lim)
(let ((sp (point)))
(if (and
(not (looking-at bsv-complete-reg))
(bsv-continued-line-1 lim))
(progn (goto-char sp)
(throw 'nesting 'cexp))
(goto-char sp))
(if (and begin
(not bsv-indent-begin-after-if)
(looking-at bsv-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 (bsv-re-search-backward bsv-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 bsv-align-ifelse
(throw 'nesting 'statement)
(progn ;; back up to first word on this line
(beginning-of-line)
(bsv-forward-syntactic-ws)
(throw 'nesting 'statement)))))
((match-end 3) ; assert block
(setq elsec (1- elsec))
(bsv-beg-of-statement) ;; doesn't get to beginning
(if (looking-at bsv-property-re)
(throw 'nesting 'statement) ; We don't need an endproperty for these
(throw 'nesting 'block) ;We still need a endproperty
))
(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))
;; bsv-ends => else|if|end|join(_any|_none|)|endcase|endclass|endtable|endspecify|endfunction|endtask|endgenerate|endgroup
(cond
((match-end 4) ; end
;; Search back for matching begin
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 5) ; endcase
;; Search back for matching case
(setq reg "\\(\\\\|\\[^:]\\)\\|\\(\\\\)" ))
((match-end 6) ; endfunction
;; Search back for matching function
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 7) ; endtask
;; Search back for matching task
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 8) ; endspecify
;; Search back for matching specify
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 9) ; endtable
;; Search back for matching table
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 10) ; endgenerate
;; Search back for matching generate
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 11) ; joins
;; Search back for matching fork
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 12) ; class
;; Search back for matching class
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((match-end 13) ; covergroup
;; Search back for matching covergroup
(setq reg "\\(\\\\)\\|\\(\\\\)" )))
(catch 'skip
(while (bsv-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 (bsv-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 (bsv-case-indent-level)))
((eq type 'statement)
(list type (current-column)))
((eq type 'defun)
(list type 0))
(t
(list type (bsv-current-indent-level))))))))
(defun bsv-wai ()
"Show matching nesting block for debugging."
(interactive)
(save-excursion
(let* ((type (bsv-calc-1))
depth)
;; Return type of block and indent level.
(if (not type)
(setq type 'cpp))
(if (and
bsv-indent-lists
(not(or (bsv-in-coverage-p)
(bsv-in-struct-p)))
(bsv-in-paren))
(setq depth 1)
(cond
((eq type 'case)
(setq depth (bsv-case-indent-level)))
((eq type 'statement)
(setq depth (current-column)))
((eq type 'defun)
(setq depth 0))
(t
(setq depth (bsv-current-indent-level)))))
(message "You are at nesting %s depth %d" type depth))))
(defun bsv-calc-1 ()
(catch 'nesting
(let ((re (concat "\\({\\|}\\|" bsv-indent-re "\\)")))
(while (bsv-re-search-backward re nil 'move)
(catch 'continue
(cond
((equal (char-after) ?\{)
(if (bsv-at-constraint-p)
(throw 'nesting 'block)))
((equal (char-after) ?\})
(let ((there (bsv-at-close-constraint-p)))
(if there ;; we are at the } that closes a constraint. Find the { that opens it
(progn
(forward-char 1)
(backward-list 1)
(bsv-beg-of-statement)))))
((looking-at bsv-beg-block-re-ordered)
(cond
((match-end 2) ; *sigh* could be "unique case" or "priority casex"
(let ((here (point)))
(bsv-beg-of-statement)
(if (looking-at bsv-extended-case-re)
(throw 'nesting 'case)
(goto-char here)))
(throw 'nesting 'case))
((match-end 4) ; *sigh* could be "disable fork"
(let ((here (point)))
(bsv-beg-of-statement)
(if (looking-at bsv-disable-fork-re)
t ; this is a normal statement
(progn ; or is fork, starts a new block
(goto-char here)
(throw 'nesting 'block)))))
((match-end 27) ; *sigh* might be a clocking declaration
(let ((here (point)))
(if (bsv-in-paren)
t ; this is a normal statement
(progn ; or is fork, starts a new block
(goto-char here)
(throw 'nesting 'block)))))
;; need to consider typedef struct here...
((looking-at "\\")
; *sigh* These words have an optional prefix:
; extern {virtual|protected}? function a();
; typedef class foo;
; and we don't want to confuse this with
; function a();
; property
; ...
; endfunction
(bsv-beg-of-statement)
(if (looking-at bsv-beg-block-re-ordered)
(throw 'nesting 'block)
(throw 'nesting 'defun)))
((looking-at "\\")
; *sigh*
; {assert|assume|cover} property (); are complete
; and could also be labeled: - foo: assert property
; but
; property ID () ... needs end_property
(bsv-beg-of-statement)
(if (looking-at bsv-property-re)
(throw 'continue 'statement) ; We don't need an endproperty for these
(throw 'nesting 'block) ;We still need a endproperty
))
(t (throw 'nesting 'block))))
((looking-at bsv-end-block-re)
(bsv-leap-to-head)
(if (bsv-in-case-region-p)
(progn
(bsv-leap-to-case-head)
(if (looking-at bsv-extended-case-re)
(throw 'nesting 'case)))))
((looking-at bsv-defun-level-re)
(if (looking-at bsv-defun-level-generate-only-re)
(if (bsv-in-generate-region-p)
(throw 'continue 'foo) ; always block in a generate - keep looking
(throw 'nesting 'defun))
(throw 'nesting 'defun)))
((looking-at bsv-cpp-level-re)
(throw 'nesting 'cpp))
((bobp)
(throw 'nesting 'cpp)))))
(throw 'nesting 'cpp))))
(defun bsv-calculate-indent-directive ()
"Return indentation level for directive.
For speed, the searcher looks at the last directive, not the indent
of the appropriate enclosing block."
(let ((base -1) ;; Indent of the line that determines our indentation
(ind 0)) ;; Relative offset caused by other directives (like `endif on same line as `else)
;; Start at current location, scan back for another directive
(save-excursion
(beginning-of-line)
(while (and (< base 0)
(bsv-re-search-backward bsv-directive-re nil t))
(cond ((save-excursion (skip-chars-backward " \t") (bolp))
(setq base (current-indentation))))
(cond ((and (looking-at bsv-directive-end) (< base 0)) ;; Only matters when not at BOL
(setq ind (- ind bsv-indent-level-directive)))
((and (looking-at bsv-directive-middle) (>= base 0)) ;; Only matters when at BOL
(setq ind (+ ind bsv-indent-level-directive)))
((looking-at bsv-directive-begin)
(setq ind (+ ind bsv-indent-level-directive)))))
;; Adjust indent to starting indent of critical line
(setq ind (max 0 (+ ind base))))
(save-excursion
(beginning-of-line)
(skip-chars-forward " \t")
(cond ((or (looking-at bsv-directive-middle)
(looking-at bsv-directive-end))
(setq ind (max 0 (- ind bsv-indent-level-directive))))))
ind))
(defun bsv-leap-to-case-head ()
(let ((nest 1))
(while (/= 0 nest)
(bsv-re-search-backward
(concat
"\\(\\\\|\\(\\\\)"
"\\|\\(\\\\)" )
nil 'move)
(cond
((match-end 1)
(let ((here (point)))
(bsv-beg-of-statement)
(unless (looking-at bsv-extended-case-re)
(goto-char here)))
(setq nest (1- nest)))
((match-end 3)
(setq nest (1+ nest)))
((bobp)
(ding 't)
(setq nest 0))))))
(defun bsv-leap-to-head ()
"Move point to the head of this block.
Jump from end to matching begin, from endcase to matching case, and so on."
(let ((reg nil)
snest
(nesting 'yes)
(nest 1))
(cond
((looking-at "\\")
;; 1: Search back for matching begin
(setq reg (concat "\\(\\\\)\\|\\(\\\\)\\|"
"\\(\\\\)\\|\\(\\\\)" )))
((looking-at "\\")
;; 2: Search back for matching task
(setq reg "\\(\\\\)\\|\\(\\(\\(\\\\s-+\\)\\|\\(\\\\s-+\\)\\)+\\\\)")
(setq nesting 'no))
((looking-at "\\")
(catch 'nesting
(bsv-leap-to-case-head) )
(setq reg nil) ; to force skip
)
((looking-at "\\")
;; 4: Search back for matching fork
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((looking-at "\\")
;; 5: Search back for matching class
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((looking-at "\\")
;; 6: Search back for matching table
(setq reg "\\(\\\\)\\|\\(\\\\)" ))
((looking-at "\\")
;; 7: Search back for matching specify
(setq reg "\\(\\\\)\\|\\(\\