From 5509c6add4c2bf1430c1ed0eb5770e259e1afcf9 Mon Sep 17 00:00:00 2001 From: Dan Nicolaescu Date: Tue, 6 May 2008 15:54:16 +0000 Subject: [PATCH] (verilog-getopt-file): Cleanup warning message format. (verilog-auto, verilog-auto-arg, verilog-auto-ascii-enum) (verilog-auto-inout, verilog-auto-inout-module) (verilog-auto-input, verilog-auto-inst, verilog-auto-inst-param) (verilog-auto-output, verilog-auto-output-every, verilog-auto-reg) (verilog-auto-reg-input, verilog-auto-reset, verilog-auto-sense) (verilog-auto-sense-sigs, verilog-auto-tieoff) (verilog-auto-unused, verilog-auto-wire) (verilog-decls-get-assigns, verilog-decls-get-consts) (verilog-decls-get-gparams, verilog-decls-get-inouts) (verilog-decls-get-inputs, verilog-decls-get-outputs) (verilog-decls-get-ports, verilog-decls-get-regs) (verilog-decls-get-signals, verilog-decls-get-wires) (verilog-dir-cache-lib-filenames, verilog-dir-cache-list) (verilog-dir-cache-preserving, verilog-dir-file-exists-p) (verilog-dir-files, verilog-expand-dirnames, verilog-getopt-file) (verilog-inject-sense, verilog-library-filenames) (verilog-mode-release-date, verilog-mode-version) (verilog-modi-cache-add, verilog-modi-cache-preserve-buffer) (verilog-modi-cache-preserve-tick, verilog-modi-cache-results) (verilog-modi-get-assigns, verilog-modi-get-consts) (verilog-modi-get-gparams, verilog-modi-get-inouts) (verilog-modi-get-inputs, verilog-modi-get-outputs) (verilog-modi-get-ports, verilog-modi-get-regs) (verilog-modi-get-signals, verilog-modi-get-sub-inouts) (verilog-modi-get-sub-inputs, verilog-modi-get-sub-outputs) (verilog-modi-get-wires, verilog-preserve-cache) (verilog-preserve-dir-cache, verilog-preserve-modi-cache) (verilog-read-sub-decls, verilog-read-sub-decls-line) (verilog-read-sub-decls-sig, verilog-subdecls-get-inouts) (verilog-subdecls-get-inputs, verilog-subdecls-get-outputs): Add caching of additional state, and rework signal extraction routines to improve AUTO expansion performance by 300%++. --- lisp/ChangeLog | 36 +++ lisp/progmodes/verilog-mode.el | 495 ++++++++++++++++++++------------- 2 files changed, 341 insertions(+), 190 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 465b1fb948e..67f9174a5bd 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,39 @@ +2008-05-06 Wilson Snyder + + * verilog-mode.el (verilog-getopt-file): Cleanup warning message format. + (verilog-auto, verilog-auto-arg, verilog-auto-ascii-enum) + (verilog-auto-inout, verilog-auto-inout-module) + (verilog-auto-input, verilog-auto-inst, verilog-auto-inst-param) + (verilog-auto-output, verilog-auto-output-every, verilog-auto-reg) + (verilog-auto-reg-input, verilog-auto-reset, verilog-auto-sense) + (verilog-auto-sense-sigs, verilog-auto-tieoff) + (verilog-auto-unused, verilog-auto-wire) + (verilog-decls-get-assigns, verilog-decls-get-consts) + (verilog-decls-get-gparams, verilog-decls-get-inouts) + (verilog-decls-get-inputs, verilog-decls-get-outputs) + (verilog-decls-get-ports, verilog-decls-get-regs) + (verilog-decls-get-signals, verilog-decls-get-wires) + (verilog-dir-cache-lib-filenames, verilog-dir-cache-list) + (verilog-dir-cache-preserving, verilog-dir-file-exists-p) + (verilog-dir-files, verilog-expand-dirnames, verilog-getopt-file) + (verilog-inject-sense, verilog-library-filenames) + (verilog-mode-release-date, verilog-mode-version) + (verilog-modi-cache-add, verilog-modi-cache-preserve-buffer) + (verilog-modi-cache-preserve-tick, verilog-modi-cache-results) + (verilog-modi-get-assigns, verilog-modi-get-consts) + (verilog-modi-get-gparams, verilog-modi-get-inouts) + (verilog-modi-get-inputs, verilog-modi-get-outputs) + (verilog-modi-get-ports, verilog-modi-get-regs) + (verilog-modi-get-signals, verilog-modi-get-sub-inouts) + (verilog-modi-get-sub-inputs, verilog-modi-get-sub-outputs) + (verilog-modi-get-wires, verilog-preserve-cache) + (verilog-preserve-dir-cache, verilog-preserve-modi-cache) + (verilog-read-sub-decls, verilog-read-sub-decls-line) + (verilog-read-sub-decls-sig, verilog-subdecls-get-inouts) + (verilog-subdecls-get-inputs, verilog-subdecls-get-outputs): + Add caching of additional state, and rework signal extraction + routines to improve AUTO expansion performance by 300%++. + 2008-05-06 Chong Yidong * progmodes/compile.el (compilation-error-regexp-alist-alist): diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el index 280c2270dde..e7720bfc1da 100644 --- a/lisp/progmodes/verilog-mode.el +++ b/lisp/progmodes/verilog-mode.el @@ -6220,31 +6220,31 @@ Return a array of [outputs inouts inputs wire reg assign const]." ;; Signal reading for given module ;; Note these all take modi's - as returned from the ;; verilog-modi-current function. -(defsubst verilog-modi-get-outputs (modi) - (aref (verilog-modi-get-decls modi) 0)) -(defsubst verilog-modi-get-inouts (modi) - (aref (verilog-modi-get-decls modi) 1)) -(defsubst verilog-modi-get-inputs (modi) - (aref (verilog-modi-get-decls modi) 2)) -(defsubst verilog-modi-get-wires (modi) - (aref (verilog-modi-get-decls modi) 3)) -(defsubst verilog-modi-get-regs (modi) - (aref (verilog-modi-get-decls modi) 4)) -(defsubst verilog-modi-get-assigns (modi) - (aref (verilog-modi-get-decls modi) 5)) -(defsubst verilog-modi-get-consts (modi) - (aref (verilog-modi-get-decls modi) 6)) -(defsubst verilog-modi-get-gparams (modi) - (aref (verilog-modi-get-decls modi) 7)) -(defsubst verilog-modi-get-sub-outputs (modi) - (aref (verilog-modi-get-sub-decls modi) 0)) -(defsubst verilog-modi-get-sub-inouts (modi) - (aref (verilog-modi-get-sub-decls modi) 1)) -(defsubst verilog-modi-get-sub-inputs (modi) - (aref (verilog-modi-get-sub-decls modi) 2)) - - -(defun verilog-read-sub-decls-sig (submodi comment port sig vec multidim) +(defsubst verilog-decls-get-outputs (decls) + (aref decls 0)) +(defsubst verilog-decls-get-inouts (decls) + (aref decls 1)) +(defsubst verilog-decls-get-inputs (decls) + (aref decls 2)) +(defsubst verilog-decls-get-wires (decls) + (aref decls 3)) +(defsubst verilog-decls-get-regs (decls) + (aref decls 4)) +(defsubst verilog-decls-get-assigns (decls) + (aref decls 5)) +(defsubst verilog-decls-get-consts (decls) + (aref decls 6)) +(defsubst verilog-decls-get-gparams (decls) + (aref decls 7)) +(defsubst verilog-subdecls-get-outputs (subdecls) + (aref subdecls 0)) +(defsubst verilog-subdecls-get-inouts (subdecls) + (aref subdecls 1)) +(defsubst verilog-subdecls-get-inputs (subdecls) + (aref subdecls 2)) + + +(defun verilog-read-sub-decls-sig (submoddecls comment port sig vec multidim) "For `verilog-read-sub-decls-line', add a signal." (let (portdata) (when sig @@ -6255,19 +6255,19 @@ Return a array of [outputs inouts inputs wire reg assign const]." (if multidim (setq multidim (mapcar `verilog-symbol-detick-denumber multidim))) (unless (or (not sig) (equal sig "")) ;; Ignore .foo(1'b1) assignments - (cond ((setq portdata (assoc port (verilog-modi-get-inouts submodi))) + (cond ((setq portdata (assoc port (verilog-decls-get-inouts submoddecls))) (setq sigs-inout (cons (list sig vec (concat "To/From " comment) nil nil (verilog-sig-signed portdata) (verilog-sig-type portdata) multidim) sigs-inout))) - ((setq portdata (assoc port (verilog-modi-get-outputs submodi))) + ((setq portdata (assoc port (verilog-decls-get-outputs submoddecls))) (setq sigs-out (cons (list sig vec (concat "From " comment) nil nil (verilog-sig-signed portdata) (verilog-sig-type portdata) multidim) sigs-out))) - ((setq portdata (assoc port (verilog-modi-get-inputs submodi))) + ((setq portdata (assoc port (verilog-decls-get-inputs submoddecls))) (setq sigs-in (cons (list sig vec (concat "To " comment) nil nil (verilog-sig-signed portdata) (verilog-sig-type portdata) @@ -6276,7 +6276,7 @@ Return a array of [outputs inouts inputs wire reg assign const]." ;; (t -- warning pin isn't defined.) ; Leave for lint tool ))))) -(defun verilog-read-sub-decls-line (submodi comment) +(defun verilog-read-sub-decls-line (submoddecls comment) "For `verilog-read-sub-decls', read lines of port defs until none match anymore. Return the list of signals found, using submodi to look up each port." (let (done port sig vec multidim) @@ -6336,11 +6336,11 @@ Return the list of signals found, using submodi to look up each port." (t (setq sig nil))) ;; Process signals - (verilog-read-sub-decls-sig submodi comment port sig vec multidim)))) + (verilog-read-sub-decls-sig submoddecls comment port sig vec multidim)))) (t (setq sig nil))) ;; Process signals - (verilog-read-sub-decls-sig submodi comment port sig vec multidim)) + (verilog-read-sub-decls-sig submoddecls comment port sig vec multidim)) ;; (forward-line 1))))) @@ -6375,21 +6375,23 @@ Outputs comments above subcell signals, for example: ;; Attempt to snarf a comment (let* ((submod (verilog-read-inst-module)) (inst (verilog-read-inst-name)) - (comment (concat inst " of " submod ".v")) submodi) + (comment (concat inst " of " submod ".v")) + submodi submoddecls) (when (setq submodi (verilog-modi-lookup submod t)) + (setq submoddecls (verilog-modi-get-decls submodi)) ;; This could have used a list created by verilog-auto-inst ;; However I want it to be runnable even on user's manually added signals (verilog-backward-open-paren) (setq end-inst-point (save-excursion (forward-sexp 1) (point)) st-point (point)) (while (re-search-forward "\\s *(?\\s *// Outputs" end-inst-point t) - (verilog-read-sub-decls-line submodi comment)) ;; Modifies sigs-out + (verilog-read-sub-decls-line submoddecls comment)) ;; Modifies sigs-out (goto-char st-point) (while (re-search-forward "\\s *// Inouts" end-inst-point t) - (verilog-read-sub-decls-line submodi comment)) ;; Modifies sigs-inout + (verilog-read-sub-decls-line submoddecls comment)) ;; Modifies sigs-inout (goto-char st-point) (while (re-search-forward "\\s *// Inputs" end-inst-point t) - (verilog-read-sub-decls-line submodi comment)) ;; Modifies sigs-in + (verilog-read-sub-decls-line submoddecls comment)) ;; Modifies sigs-in ))))) ;; Combine duplicate bits ;;(setq rr (vector sigs-out sigs-inout sigs-in)) @@ -6961,7 +6963,7 @@ Some macros and such are also found and included. For dinotrace.el." (if fns (set-buffer (find-file-noselect (car fns))) (error (concat (verilog-point-text) - "Can't find verilog-getopt-file -f file: " filename))) + ": Can't find verilog-getopt-file -f file: " filename))) (goto-char (point-min)) (while (not (eobp)) (setq line (buffer-substring (point) @@ -6996,6 +6998,69 @@ unless it is already a member of the variable's list." varref) ;;(progn (setq l '()) (verilog-add-list-unique `l "a") (verilog-add-list-unique `l "a") l) + +;; +;; Cached directory support +;; + +(defvar verilog-dir-cache-preserving nil + "If set, the directory cache is enabled, and file system changes are ignored. +See `verilog-dir-exists-p' and `verilog-dir-files'.") + +;; If adding new cached variable, add also to verilog-preserve-dir-cache +(defvar verilog-dir-cache-list nil + "Alist of (((Cwd Dirname) Results)...) for caching `verilog-dir-files'.") +(defvar verilog-dir-cache-lib-filenames nil + "Cached data for `verilog-library-filenames'.") + +(defmacro verilog-preserve-dir-cache (&rest body) + "Execute the BODY forms, allowing directory cache preservation within BODY. +This means that changes inside BODY made to the file system will not be +seen by the `verilog-dir-files' and related functions." + `(let ((verilog-dir-cache-preserving t) + verilog-dir-cache-list + verilog-dir-cache-lib-filenames) + (progn ,@body))) + +(defun verilog-dir-files (dirname) + "Return all filenames in the DIRNAME directory. +Relative paths depend on the `default-directory'. +Results are cached if inside `verilog-preserve-dir-cache'." + (unless verilog-dir-cache-preserving + (setq verilog-dir-cache-list nil)) ;; Cache disabled + ;; We don't use expand-file-name on the dirname to make key, as it's slow + (let* ((cache-key (list dirname default-directory)) + (fass (assoc cache-key verilog-dir-cache-list)) + exp-dirname data) + (cond (fass ;; Return data from cache hit + (nth 1 fass)) + (t + (setq exp-dirname (expand-file-name dirname) + data (and (file-directory-p exp-dirname) + (directory-files exp-dirname nil nil nil))) + ;; Note we also encache nil for non-existing dirs. + (setq verilog-dir-cache-list (cons (list cache-key data) + verilog-dir-cache-list)) + data)))) +;; Miss-and-hit test: +;;(verilog-preserve-dir-cache (prin1 (verilog-dir-files ".")) +;; (prin1 (verilog-dir-files ".")) nil) + +(defun verilog-dir-file-exists-p (filename) + "Return true if FILENAME exists. +Like `file-exists-p' but results are cached if inside +`verilog-preserve-dir-cache'." + (let* ((dirname (file-name-directory filename)) + ;; Correct for file-name-nondirectory returning same if no slash. + (dirnamed (if (or (not dirname) (equal dirname filename)) + default-directory dirname)) + (flist (verilog-dir-files dirnamed))) + (and flist + (member (file-name-nondirectory filename) flist) + t))) +;;(verilog-dir-file-exists-p "verilog-mode.el") +;;(verilog-dir-file-exists-p "../verilog-mode/verilog-mode.el") + ;; ;; Module name lookup @@ -7081,11 +7146,13 @@ If the variable vh-{symbol} is defined, substitute that value." (defun verilog-expand-dirnames (&optional dirnames) "Return a list of existing directories given a list of wildcarded DIRNAMES. Or, just the existing dirnames themselves if there are no wildcards." + ;; Note this function is performance critical. + ;; Do not call anything that requires disk access that cannot be cached. (interactive) (unless dirnames (error "`verilog-library-directories' should include at least '.'")) (setq dirnames (reverse dirnames)) ; not nreverse (let ((dirlist nil) - pattern dirfile dirfiles dirname root filename rest) + pattern dirfile dirfiles dirname root filename rest basefile) (while dirnames (setq dirname (substitute-in-file-name (car dirnames)) dirnames (cdr dirnames)) @@ -7099,18 +7166,19 @@ Or, just the existing dirnames themselves if there are no wildcards." pattern filename) ;; now replace those * and ? with .+ and . ;; use ^ and /> to get only whole file names - ;;verilog-string-replace-matches (setq pattern (verilog-string-replace-matches "[*]" ".+" nil nil pattern) pattern (verilog-string-replace-matches "[?]" "." nil nil pattern) - - ;; Unfortunately allows abc/*/rtl to match abc/rtl - ;; because abc/.. shows up in dirfiles. Solutions welcome. - dirfiles (if (file-directory-p root) ; Ignore version control external - (directory-files root t pattern nil))) + pattern (concat "^" pattern "$") + dirfiles (verilog-dir-files root)) (while dirfiles - (setq dirfile (expand-file-name (concat (car dirfiles) rest)) + (setq basefile (car dirfiles) + dirfile (expand-file-name (concat root basefile rest)) dirfiles (cdr dirfiles)) - (if (file-directory-p dirfile) + (if (and (string-match pattern basefile) + ;; Don't allow abc/*/rtl to match abc/rtl via .. + (not (equal basefile ".")) + (not (equal basefile "..")) + (file-directory-p dirfile)) (setq dirlist (cons dirfile dirlist))))) ;; Defaults (t @@ -7120,23 +7188,40 @@ Or, just the existing dirnames themselves if there are no wildcards." ;;(verilog-expand-dirnames (list "." ".." "nonexist" "../*" "/home/wsnyder/*/v")) (defun verilog-library-filenames (filename current &optional check-ext) - "Return a search path to find the given FILENAME name. + "Return a search path to find the given FILENAME or module name. Uses the CURRENT filename, `verilog-library-directories' and `verilog-library-extensions' variables to build the path. With optional CHECK-EXT also check `verilog-library-extensions'." - (let ((ckdir (verilog-expand-dirnames verilog-library-directories)) - fn outlist) - (while ckdir - (let ((ckext (if check-ext verilog-library-extensions `("")))) - (while ckext - (setq fn (expand-file-name - (concat filename (car ckext)) - (expand-file-name (car ckdir) (file-name-directory current)))) - (if (file-exists-p fn) - (setq outlist (cons fn outlist))) - (setq ckext (cdr ckext)))) - (setq ckdir (cdr ckdir))) - (nreverse outlist))) + (unless verilog-dir-cache-preserving + (setq verilog-dir-cache-lib-filenames nil)) + (let* ((cache-key (list filename current check-ext)) + (fass (assoc cache-key verilog-dir-cache-lib-filenames)) + chkdirs chkdir chkexts fn outlist) + (cond (fass ;; Return data from cache hit + (nth 1 fass)) + (t + ;; Note this expand can't be easily cached, as we need to + ;; pick up buffer-local variables for newly read sub-module files + (setq chkdirs (verilog-expand-dirnames verilog-library-directories)) + (while chkdirs + (setq chkdir (expand-file-name (car chkdirs) + (file-name-directory current)) + chkexts (if check-ext verilog-library-extensions `(""))) + (while chkexts + (setq fn (expand-file-name (concat filename (car chkexts)) + chkdir)) + ;;(message "Check for %s" fn) + (if (verilog-dir-file-exists-p fn) + (setq outlist (cons (expand-file-name + fn (file-name-directory current)) + outlist))) + (setq chkexts (cdr chkexts))) + (setq chkdirs (cdr chkdirs))) + (setq outlist (nreverse outlist)) + (setq verilog-dir-cache-lib-filenames + (cons (list cache-key outlist) + verilog-dir-cache-lib-filenames)) + outlist)))) (defun verilog-module-filenames (module current) "Return a search path to find the given MODULE name. @@ -7166,10 +7251,10 @@ Buffer-local.") (defvar verilog-modi-cache-preserve-tick nil "Modification tick after which the cache is still considered valid. -Use `verilog-preserve-cache' to set it.") +Use `verilog-preserve-modi-cache' to set it.") (defvar verilog-modi-cache-preserve-buffer nil "Modification tick after which the cache is still considered valid. -Use `verilog-preserve-cache' to set it.") +Use `verilog-preserve-modi-cache' to set it.") (defun verilog-modi-current () "Return the modi structure for the module currently at point." @@ -7260,10 +7345,10 @@ Return modi if successful, else print message unless IGNORE-ERROR is true." (defun verilog-modi-cache-results (modi function) "Run on MODI the given FUNCTION. Locate the module in a file. Cache the output of function so next call may have faster access." - (let (func-returns fass) - (save-excursion + (let (fass) + (save-excursion ;; Cache is buffer-local so can't avoid this. (verilog-modi-goto modi) - (if (and (setq fass (assoc (list (verilog-modi-name modi) function) + (if (and (setq fass (assoc (list modi function) verilog-modi-cache-list)) ;; Destroy caching when incorrect; Modified or file changed (not (and verilog-cache-enabled @@ -7275,26 +7360,26 @@ Cache the output of function so next call may have faster access." (setq verilog-modi-cache-list nil fass nil)) (cond (fass - ;; Found - (setq func-returns (nth 3 fass))) + ;; Return data from cache hit + (nth 3 fass)) (t ;; Read from file - ;; Clear then restore any hilighting to make Emacs 19 happy + ;; Clear then restore any hilighting to make emacs19 happy (let ((fontlocked (when (and (boundp 'font-lock-mode) font-lock-mode) (font-lock-mode nil) - t))) + t)) + func-returns) (setq func-returns (funcall function)) - (when fontlocked (font-lock-mode t))) + (when fontlocked (font-lock-mode t)) ;; Cache for next time (setq verilog-modi-cache-list - (cons (list (list (verilog-modi-name modi) function) + (cons (list (list modi function) (buffer-modified-tick) (visited-file-modtime) func-returns) - verilog-modi-cache-list))))) - ;; - func-returns)) + verilog-modi-cache-list)) + func-returns)))))) (defun verilog-modi-cache-add (modi function element sig-list) "Add function return results to the module cache. @@ -7303,13 +7388,13 @@ function now contains the additional SIG-LIST parameters." (let (fass) (save-excursion (verilog-modi-goto modi) - (if (setq fass (assoc (list (verilog-modi-name modi) function) + (if (setq fass (assoc (list modi function) verilog-modi-cache-list)) (let ((func-returns (nth 3 fass))) (aset func-returns element (append sig-list (aref func-returns element)))))))) -(defmacro verilog-preserve-cache (&rest body) +(defmacro verilog-preserve-modi-cache (&rest body) "Execute the BODY forms, allowing cache preservation within BODY. This means that changes to the buffer will not result in the cache being flushed. If the changes affect the modsig state, they must call the @@ -7359,22 +7444,22 @@ and invalidating the cache." (nreverse out-list)))) ;; Combined -(defun verilog-modi-get-signals (modi) +(defun verilog-decls-get-signals (decls) (append - (verilog-modi-get-outputs modi) - (verilog-modi-get-inouts modi) - (verilog-modi-get-inputs modi) - (verilog-modi-get-wires modi) - (verilog-modi-get-regs modi) - (verilog-modi-get-assigns modi) - (verilog-modi-get-consts modi) - (verilog-modi-get-gparams modi))) - -(defun verilog-modi-get-ports (modi) + (verilog-decls-get-outputs decls) + (verilog-decls-get-inouts decls) + (verilog-decls-get-inputs decls) + (verilog-decls-get-wires decls) + (verilog-decls-get-regs decls) + (verilog-decls-get-assigns decls) + (verilog-decls-get-consts decls) + (verilog-decls-get-gparams decls))) + +(defun verilog-decls-get-ports (decls) (append - (verilog-modi-get-outputs modi) - (verilog-modi-get-inouts modi) - (verilog-modi-get-inputs modi))) + (verilog-decls-get-outputs decls) + (verilog-decls-get-inouts decls) + (verilog-decls-get-inputs decls))) (defsubst verilog-modi-cache-add-outputs (modi sig-list) (verilog-modi-cache-add modi 'verilog-read-decls 0 sig-list)) @@ -7402,10 +7487,6 @@ and invalidating the cache." (while (verilog-re-search-forward search-for nil t) (funcall func))) -(defun verilog-auto-search-do (search-for func) - "Search for the given auto text SEARCH-FOR, and perform FUNC where it occurs." - (verilog-auto-re-search-do (regexp-quote search-for) func)) - (defun verilog-insert-one-definition (sig type indent-pt) "Print out a definition for SIG of the given TYPE, with appropriate INDENT-PT indentation." @@ -7760,8 +7841,9 @@ Typing \\[verilog-inject-auto] will make this into: (save-excursion (goto-char (point-min)) (while (verilog-re-search-forward-quick "\\