Function: verilog-auto-ascii-enum

verilog-auto-ascii-enum is a byte-compiled function defined in verilog-mode.el.gz.

Signature

(verilog-auto-ascii-enum)

Documentation

Expand AUTOASCIIENUM statements, as part of M-x verilog-auto (verilog-auto).

Create a register to contain the ASCII decode of an enumerated signal type. This will allow trace viewers to show the ASCII name of states.

First, parameters are built into an enumeration using the synopsys enum comment. The comment must be between the keyword and the symbol.
(Annoying, but that's what Synopsys's dc_shell FSM reader requires.)

Next, registers which that enum applies to are also tagged with the same enum.

Finally, an AUTOASCIIENUM command is used.

  The first parameter is the name of the signal to be decoded.

  The second parameter is the name to store the ASCII code into. For the
  signal foo, I suggest the name _foo__ascii, where the leading _ indicates
  a signal that is just for simulation, and the magic characters _ascii
  tell viewers like Dinotrace to display in ASCII format.

  The third optional parameter is a string which will be removed
  from the state names. It defaults to "" which removes nothing.

  The fourth optional parameter is "onehot" to force one-hot
  decoding. If unspecified, if and only if the first parameter
  width is 2^(number of states in enum) and does NOT match the
  width of the enum, the signal is assumed to be a one-hot
  decode. Otherwise, it's a normal encoded state vector.

  verilog-auto-wire-type may be used to change the datatype of
  the declarations.

  "synopsys enum" may be used in place of "auto enum".

An example:

        //== State enumeration
        parameter [2:0] // auto enum state_info
                           SM_IDLE = 3'b000,
                           SM_SEND = 3'b001,
                           SM_WAIT1 = 3'b010;
        //== State variables
        reg [2:0] /* auto enum state_info */
                   state_r; /* auto state_vector state_r */
        reg [2:0] /* auto enum state_info */
                   state_e1;

        /*AUTOASCIIENUM("state_r", "state_ascii_r", "SM_")*/

