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"))))