Next: , Previous: Event log procedures, Up: Procedures and variables


2.4.6 HDL generation procedures

The module (thud thgen) provides procedures to instantiate THUD HDL forms for a named device using a generator that you specify for that device. The installed program thgen makes these facilities available to the shell.

2.4.6.1 Generation concepts

A generator comprises three pieces of information: the list of configuration variables specific to the device (if any); the template of THUD HDL forms with specially indicated subtitution locations; and the variables-alist callback procedure that computes what values to substitute, taking an lookup procedure get and returning the settings as a list of variable/value pairs (an alist).

Configuration variables are specified with the general form:

     (NAME DEFAULT-VALUE TYPE [RESERVED...])

name is a symbol. type is a keyword, one of:

Finally, default-value is either the keyword #:UNSET (note uppercase), or some suitable value to use in the case name is not overridden. The reserved... means that the specification is not yet finalized; i.e., do not rely on type being the “last” field, etc.

Here are the built-in configuration variables:

(seed 0 #:integer)
(seq-beg 0 #:integer)
(seq-end 15 #:integer)
These are used internally, and will probably be replaced by THUD 1.0 release with a more general mechanism for permuting variables that doesn't require “user-level” encode/decode. For the present, you can use seed for any purpose; its value ranges from seq-beg through seq-end (inclusively).
(width 1 #:integer)
This is conventionally used for the datapath width (in bits).
(block-name #:UNSET #:symbol)
This is the name of the block in the blk form.

The template is a list of top-level THUD HDL forms, typically starting with a blk form, followed by one or more a. and n. forms that implement the device's behavior. Within the forms, the location where configuration variables are to be substituted is indicated by either comma, which substitutes the variable's value directly; or comma-at, which takes the variable's value as a list and substitutes the elements of the list (without the top-level surrounding parentheses). This is directly analogous to the unquote and unquote-splicing Scheme constructs (no surprise).

The template may also be a symbol naming another device generator to inherit from. In this way you can share a general device's template with more specific devices.

2.4.6.2 From a Scheme program
— Procedure: format-symbol fstr [args...]

Return a symbol whose name is formatted by applying simple-format to fstr and args.

— Procedure: define-generator name [args...]

name is a unique name for the generator, a symbol that identifies the device generated, such as fully-decoded-mux. args is a list of alternating keywords and associated values. Valid keywords:

#:vars '(VARSPEC...)
Declare configuration variables specific to name. Note that the list of varspec forms is prefixed with a single-quote.
#:template 'TEMPLATE
Declare template for name. template may be the name of another device, or a list of HDL forms. Note that template is prefixed with a single-quote.
#:var-alist-proc (lambda (get) ...)
get is a procedure that retrieves the current value of a configuration variable:
               (get 'seed)  42

The var-alist-proc should return an alist associating configuration variables with computed values.

— Procedure: thgen config

Generate a sequence of instances, ranging a seed value from seq-beg to seq-end (inclusive). Return the sequence.

— Procedure: thgen/command-line-rest rest

Process the list of strings rest (as if they were command-line arguments from the shell) and call thgen with the properly massaged configuration. Return what thgen returns. The first element of rest should name a previously-defined device.

THUD is distributed with two generators built-in: mux and flop. We include their definitions here as an example of how to use define-generator.

     (define-generator 'mux
     
       #:template
       '((blk ,block-name
              (out ,width x)
              (in  ,width a0)
              (in  ,width a1)
              (in  sel))
         (a. x (| (& (! sel) a0) (& sel a1))))
     
       #:var-alist-proc
       (lambda (get)
         (let ((seed (get 'seed)))
           `((block-name . ,(format-symbol "mux~A" seed))
             (width . ,seed)))))
     
     (define-generator 'flop
     
       #:template
       '((blk ,block-name
              (out ,width q)
              (in  ,width d)
              (in         en))
         (reg ,width state)
         (a. q state)
         (n. state (| (&    en  d)
                      (& (! en) state))))
     
       #:var-alist-proc
       (lambda (get)
         (let ((seed (get 'seed)))
           `((block-name . ,(format-symbol "flop~A" seed))
             (width . ,seed)))))
2.4.6.3 From the shell

Some quick examples, presuming we are in the distribution's bin subdirectory after successfully completing make && make check:

     # To use the `mux' built-in type:
     ./thgen -- mux
     
     # To try the fully-decoded mux example:
     ./thgen -l ../examples/thgen/fully-decoded-mux.thgen-config -- \
             fully-decoded-mux
     
     # Similarly, but only from 2:1 through 8:1, with a 53-bit
     # datapath, changed name pattern, and displaying the output
     # using `pretty-print':
     ./thgen -p -l ../examples/thgen/fully-decoded-mux.thgen-config -- \
             fully-decoded-mux --seq-beg 2 \
                               --seq-end 8 \
                               --width 53 \
                               --block-name-pattern "dmux~A"

Note that in all cases, the -- (double-dash) separates the arguments (if any) for program thgen from the device name and the subsequent configuration variable settings (if any).