Difference between revisions of "Genesis2"

From Genesis2
Jump to: navigation, search
(Parametrization Methods)
(Parametrization Methods)
Line 808: Line 808:
  
 
==== Parametrization Methods ====
 
==== Parametrization Methods ====
; sub parameter: API method and syntactic sugar for <i>$self->define_param</i>, <i>$self->force_param</i>, $self->doc_param</i>, <i>$self->param_range</i>. This is the main call for defining any parameter and specifying its default value, documentation and range. The call to <i>parameter</i> can be done in either method- or function-call format. More details on parametrization in Genesis2 can be found [[#A_Word_About_Genesis2_Elaboration_Order_And_Parameterization|here]]
+
; sub parameter: This is the main call for defining a new parameter (just like defining a parameter in SystemVerilog), and specifying its default value, documentation and range. Note that using the ''parameter'', parameters can only be defined inside the module to which they belong (i.e., a call to ''$someOtherInst->parameter(...arguments...)'' will cause a genesis generation error). Much like SystemVerilog, parameters can also be overridden at instantiation using the ''generate'' method as shown below. Definition at instantiation time overwrites definitions done within the module (just like in Verilog). As a middle ground, parameter definitions that are not bounded by instantiation can be set using the input XML configuration file. More details can be found [[Genesis2#A_Word_About_Genesis2_Elaboration_Order_And_Parameterization|here]].
 +
 
 +
Notes:
 +
* The call to <i>parameter</i> can be done in either method- or function-call format.
 +
* This API method/function is in fact syntactic sugar for the older parameter definition methods <i>$self->define_param</i>, <i>$self->force_param</i>, $self->doc_param</i>, <i>$self->param_range</i>.
 +
 
 
<pre>
 
<pre>
 
//; my $prmVal = parameter(name=>'prmName', # required
 
//; my $prmVal = parameter(name=>'prmName', # required

Revision as of 22:38, 8 November 2011

Synopsis

As power constraints continue to impact traditional chip design, and custom design costs become prohibitively expensive, the only economic way for companies to produce new ASICs is to embed and reuse designers’ knowledge. In fact, most companies are already doing exactly that by creating in-house “generator” scripts.

We have developed a pre-processing tool for designing digital and mixed-signal chips. This chip generator technology (“Genesis2”) changes the programming paradigm to allow designers to embed their knowledge when constructing RTL design modules. Genesis2 enables the designer to simultaneously code in two interleaved languages for a rich, extensible software environment: one language generically describes the hardware proper and the other one decides what specific hardware to instantiate. This process allows for greater flexibility in the initial construction and later elaboration of the design without compromising strict synthesizability rules for the functionality of the module. Put differently, Genesis2 enables not only an easier, standardized method for creation of module generators, but also aggregates those unit level generators together into a full chip generator. Ultimately, Genesis2 enables users to design an entire family of chips at once using a chip template that is then elaborated into multiple different per-application customized chips.


The rest of this page describes Genesis2 and how to use it.

Comments are welcome: Ofer Shacham, Ofer Shacham

Getting Started With Genesis2

Setting Your Environment

Setting Xemacs/Emacs Verilog Mode

To set xemacs such that it starts in verilog mode, add the following code to your ~/.xemacs/init.el file. OR...

To set emacs such that it starts in verilog mode, add the following code to your ~/.emacs file:

;; Load verilog mode only when needed
(autoload 'verilog-mode "verilog-mode" "Verilog mode" t )
;; Any files that end in .v should be in verilog mode
(setq auto-mode-alist
      (append '(
                ("\\.v\\'" . verilog-mode);; for verilog files
                ("\\.vh\\'" . verilog-mode);; for verilog header files
                ("\\.sv\\'" . verilog-mode);; for system verilog files
                ("\\.svh\\'" . verilog-mode);; for system verilog header files
                ("\\.vp\\'" . verilog-mode);; for pre-processed Genesis files
                ("\\.vph\\'" . verilog-mode));; for pre-processed Genesis header files
              auto-mode-alist))
  • Note that a loader for verilog mode may have already been defined. In that case either modify it to identify .vp and .vph files, or replace with the above code.

Of course, you would have to make sure that you have the file ~/elisp/verilog-mode.el. Since we keep an elisp folder on p4 (under $SMASH/elisp/, the easiest option might be to just soft link to that folder from your home directory. See ~shacham/elisp and ~shacham/.xemacs/init.el for reference.

Missing Perl Libraries?

Genesis2 is written in Perl. However not all Linux distributions are born equal and as a result, some machines lack certain Perl Libraries needed by Genesis2. So far, libraries that I have seen missing include XML::Simple and XML::SAX / XML::Parser (you only need one of SAX or Parser).

These libraries are freely available from CPAN. To install these libraries simply follow these steps:

  1. Login as root
  2. Open a CPAN shell:
     perl -MCPAN -e shell
  3. Install the library XML::SAX (required by XML::Simple). Make sure to answer yes for installing all library dependencies!
     cpan> install XML::SAX 
  4. Install the library XML::Simple
     cpan> install XML::Simple 

Adding Genesis2 To Your Execution Path

Working On Stanford Machines

New! As of Dec 3rd, 2010: Genesis2 is now available through the common module load system just like any other cad tool. To load Genesis2 do the following:

  1. If you have not already done so, source the module loader by typing:
    source /cad/modules/init_modules.csh
  2. Load the Genesis2 module
    module load genesis2

That's it. You are good to go.

Working Locally On Your Own Server/Machine

First, install the Genesis2 files. For example, you can put them under $USER/bin/PerlLibs/Genesis2. It should look something like this:

vlsi: ~/bin/PerlLibs/Genesis2> ls -R

.:
Auxiliary/ Genesis2.pl Manager.pm UniqueModule.pm

./Auxiliary:
TypeConv.pm

Then, to add Genesis2 to your execution path, simply type (or place at the end of your .cshrc file):

setenv GENESIS_LIBS "~USER/bin/PerlLibs"
set path=($GENESIS_LIBS/Genesis2 $path)

With time, you may want to add more Perl libraries (i.e., .pm files). Say you place those under $USER/bin/Genesis2LocalLibs, just add the following line to your environment so that Genesis knows where to look for them:

setenv GENESIS_PROJECT_LIBS $USER/bin/Genesis2LocalLibs

Genesis2 File Types

Main File Types

SomeModule.vp And SomeIncludeFile.vph Files

These are the user's files. That is, when you come to write a hardware module that you want Genesis2 to elaborate, you should write it in a file named base_module_name.vp. For example, if the module name is onehotmux, it should be placed in a file named onehotmux.vp.

Included files should be named whatever.vph. In fact, this requirement is not real and whatever.anything or even whatever would work. However, for nice coding style, and for xemacs verilog mode to work nicely, the whatever.vph is recommended.

SomeModule.pm Files

Genesis2 generates intermediate Perl module files (Given the file filename1.vp, Genesis2 would generate filename1.pm). Typically there is no reason to look at these files, except for debugging of parsing errors and their like.

Note that Genesis2 works in two stages: First all the .pm files are generated. These files are, in fact, a complete object oriented program in Perl, where each module represents a module generator. Then, after all the Perl modules are created, Genesis2 executes the newly created Perl program that in turn generates Verilog.

SomeModule.v Files

The final type of file of interest is the generated verilog file. This code should consist of only verilog, and will eventually be fed to VCS/dc_shell/other tools.

  • Note: For every somemodule.vp input file, there may be more than one verilog file generated. If somemodule is instantiated in different places using different parameters, each different instance would be uniquified. The resulting verilog files would be named somemodule_unq0.v, somemodule_unq1.v, etc.

Program.xml File

The XML input program has a very simple structure. Yet, one has to remember that XML is best if read/written by machine and not human. The absolutly best way to get started is to let Genesis2 run with the -hierarchy outfile.xml flag set. This will create an output xml representation which is a superset of the input xml representation and can serve as a template.

NEW! See Genesis2SchemaXSD page!

Having said that, the following is a description of the input XML schema:

  • There are a few reserved element names: HierarchyTop, BaseModuleName, InstanceName, Parameters, ImmutableParameters, ParameterItem, Name, Val, Doc, Range, List, Min, Max, Step, SubInstances, SubInstanceItem, UniqueModuleName, CloneOf, HashType, HashItem, Key, ArrayType, ArrayItem, InstancePath. Avoid using these key words in any context other than the one explained here or in the output xml representation section.
  • HierarchyTop: There is a single root element which represents the top module of the design (since the top module is never instantiated, it is referred to by HierarchyTop and not by an instance name). A minimal (but legal) input XML structure would contain the following text:
<HierarchyTop></HierarchyTop>
  • General tree structure: For each module instance in the hierarchy (including HierarchyTop) the following recursive structure can be used. It must have an InstanceName element (except for the HierarchyTop), and it can optionally have Parameters and SubInstances elements. Omitting the Parameters or the SubInstances element is ok. However, omitting the InstanceName will result in an error!
Example of top level:
<HierarchyTop>
    <!-- Optional: -->
    <Parameters>
        <!-- List zero or more ParameterItem elements-->
    </Parameters>
    <SubInstances>
        <!-- List zero or more SubInstanceItem elements-->
    </SubInstances>
</HierarchyTop>
Example for internal node
<SubInstances>
    <SubInstanceItem>
        <!-- Mandatory: -->
        <InstanceName>someInstanceName</InstanceName>

        <!-- Optional: -->
        <Parameters>
            <!-- List zero or more ParameterItem elements-->
        </Parameters>
        <SubInstances>
            <!-- List zero or more SubInstanceItem elements-->
        </SubInstances>
    </SubInstanceItem>
    ...
    <!-- More SubInstanceItem elements-->
    ...
</SubInstances>
  • SubInstances: (Optional) A list of zero or more SubInstanceItem elements that represent the sub-instances in the current hierarchy level. The same rules apply recursively for each of these elements. Note that if an instance is encountered during elaboration, but the corresponding SubInstanceItem is missing from the XML tree, it will be assumed that that instance uses the default parameters or the instantiation line parameters, as noted in the .vp files. If a SubInstanceItem element that does not correspond to any instance in the design is encountered, than it is simply ignored.
<SubInstances>
    <SubInstanceItem>
        <InstanceName>someInstanceName_A</InstanceName>
        ...
    </SubInstanceItem>
    <SubInstanceItem>
        <InstanceName>someInstanceName_B</InstanceName>
        ...
    </SubInstanceItem>
    ...
    <!-- More SubInstanceItem elements-->
    ...
</SubInstances>
  • Parameters: (Optional) A list of zero or more ParameterItem. Note that if a ParameterItem is missing from the list, it is assumed that its value is not overwritten by XML. If ParameterItem exists for a parameter that is not defined in the .vp file, it is simply ignored. Of course, two ParameterItem elements carrying the same Name will produce an error. Each myValue of a parameter myParam would be written as:
<Parameters>
    <ParameterItem>
        <Name>myParam</Name>
        <Val>>myValue</Val>
    </ParameterItem>
    ...
    <!-- More ParameterItem elements-->
    ...
</Parameters>
  • For Parameters, note that more complicated data structures are also supported. Simply replace the Val element with the HashType to show that a parameter is a hash rather than a string/scalar or with the ArrayType to show that a parameter is an array rather than a string/scalar. Array of hashes and hash of arrays (or any recursive combination) is also supported. Finally, an InstancePath element can be used to express that a parameter represents a reference to a particular instance in the design hierarchy (i.e., it is a pointer to another object).
    • Each ArrayType contains a list of zero or more ArrayItem elements. An empty array is an ArrayType with no internal ArrayItem. Each ArrayItem must contain a Val OR HashType OR ArrayType OR InstancePath element. (see example next)
    • Each HashType contains a list of zero or more HashItem elements. An empty hash is a HashType with no internal HashItem. Each HashItem must contain a Key element AND a Val OR HashType OR ArrayType OR InstancePath element. Of course, two HashItem elements carrying the same Key will produce an error. (see example next)
    • InstancePath is a string that represents a complete path such as "top.dut.unit1"
<Parameters>
    <ParameterItem>
        <Name>myArrayParam</Name>
        <ArrayType>
            <ArrayItem>
                <Val>1</Val>
            </ArrayItem>
            <ArrayItem>
                <Val>2</Val>
            </ArrayItem>
            <ArrayItem>
                <Val>3</Val>
            </ArrayItem>
            ...
            <!-- More ArrayItem elements-->
            ...
        </ArrayType>
    </ParameterItem>
    <ParameterItem>
        <Name>myHashParam</Name>
        <HashType>
            <HashItem>
                <Key>somekey</Key>
                <Val>someval<Val>
            </HashItem>
            <HashItem>
                <Key>anotherkey</Key>
                <Val>anotherval</Val>
            </HashItem>
            ...
            <!-- More HashItem elements-->
            ...
        </HashType>
    </ParameterItem>
    <ParameterItem>
        <Name>myRefToAnotherInstance</Name>
        <InstancePath>name_of_top_module.name_of_sub_instance_1</InstancePath>
    </ParameterItem>
</Parameters>
  • Example of full hierarchical XML program input example:
<HierarchyTop>
   <Parameters>
      <ParameterItem>
         <Name>some_param_name_1</Name>
         <Val>>12</Val>
      </ParameterItem>
      <ParameterItem>
         <Name>some_param_name_2</Name>
         <Val>>15</Val>
      <ParameterItem>
   </Parameters>
   <SubInstances>
      <SubInstanceItem>
         <InstanceName>name_of_sub_instance_1</InstanceName>
         <Parameters>
            <ParameterItem>
               <Name>some_param_name_1</Name>
               <Val>5</Val>
            </ParameterItem>
            <ParameterItem>
               <Name>some_param_name_2</Name>
               <Val>3</Val>
            </ParameterItem>
            <ParameterItem>
               <Name>my_empty_array</Name>
               <ArrayType></ArrayType>
            </ParameterItem>
            <ParameterItem>
               <Name>my_empty_hash</Name>
               <HashType></HashType>
            </ParameterItem>
            <ParameterItem>
               <Name>some_array_param_name</Name>
               <ArrayType>
                  <ArrayItem>
                     <Val>element_1</Val>
                  </ArrayItem>
                  <ArrayItem>
                     <Val>element_2</Val>
                  </ArrayItem>
               </ArrayType>
            </ParameterItem>
            <ParameterItem>
               <Name>some_hash_param_name</Name>
               <HashType>
                  <HashItem>
                     <Key>some_key_1</Key>
                     <Val>val_1</Val>
                  </HashItem>
                  <HashItem>
                     <Key>some_key_2</Key>
                     <Val>val_2</Val>
                  </HashItem>
               </HashType>
            </ParameterItem>
         </Parameters>
      </SubInstanceItem>
      <SubInstanceItem>
         <InstanceName>name_of_sub_instance_2</InstanceName>
         <Parameters>
            <ParameterItem>
               <Name>some_param_name_1</Name>
               <Val>73</Val>
            </ParameterItem>
            <ParameterItem>
               <Name>some_param_name_1</Name>
               <Val>45</Val>
            </ParameterItem>
            <ParameterItem>
               <Name>some_instance_ref</Name>
               <InstancePath>
                  name_of_top_module.name_of_sub_instance_1
               </InstancePath>
            </ParameterItem>
         </Parameters>
         <SubInstances>
            <SubInstanceItem>
               <InstanceName>name_of_sub_sub_instance_1</InstanceName>
               <Parameters>
                  <ParameterItem>
                     <Name>some_param_name_1</Name>
                     <Val>1</Val>
                  </ParameterItem>
                  <ParameterItem>
                     <Name>some_param_name_2</Name>
                     <Val>2</Val>
                  </ParameterItem>
               </Parameters>
               <SubInstances>
               </SubInstances>
            </SubInstanceItem>
         </SubInstances>
      </SubInstanceItem>
   </SubInstances>
</HierarchyTop>

Additional Output File Types

Genesis2 produces some additional outputs, on top of the Verilog files: a dependent list (using the -depend depend_file_name flag), a product list (using the -product product_file_name flag), and an xml hierarchy representation of the design (using the -hierarchy hierarchy_file_name flag).

Depend List

List of the source .vp files and included .vph files that were used by Genesis2

Product List

This very important list is a list of the generated verilog (.v) files. This list is convenient, for example for use as input to downstream tools such as VCS, or for use in makefiles.

Note that the list is arranged in reverse hierarchical order which means the lowest level modules are listed first, and the top module last. The reason for this reversed order is so that it can be used for compilation.

Hierarchy Out

The XML hierarchy output representation is almost identical to the input XML program. It also has a very simple structure, but it adds more information about source and target modules and files. In addition to providing useful feedback to the designer, the hierarchical XML was designed to be used as a template for the XML input program.

NEW! See Genesis2SchemaXSD page!

To avoid duplicate instructions, and since the output XML is strictly a superset of the input XML, please refer to the input xml program section for the basic structure of the XML tree. This section will highlight the additional information that is provided in the output XML schema. An example of a hierarchical outfile follows. Note that structure-wise:

  • General tree structure: For each module instance in the hierarchy (including HierarchyTop) the following recursive structure is used. It has a BaseModuleName, InstanceName, ImmutableParameters, Parameters, SubInstances, UniqueModuleName
    • BaseModuleName: The name of the template module before uniquification
    • InstanceName: The name of the instance that was generated
    • ImmutableParameters: A list of zero or more ParameterItem elements. ImmutableParameters has the exact same structure as that of the Parameters element. However, while Parameters can be altered and re-fed into Genesis2 using the input xml program to create new RTL, ImmutableParameters are parameters that where already assigned a value, either using $self->force_param(...) call or at instantiation using the $self->unique_inst(...) or $self->generate call.
    • Parameters: A list of zero or more ParameterItem elements. In addition to the Name and Val fields as described for the input xml schema, the output XML schema also has a Doc and a Range elements, but only for simple Val parameters (i.e., simple parameters that are numbers or strings but not arrays or hashes or pointers).
      • Doc: A documentation or description of a parameter.
      • Range: An allowed range for a parameter value. The Range element support two mutually exclusive options:
        • List: A list of allowed values. Or,
        • Min and/or Max and/or Step: At least on of Min or Max element and optionally a Step element.
    • SubInstances: A list of SubInstanceItem elements that represent the sub-instances in the current hierarchy level. See more in the input xml schema section.
    • UniqueModuleName: The name of the generated module after uniquification
    • CloneOf: If the instance is a clone of another instance, the field CloneOf appears instead of the fields Parameters, ImmutableParameters and SubInstances. CloneOf would then have a sub-element, InstancePath, that holds the a text path to the original instance (e.g., top.dut.subinst.subsubinst).

Next is an example of a complete XML hierarchy. In this example, the top level instantiate 2 Wallace trees. In addition, it instantiate two clones of those Wallace trees (only for the purpose of this example). In addition, (again, for the example only) each Wallce module has numerous parameter definitions of various kinds.

<HierarchyTop>
  <BaseModuleName>top</BaseModuleName>
  <ImmutableParameters></ImmutableParameters>
  <InstanceName>top</InstanceName>
  <Parameters>
    <ParameterItem>
      <ArrayType>
        <ArrayItem>
          <Val>32</Val>
        </ArrayItem>
        <ArrayItem>
          <Val>64</Val>
        </ArrayItem>
      </ArrayType>
      <Doc></Doc>
      <Name>WALLACES_WIDTHS</Name>
    </ParameterItem>
  </Parameters>
  <SubInstances>
    <SubInstanceItem>
      <BaseModuleName>wallace</BaseModuleName>
      <ImmutableParameters>
        <ParameterItem>
          <Doc>This is the bit width of the partial products</Doc>
          <Name>N</Name>
          <Range>
            <List>8</List>
            <List>16</List>
            <List>32</List>
            <List>64</List>
          </Range>
          <Val>32</Val>
        </ParameterItem>
      </ImmutableParameters>
      <InstanceName>wallace_32</InstanceName>
      <Parameters>
        <ParameterItem>
          <Name>COND</Name>
          <Doc>the value can be true or false</Doc>
          <Range>
            <List>false</List>
            <List>true</List>
          </Range>
          <Val>false</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMin</Name>
          <Doc></Doc>
          <Range>
            <Min>106</Min>
          </Range>
          <Val>107</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMax</Name>
          <Doc></Doc>
          <Range>
            <Max>210</Max>
          </Range>
          <Val>200</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinStep</Name>
          <Doc></Doc>
          <Range>
            <Min>300</Min>
            <Step>3</Step>
          </Range>
          <Val>309</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMaxStep</Name>
          <Doc></Doc>
          <Range>
            <Max>410</Max>
            <Step>2</Step>
          </Range>
          <Val>404</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinMax</Name>
          <Doc></Doc>
          <Range>
            <Max>510</Max>
            <Min>500</Min>
          </Range>
          <Val>505</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinMaxStep</Name>
          <Doc></Doc>
          <Range>
            <Max>630</Max>
            <Min>610</Min>
            <Step>2</Step>
          </Range>
          <Val>622</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamExamplePointerToMe</Name>
          <Doc></Doc>
          <InstancePath>top.wallace_32</InstancePath>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamHash</Name>
          <Doc></Doc>
          <HashType>
            <HashItem>
              <Key>alma</Key>
              <Val>4</Val>
            </HashItem>
            <HashItem>
              <Key>neta</Key>
              <Val>2</Val>
            </HashItem>
            <HashItem>
              <Key>ofer</Key>
              <Val>1</Val>
            </HashItem>
            <HashItem>
              <Key>ori</Key>
              <Val>3</Val>
            </HashItem>
          </HashType>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamComplexStruct</Name>
          <Doc></Doc>
          <ArrayType>
            <ArrayItem>
              <Val>value</Val>
            </ArrayItem>
            <ArrayItem>
              <ArrayType>
                <ArrayItem>
                  <Val>1</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>2</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>3</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>4</Val>
                </ArrayItem>
              </ArrayType>
            </ArrayItem>
            <ArrayItem>
              <HashType>
                <HashItem>
                  <Key>a</Key>
                  <Val>1</Val>
                </HashItem>
                <HashItem>
                  <Key>b</Key>
                  <Val>2</Val>
                </HashItem>
                <HashItem>
                  <Key>c</Key>
                  <Val>3</Val>
                </HashItem>
                <HashItem>
                  <ArrayType>
                    <ArrayItem>
                      <Val>a</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>b</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>c</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>x</Val>
                    </ArrayItem>
                  </ArrayType>
                  <Key>d</Key>
                </HashItem>
              </HashType>
            </ArrayItem>
          </ArrayType>
        </ParameterItem>
      </Parameters>
      <SubInstances></SubInstances>
      <UniqueModuleName>wallace_unq1</UniqueModuleName>
    </SubInstanceItem>
    <SubInstanceItem>
      <BaseModuleName>wallace</BaseModuleName>
      <CloneOf>
        <InstancePath>top.wallace_32</InstancePath>
      </CloneOf>
      <InstanceName>clone_of_wallce_32</InstanceName>
      <UniqueModuleName>wallace_unq1</UniqueModuleName>
    </SubInstanceItem>
    <SubInstanceItem>
      <BaseModuleName>wallace</BaseModuleName>
      <ImmutableParameters>
        <ParameterItem>
          <Doc>This is the bit width of the partial products</Doc>
          <Name>N</Name>
          <Range>
            <List>8</List>
            <List>16</List>
            <List>32</List>
            <List>64</List>
          </Range>
          <Val>64</Val>
        </ParameterItem>
      </ImmutableParameters>
      <InstanceName>wallace_64</InstanceName>
      <Parameters>
        <ParameterItem>
          <Name>COND</Name>
          <Doc>the value can be true or false</Doc>
          <Range>
            <List>false</List>
            <List>true</List>
          </Range>
          <Val>false</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMin</Name>
          <Doc></Doc>
          <Range>
            <Min>106</Min>
          </Range>
          <Val>107</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMax</Name>
          <Doc></Doc>
          <Range>
            <Max>210</Max>
          </Range>
          <Val>200</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinStep</Name>
          <Doc></Doc>
          <Range>
            <Min>300</Min>
            <Step>3</Step>
          </Range>
          <Val>309</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMaxStep</Name>
          <Doc></Doc>
          <Range>
            <Max>410</Max>
            <Step>2</Step>
          </Range>
          <Val>404</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinMax</Name>
          <Doc></Doc>
          <Range>
            <Max>510</Max>
            <Min>500</Min>
          </Range>
          <Val>505</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParWithMinMaxStep</Name>
          <Doc></Doc>
          <Range>
            <Max>630</Max>
            <Min>610</Min>
            <Step>2</Step>
          </Range>
          <Val>622</Val>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamExamplePointerToMe</Name>
          <Doc></Doc>
          <InstancePath>top.wallace_64</InstancePath>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamHash</Name>
          <Doc></Doc>
          <HashType>
            <HashItem>
              <Key>alma</Key>
              <Val>4</Val>
            </HashItem>
            <HashItem>
              <Key>neta</Key>
              <Val>2</Val>
            </HashItem>
            <HashItem>
              <Key>ofer</Key>
              <Val>1</Val>
            </HashItem>
            <HashItem>
              <Key>ori</Key>
              <Val>3</Val>
            </HashItem>
          </HashType>
        </ParameterItem>
        <ParameterItem>
          <Name>ParamComplexStruct</Name>
          <Doc></Doc>
          <ArrayType>
            <ArrayItem>
              <Val>value</Val>
            </ArrayItem>
            <ArrayItem>
              <ArrayType>
                <ArrayItem>
                  <Val>1</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>2</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>3</Val>
                </ArrayItem>
                <ArrayItem>
                  <Val>4</Val>
                </ArrayItem>
              </ArrayType>
            </ArrayItem>
            <ArrayItem>
              <HashType>
                <HashItem>
                  <Key>a</Key>
                  <Val>1</Val>
                </HashItem>
                <HashItem>
                  <Key>b</Key>
                  <Val>2</Val>
                </HashItem>
                <HashItem>
                  <Key>c</Key>
                  <Val>3</Val>
                </HashItem>
                <HashItem>
                  <ArrayType>
                    <ArrayItem>
                      <Val>a</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>b</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>c</Val>
                    </ArrayItem>
                    <ArrayItem>
                      <Val>x</Val>
                    </ArrayItem>
                  </ArrayType>
                  <Key>d</Key>
                </HashItem>
              </HashType>
            </ArrayItem>
          </ArrayType>
        </ParameterItem>
      </Parameters>
      <SubInstances></SubInstances>
      <UniqueModuleName>wallace_unq2</UniqueModuleName>
    </SubInstanceItem>
    <SubInstanceItem>
      <BaseModuleName>wallace</BaseModuleName>
      <CloneOf>
        <InstancePath>top.wallace_64</InstancePath>
      </CloneOf>
      <InstanceName>clone_of_wallce_64</InstanceName>
      <UniqueModuleName>wallace_unq2</UniqueModuleName>
    </SubInstanceItem>
  </SubInstances>
  <UniqueModuleName>top</UniqueModuleName>
</HierarchyTop>

Source Code Structure For Using Genesis2

The code structure for using Genesis2, just like in Genesis 1, is whatever target language your code should generate annotated with directives that tell Genesis2 how to expand the text.

In our case, the target language is Verilog or System Verilog. The meta language that is used on top is simply Perl. You now have the strength of Perl in your hands when you write verilog. Use it wisely.

Perl Escapes

There are two types of Perl escapes that can be used:

Full Line Escape ( //; Perl text 'til end of line )
This escape sequence tells Genesis2 that the entire line is Perl. To use it, simply type ' //; ' (i.e. line comment followed by a semi-colon) at the beginning of the line (white space before is also allowed).
  • Note that this would look like a comment to the xemacs's (or any other editor's) Verilog mode. Hence, coloring and indentations would not be influenced.

Descriptive example:

This is regular (though not legal Verilog) text that would go directly to output.
// This is also regular text that would go directly to the output as a Verilog comment.
//; This is text that would be evaluated as a Perl script (and generate a syntax error ;-))

Compilable example:

assign verilog_wire = some_other_verilog_wire;
// I am a verilog comment line
//; my $to_be_perl_var = "This is Perl";
Part-Of-Line Escape ( ‘ Perl text between left-single-quotes ‘ )
This escape sequence tells Genesis2 that a part of the line, which is delimited in-between two '' (i.e. grave accent) signs, is to be evaluated using the Perl interpreter. Unlike the full line escape, in the partial line escape, the result of the Perl evaluation is to be printed to screen.
  • Note that this would look like a "tick-define" to the xemcas's (or any other editor's) Verilog mode. Hence, coloring and indentations would not be influenced.

Example:

//; my $width = 5;
assign some_wire[`$width-1`:0] = some_other_wire[`$width+9`:10];

//; foreach my $idx (0,1,2,3){
assign wire_`$idx` = wire_`($idx+1)%4`;
//; }

Which will produce:

assign some_wire[4:0] = some_other_wire[14:10];

assign wire_0 = wire_1;
assign wire_1 = wire_2;
assign wire_2 = wire_3;
assign wire_3 = wire_0;
  • Note About The Perl print Function: It is some times convenient to use the built-in Perl print function. Note that for convenience, printing is done by default to the output file (i.e. the Verilog modulename.v file). If you wish to print progress or debug statements that need to go to the screen use print STDOUT "your text here\n" or print STDERR "your text here\n".

Special Built-in Methods

As mentioned before, the entire effort of creating a tool like this is to enable scopes, enhanced parametrization and most importantly uniquification of modules. For this reason, there are a handful of pre-built Perl methods that were defined.

There are no other directives you need to remember. It is all Verilog annotated with Perl from here on.

Data Structure Related Methods

sub get_parent
Returns a pointer to the parent instance
//; my $parent = $self->get_parent(); 
sub get_subinst
Returns a pointer to the object of a sub instance (by name)
//; my $subinst_of_someinst = $someinst->get_subinst($subinst_name); 
sub get_subinst_array
Returns a handle to an array of sub instance objects that match a pattern
//; my $subinsts_of_someinst = $someinst->get_subinst_array($pattern); 
sub get_instance_path
API method that returns a complete path to the given instance object. An instance path has the strict format of <top_module>.<subinst>.<subsubinst>.... For example: top.dut.regfile.addr_flop.
//; my $inst_path = $inst_obj->get_instance_path();
get_instance_obj
API method that accepts an instance path (or an instance object) and returns the corresponding instance object. An instance path has the strict format of <top_module>.<subinst>.<subsubinst>.... For example: top.dut.regfile.addr_flop.
//; my $inst_obj = $self->get_instance_obj($inst_path); 

Parametrization Methods

sub parameter
This is the main call for defining a new parameter (just like defining a parameter in SystemVerilog), and specifying its default value, documentation and range. Note that using the parameter, parameters can only be defined inside the module to which they belong (i.e., a call to $someOtherInst->parameter(...arguments...) will cause a genesis generation error). Much like SystemVerilog, parameters can also be overridden at instantiation using the generate method as shown below. Definition at instantiation time overwrites definitions done within the module (just like in Verilog). As a middle ground, parameter definitions that are not bounded by instantiation can be set using the input XML configuration file. More details can be found here.

Notes:

  • The call to parameter can be done in either method- or function-call format.
  • This API method/function is in fact syntactic sugar for the older parameter definition methods $self->define_param, $self->force_param, $self->doc_param</i>, $self->param_range.
//; my $prmVal = parameter(name=>'prmName', # required
//;                        val=>$prmVal,    # required
//;                        force=>0/1,    # Optional. Default is 0. param
//;                                       # Setting to 1 will create an immutable param, 
//;                                       # exactly like $self->force_param
//;                        doc=>'message'   # Optional
//;                        min=>$minVal, max=>$maxVal, step=>$step # Optional. Can also use min only, 
//;                                                                # max only, min and step only or
//;                                                                # max and step only.
//;                        OR 
//;                        list=>[$valA, $valB, ...]);

Or
//; my $prmVal = $self->parameter(name=>'prmName', 
//;                               val=>$prmVal,
//;                               force=>0/1,
//;                               doc=>'message' 
//;                               min=>$minVal, max=>$maxVal, step=>$step OR list=>[$valA, $valB, ...]);
sub get_param
API method for extracting a parameter's value from the parameter's registry. This sort of definition is useful if your module needs to read a parameter from a different module:
//; my $val = $other_module->get_param('prm_name');
and also if you don't want to define a value but you want to force someone else (either an instantiator module or an xml entry) to define this parameter (since if neither of them define the parameter prior to you extracting it, an error would be thrown).
//; my $val = $self->get_param('prm_name');
sub get_top_param
API method for extracting a parameter's value from the top level parameter's registry.
//; my $val = $self->get_top_param('prm_name');

This is equivalent (but much shorter) to:

//; $tmp = $self;
//; while (defined $tmp1){
//;   $tmp2=$tmp1;
//;   $tmp1=$tmp1->get_parent();
//; }
//; my $val = $tmp2->get_param('prm_name');

Module Instantiation Methods

sub generate
This is syntactic sugar for $self->unique_inst(...)---the main function call for generating (and later instantiating) a new module (described below).
//; my $newObj = generate(base_module_name, inst_name, prm1 => val1, prm2 => val2, ...);

Example: Before (SystemVerilog)

Adder#(.w(8),.n(4)) MyAdder(.in1(a),.in2(b),.out(c));

Example: After (Genesis2)

//; my $my_adder = generate('Adder', 'MyAdder', w=>8, n=>4);
`$my_adder->instantiate` (.in1(a), .in2(b), .out(c));


sub unique_inst
The main function call for generating (and later instantiating) a new module. Note that this call on its own would not print anything to the output module. Rather, it will return a pointer to the instance module ($unique_inst in the code bellow). Use the $unique_inst->instantiate() and other methods as described above to query this new module and then decide what to print to the generated module code.
//; my $newObj= $self->unique_inst(base_module_name, inst_name, prm1 => val1, prm2 => val2, ...);

Example: Before (SystemVerilog)

Adder#(.w(8),.n(4)) MyAdder(.in1(a),.in2(b),.out(c));

Example: After (Genesis2)

//; my $my_adder = $self->unique_inst('Adder', 'MyAdder', w=>8, n=>4);
`$my_adder->instantiate()` (.in1(a), .in2(b), .out(c));


sub clone
This is syntactic sugar for $self->clone_inst(...)---A method for replicating a module based on an existing instance.
//; my $clonedObj = clone($src_inst, 'new_inst_name');
sub clone_inst
An API method for replicating a module based on an existing instance (i.e., get a handle, or object, which is another instance/copy of an existing one).
//; my $clonedObj = $self->clone_inst($src_inst, 'new_inst_name');

Note that <src_inst> can either be a path (e.g., top.subinst.subsubinst) or it can be just an instance object (like the ones returned by unique_inst or clone_inst)

Auxiliary Methods

sub include
includes a (header) file inline with your text
//; include("some_header_file.vph");
sub get_instance_name
Returns the name of the current instance
//; my $someObj_inst_name = $someObj->get_instance_name();

Example: Before (SystemVerilog)

Adder#(.w(8),.n(4)) MyAdder(.in1(a),.in2(b),.out(c));

After (Genesis2)

//; my $my_adder = generate('Adder', 'MyAdder', w=>8, n=>4);
`$my_adder->get_module_name()` `$my_adder->get_instance_name()`
     (.in1(a), .in2(b), .out(c));

Also see sub instantiate, below.

sub iname
Syntactic sugar for get_instance_name()
//; my $inst_name = iname();
OR
//; my $someObj_inst_name = $someObj->iname();

Example: Before (SystemVerilog)

Adder#(.w(8),.n(4)) MyAdder(.in1(a),.in2(b),.out(c));

After (Genesis2)

//; my $my_adder = generate('Adder', 'MyAdder', w=>8, n=>4);
`$my_adder->mname()` `$my_adder->iname()` (.in1(a), .in2(b), .out(c));

Also see sub instantiate, below.

sub get_module_name
Returns the uniquified module name. This task is especially important since whenever we declare a new module we don't really know whether or not it is going to be uniquified, and how many uniquifations of this module already happened. This enables us to leave the dirty work for Genesis.
//; my $module_name = $self->get_module_name();
module `$module_name` (input logic Clk, ... );

// parameterized module code comes here 
endmodule
sub mname
Syntactic sugar for get_module_name
module `mname` (input logic Clk, ... );

// parameterized module code comes here 
endmodule
sub instantiate
Syntactic sugar for $obj->mname() obj->iname() --- I.e., the module and instance name of $obj for the purpose of instantiating that module.
module `mname`(input clk, ...);
// some parameterized module code comes here 

// Let's generate and instantiate an ALU module:
//; my $ALU = generate('ALU', 'ALU_U', param1=>val1, param2=>val2,...);
  `$ALU->instantiate` (.clk(clk), 
                       .arg1(vector1), 
                       .arg2(vector2), 
                       .cmd(operation),
                       .result(result));

// more parameterized module code comes here 
endmodule: `mname`


sub error
Prints an error message and exits with a printout of the current file and line
//; $self->error("some error message");
sub warning
Prints a warning message and a printout of the current file and line. Does NOT exit.
//; $self->warning("some message");

Useful Debug Hints

Debug level
In order to see more verbose messages from Genesis during elaboration use the flag -debug n where n is the verbosity level.
Error and warning messages
It is always a good habit to check the input (that can many times come from a user filling an xml form), and printing errors or warnings accordingly. See the section about Auxiliary Methods for the use of the error and warning predefined methods.
Debug messages to the verilog file
If you want to print debug messages during elaboration, such that they go to the output verilog file, one way is to just use simple text with inline Perl escapes, since simple text is printed to the verilog file by default. You can make these statements a verilog comment so they don't disturb compilation.
 1. This text goes as is to the verilog file... but would cause a verilog compile error since it's not legal verilog
 // 2. This text also goes to the verilog file... but no compile errors this time since for verilog it's a comment
 //; print "3. This is a Perl print command that prints this line to the verilog file... expect verilog compile errors...\n";
 //; print "// 4. This is also a Perl print command. This text also goes to the verilog file... no compile error this time\n";
Debug messages to the screen
If you want to print a debug message to the screen (printed during elaboration time), use one of the following...
 //; print STDOUT "This message goes to standard output. It does NOT go to the verilog file\n";
 //; print STDERR "This message goes to standard error output. It does NOT go to the verilog file\n";

A Word About Genesis2 Elaboration Order And Parameterization

Genesis2 Elaboration Order

Elaboration is done as a depth-first search of the hierarchy. That is, the top module would start to be elaborated, until the first unique_inst call is encountered. Then Genesis2 will recursively turn to elaborate the module which is being instantiated. This process repeats recursively, until the leaf instances are elaborated. (Behind the scenes, this strategy makes it very easy to first generate the lower levels of the hierarchy, uniquify when needed, and then tell the upper levels what is the name of the uniquified module and instantiate it.)

Parametrization is also quite simple: 1) A parameter can be defined in a module using the define_param method mentioned above. 2) Parameters can be either added or overwritten by the external XML/configuration file. 3) Finally, parameters can also be added or overwritten at instantiation time (this is similar to Verilog 2001). This means that:

  1. Defining a parameter inside the module code using define_param has the lowest priority (GENESIS2_DECLARATION_PRIORITY => 1)
  2. External input priority overrides the original module code (GENESIS2_EXTERNAL_CONFIG_PRIORITY => 2)
  3. A parameter that is assigned at instantiation is assumed to be highest priority to make sure that the instantiated module is compatible with the instantiating module (GENESIS2_INHERITANCE_PRIORITY => 3)

The rationale is that this enables the designer to give default values to parameters. It enables changing those values later from external configuration files (for example by picking them using an optimizer). But it also enables forcing of the parameter values by the instantiating module if compatibility is required (for example interface bit-widths).

  • Note that these are the only ways to set parameters values! Querying the values of parameters can be done at any point, once the instance has been created of course (using the unique_inst method.
  • Note that parameters behave as constants! When you assign/get a parameter value, the value is being copied (deep copy if the parameter is a reference to a data structure).
  • Note that you can use constants to communicate values to parent modules (not just to sub-instances)! Once a parameter is defined, it can be read from anywhere in the hierarchy using the unique module object (e.g., //; my $param_from_someone_else = $someone_else_instance->get_param('param_name');).

Parameter Types

A parameter in Genesis2 can be either a string/scalar, an array, a hash, a pointer/handle of an object. Any combination nested to what ever level (silly example: hash of arrays of arrays of pointers) is also supported.

Important notes:

  • For hexadecimal numbers, use the notation 0x<0..9a..f> (e.g., 0xfff, 0xdeadbeef)
  • For binary, use the notation 0b<0..1> (e.g., 0b1100, 0b0011001)
  • No need to worry about pointers as parameters are always copied (using deep copy)
  • Please don't use weird parameters like "assign my_signal = your_signal". Try to make the leaf elements of any parameter simple strings or scalars.
  • For security reasons, parameters can only be composed out of alphanumeric characters, plus a few other characters like arithmetic +-/*, spaces, etc. No ; (semicolon) and no (parenthesis) and no {curly-braces}.

Invoking The Genesis2 Tool

Genesis2 is located in $SMASH/bin/PerlLibs/Genesis2/Genesis2.pl. For help on using the script type Genesis2.pl -help.

Note that though there are two distinct stages in Genesis2: parsing and generation. One can call the script once with both the -parse and the -generate flags on. Genesis2 would perform parsing and then move immediately to generating.

Parsing Mode

Parsing mode performs the first transformation, from Verilog annotated with Perl code (.vp files) to an object oriented set of Perl packages. Each Perl module (.pm file) is a code generator for its corresponding verilog module (.v file), but verilog generation is not yet done at this stage.

Usage:
        ./Genesis2.pl [-option value, ...]

Parsing Options:
        [-parse]                        # Parse input file and generate perl modules
        [-sources|srcpath dir]          # Where to find source files
        [-includes|incpath dir]         # Where to find included files
        [-input file1 .. filen]         # List of top level files
                                        # The default is STDIN, but some functions
                                        # (such as "for" or "while")
                                        # may not work properly.
        [-depend filename]              # Generate a dependency file list (list of input files)
        [-perl_modules modulename]      # Additional perl modules to load

Generation Mode

Generation mode is the stage where Genesis2 is asked to start doing the actual elaboration starting from some specified top level (does not need to be the absolute top level of your design). This is when the .pm files generate the .v files.

Usage:
        ./Genesis2.pl [-option value, ...]

Generating Options:
        [-generate]                     # Generate a verilog hierarchy
        [-top topmodule]                # Name of top module to start generation from
        [-product filename]             # Generate a product file list (list of output files)
        [-hierarchy filename]           # Generate a hierarchy representation tree
        [-xml filename]                 # Input XML representation of definitions
        [-perl_modules modulename]      # Additional perl modules to load

Help and Debugging

Usage:
        ./Genesis2.pl [-option value, ...]

Help and Debuging Options:
        [-debug level]                 # Set debug level
        [-help]                        # prints the script's usage message
        [-man [extension_name]]        # prints the complete man page for Genesis2 or the
                                       # specified extension (e.g. -man Math)
  • I have not written the man content yet. So it is likely to print zip.

Sample Graphical User Interface and Demo

Click here for interactive chip generator GUI and demo based on Genesis2.

Extending Genesis2 With Homemade Perl Libraries

One of the best things about using Perl as the language on top of Verilog, is that it is very easily extended. This means that one can use any Perl library in the world as part of the knowledge base that create a module's micro-architecture.

Adding A Perl Built-in Library

Simply put a "\\; use LibraryName;" in your text, just as you would do for any Perl script. Example of using the POSIX library (used for the mathematical ceiling function):

//; # More Perl Libraries
//; use POSIX;
//; my $reg_list = $self->define_param(REG_LIST => [	{name => 'regA', width => 5, default => 17, IEO => 'ie'}, 
//;							{name => 'regB', width => 10, default => 27, IEO => 'o'}, 
//;							{name => 'regC', width => 15, IEO => 'ieo'},
//;							{name => 'regD', width => 31, IEO => 'ieo'},
//;							{name => 'regE', width => 32, IEO => 'ieo'},
//;						    ]);
//; my $num_regs = scalar(@{$reg_list});
//; my $num_addr_bits = POSIX::ceil(log($num_regs)/log(2));

// Verilog code for the module
module `$self->get_module_name()` (
    input                               Clk,
    input                               Reset,
    input [`$num_addr_bits-1`:0]        Addr,
    ...
    );

endmodule // `$self->get_module_name()`

Adding Your Own Perl Library

Assuming your homemade Perl package is called MyLib.pm, place it in the folder Path/To/MyGenesisProjectLibs. Then add the environment variable GENESIS_PROJECT_LIBS to your environment setup file by adding this line:

setenv GENESIS_PROJECT_LIBS Path/To/MyGenesisProjectLibs

There are two ways for your Genesis2 modules to get the functions of a home-made library into their name space:

  1. Typical Perl "use" system: (preferred way for not polluting the name space)
    In your module (e.g., your file flop.vp) add a line that reads "use MyLib". Now you can call MyLib::funcName(args). If you want some (or all) of the functions to be embedded in the name space, you can also add their names to the EXPORT or EXPORT_OK lists. (As an example, the file $GENESIS_LIBS/Genesis2/Auxiliary/TypeConv.pm has these lists marked with "METHOD 1 FOR INHERITING ALL METHODS"
  2. Inheritance:
    You can tell all Genesis2 modules to inherit methods from this module. In order to do that, we force the UniqueModule (which is the base class of all Genesis2 modules) to inherit from this module. Then, given a method with name methodName, each and every module in Genesis would be able to call it by invoking $self->methodName. To activate this inheritance follow these two steps:
    1. Push the current package into the ISA inheritance array of the base module UniqueModule. (As an example, see in the file $GENESIS_LIBS/Genesis2/Auxiliary/TypeConv.pm, the Perl lines that are annotated as "METHOD 2 FOR INHERITING ALL METHODS").
    2. Either add "use MyLib;" to your Genesis2.pl script at the appropriate location, which would force this library to always be used. Or, use the Genesis2 flag "-perl_modules MyLib" on your command line.

Behind The Genesis2 Curtain

The Genesis2::Manager and Genesis2::UniqueModule Objects

One day I'll find the time to write this. Not today though :-))

Shacham 14:33, 11 March 2011 (PST)