Typing M-x verilog-auto (verilog-auto) will make this into:

        ...
        /*AUTOASCIIENUM("state_r", "state_ascii_r", "SM_")*/
        // Beginning of automatic ASCII enum decoding
        reg [39:0] state_ascii_r; // Decode of state_r
        always @(state_r) begin
           case ({state_r})
                SM_IDLE: state_ascii_r = "idle ";
                SM_SEND: state_ascii_r = "send ";
                SM_WAIT1: state_ascii_r = "wait1";
                default: state_ascii_r = "%Erro";
           endcase
        end
        // End of automatics

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/verilog-mode.el.gz
(defun verilog-auto-ascii-enum ()
  "Expand AUTOASCIIENUM statements, as part of \\[verilog-auto].
Create a register to contain the ASCII decode of an enumerated signal type.
This will allow trace viewers to show the ASCII name of states.

First, parameters are built into an enumeration using the synopsys enum
comment.  The comment must be between the keyword and the symbol.
\(Annoying, but that's what Synopsys's dc_shell FSM reader requires.)

Next, registers which that enum applies to are also tagged with the same
enum.

Finally, an AUTOASCIIENUM command is used.

  The first parameter is the name of the signal to be decoded.

  The second parameter is the name to store the ASCII code into.  For the
  signal foo, I suggest the name _foo__ascii, where the leading _ indicates
  a signal that is just for simulation, and the magic characters _ascii
  tell viewers like Dinotrace to display in ASCII format.

  The third optional parameter is a string which will be removed
  from the state names.  It defaults to \"\" which removes nothing.

  The fourth optional parameter is \"onehot\" to force one-hot
  decoding.  If unspecified, if and only if the first parameter
  width is 2^(number of states in enum) and does NOT match the
  width of the enum, the signal is assumed to be a one-hot
  decode.  Otherwise, it's a normal encoded state vector.

  `verilog-auto-wire-type' may be used to change the datatype of
  the declarations.

  \"synopsys enum\" may be used in place of \"auto enum\".

An example:

        //== State enumeration
        parameter [2:0] // auto enum state_info
                           SM_IDLE =  3\\='b000,
                           SM_SEND =  3\\='b001,
                           SM_WAIT1 = 3\\='b010;
        //== State variables
        reg [2:0]  /* auto enum state_info */
                   state_r;  /* auto state_vector state_r */
        reg [2:0]  /* auto enum state_info */
                   state_e1;

        /*AUTOASCIIENUM(\"state_r\", \"state_ascii_r\", \"SM_\")*/

Typing \\[verilog-auto] will make this into:

        ...
        /*AUTOASCIIENUM(\"state_r\", \"state_ascii_r\", \"SM_\")*/
        // Beginning of automatic ASCII enum decoding
        reg [39:0]              state_ascii_r;          // Decode of state_r
        always @(state_r) begin
           case ({state_r})
                SM_IDLE:  state_ascii_r = \"idle \";
                SM_SEND:  state_ascii_r = \"send \";
                SM_WAIT1: state_ascii_r = \"wait1\";
                default:  state_ascii_r = \"%Erro\";
           endcase
        end
        // End of automatics"
  (save-excursion
    (let* ((params (verilog-read-auto-params 2 4))
	   (undecode-name (nth 0 params))
	   (ascii-name (nth 1 params))
	   (elim-regexp (and (nth 2 params)
			     (not (equal (nth 2 params) ""))
			     (nth 2 params)))
	   (one-hot-flag (nth 3 params))
	   ;;
	   (indent-pt (current-indentation))
	   (modi (verilog-modi-current))
	   (moddecls (verilog-modi-get-decls modi))
	   ;;
	   (sig-list-consts (append (verilog-decls-get-consts moddecls)
				    (verilog-decls-get-gparams moddecls)))
	   (sig-list-all  (verilog-decls-get-iovars moddecls))
	   ;;
	   (undecode-sig (or (assoc undecode-name sig-list-all)
			     (error "%s: Signal `%s' not found in design"
                                    (verilog-point-text) undecode-name)))
	   (undecode-enum (or (verilog-sig-enum undecode-sig)
			      (error "%s: Signal `%s' does not have an enum tag"
                                     (verilog-point-text) undecode-name)))
	   ;;
	   (enum-sigs (verilog-signals-not-in
		       (or (verilog-signals-matching-enum sig-list-consts undecode-enum)
			   (error "%s: No state definitions for `%s'"
                                  (verilog-point-text) undecode-enum))
		       nil))
	   ;;
	   (one-hot (or
		     (string-match "onehot" (or one-hot-flag ""))
                     (and  ; width(enum) != width(sig)
		      (or (not (verilog-sig-bits (car enum-sigs)))
			  (not (equal (verilog-sig-width (car enum-sigs))
				      (verilog-sig-width undecode-sig))))
		      ;; count(enums) == width(sig)
		      (equal (number-to-string (length enum-sigs))
			     (verilog-sig-width undecode-sig)))))
	   (enum-chars 0)
	   (ascii-chars 0))
      ;;
      ;; Find number of ascii chars needed
      (let ((tmp-sigs enum-sigs))
	(while tmp-sigs
	  (setq enum-chars (max enum-chars (length (verilog-sig-name (car tmp-sigs))))
		ascii-chars (max ascii-chars (length (verilog-enum-ascii
						      (verilog-sig-name (car tmp-sigs))
						      elim-regexp)))
		tmp-sigs (cdr tmp-sigs))))
      ;;
      (verilog-forward-or-insert-line)
      (verilog-insert-indent "// Beginning of automatic ASCII enum decoding\n")
      (let ((decode-sig-list (list (list ascii-name (format "[%d:0]" (- (* ascii-chars 8) 1))
					 (concat "Decode of " undecode-name) nil nil))))
	(verilog-insert-definition modi decode-sig-list "reg" indent-pt nil))
      ;;
      (verilog-insert-indent "always @(" undecode-name ") begin\n")
      (setq indent-pt (+ indent-pt verilog-indent-level))
      (verilog-insert-indent "case ({" undecode-name "})\n")
      (setq indent-pt (+ indent-pt verilog-case-indent))
      ;;
      (let ((tmp-sigs enum-sigs)
	    (chrfmt (format "%%-%ds %s = \"%%-%ds\";\n"
			    (+ (if one-hot 9 1) (max 8 enum-chars))
			    ascii-name ascii-chars))
	    (errname (substring "%Error" 0 (min 6 ascii-chars))))
	(while tmp-sigs
	  (verilog-insert-indent
	   (concat
	    (format chrfmt
		    (concat (if one-hot "(")
			    ;; Use enum-sigs length as that's numeric
			    ;; verilog-sig-width undecode-sig might not be.
			    (if one-hot (number-to-string (length enum-sigs)))
			    ;; We use a shift instead of var[index]
			    ;; so that a non-one hot value will show as error.
			    (if one-hot "'b1<<")
			    (verilog-sig-name (car tmp-sigs))
			    (if one-hot ")") ":")
		    (verilog-enum-ascii (verilog-sig-name (car tmp-sigs))
					elim-regexp))))
	  (setq tmp-sigs (cdr tmp-sigs)))
	(verilog-insert-indent (format chrfmt "default:" errname)))
      ;;
      (setq indent-pt (- indent-pt verilog-case-indent))
      (verilog-insert-indent "endcase\n")
      (setq indent-pt (- indent-pt verilog-indent-level))
      (verilog-insert-indent "end\n"
			     "// End of automatics\n"))))