Genesis2

From Genesis2

Jump to: navigation, search

Contents

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 an extension to SystemVerilog for designing digital and mixed-signal chip generators. 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. Moreover, Genesis2 maintains the same object-oriented, hierarchical system and instance scopes of the design hierarchy.

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

Installing Genesis2

The following are instructions for installing genesis2 on your machine. If you're at Stanford however, skip this section and read this instead because Genesis2 is already installed on /cad and the environment is sourced though the modules system. If you are not at Stanford, send me an email to get the tar ball and then:

  1. Save the file. Say the tarball is called r#####.tar.bz2 and you put it in a folder called $GENESIS/
  2. Unzip the file:
     cd $GENESIS
     tar -xjf r#####.tar.bz2 -C ./
    
  3. Now you should see a folder named r#####/Genesis2Tools that contains three sub-folders: bin, demo, gui, Info, PythonLibs and PerlLibs. The demo contains a few small design examples for you to play with/get started, including makefiles.
  4. Add Genesis2 (and GUI) to your execution path, and some key libraries that it uses: simply type (or add to the end of your .cshrc file)
      % setenv GENESIS_HOME "$GENESIS/r#####/Genesis2Tools"
      % set path=($GENESIS_HOME/bin $GENESIS_HOME/gui/bin $path)
      % setenv PERL5LIB "$PERL5LIB":$GENESIS_HOME/PerlLibs/ExtrasForOldPerlDistributions
    
  5. To build a private standalone GUI (easy!) follow this link and/or simply do the following:
      % $GENESIS_HOME/gui/bin/stewie start ~/mystewie
    
    • If your local perl distribution lacks HTTP libraries, stewie might complain. To fix this, you can either install HTTP via CPAN (for Perl wizards only!) or you can use the CPAN included with the GUI distribution, as shown below. Note: code has been added recently such that you should never have to do this, so feel free to complain if it happens :)
      % setenv PERL5LIB "$PERL5LIB":$GENESIS_HOME/gui/configs/install/perlfiles
    
  6. To build a public GUI that runs on your company's server (harder), follow this link and/or you can try simply running the install script:
      % $GENESIS_HOME/gui/configs/install/INSTALL.sh
    
  7. To use the Python Genesis2.XMLCrawler library:
     setenv PYTHONPATH "$GENESIS_HOME/PythonLibs:$PYTHONPATH"

Working On Stanford Machines

Genesis2 is available at Stanford 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/tcl/init/<yourFavoriteShell>  
    
  2. Load the Genesis2 module
    module load genesis2

That's it. You are good to go.

Meanwhile, you can access Genesis2 via the public Stanford GUI here and/or start your own Stewie standalone GUI.

Getting Started With Genesis2

Setting Your Environment

Setting Genesis2 Mode for Emacs/Xemacs

If you use emacs or xemacs and would like to use genesis2-mode, download File:Mmm.tar.bz2 and then...

  1. Unpack the mmm files and directory:
    tar xjf Mmm.tar.bz2
  2. Install the new code in your .emacs and/or .xemacs/init.el file(s):
    ./mmm-install.csh

Note that mmm depends on the pre-existence and availability of verilog-mode and perl-mode (not cperl-mode) in your emacs. Most versions of emacs already have these built-in. Otherwise, e.g. google "verilog-mode" and download from one of the places that offer it.

If you don't like genesis2 mode, you can just as easily make .vp files open in verilog mode, in which case perl lines will simply appear as comments.

Example

  % mkdir ~/mmm
  % mv Mmm.tar.bz2 ~/mmm
  % cd ~/mmm
  % tar xjf Mmm.tar.bz2
  % ./mmm-install.csh

In case of failure

Check your emacs init file(s) ~/.emacs and/or ~/.xemacs/init.el file to see if the following code got added correctly at the end. Particularly check to see that the correct directory was added in place of /home/mydir/mmm and that e.g. /home/mydir/mmm/mmm-genesis2-mode-init.el exists is readable.

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; BEGIN genesis2-mode setup

  ;; mmm-dir tells emacs where to find the mmm directory and startup file
  (setq mmm-dir "/home/mydir/mmm")

  ;; Add mmm-dir and "mmm-dir/mmm-mode-0.4.8" to the load path
  (setq mmm-dir (expand-file-name mmm-dir)) ;; Turns e.g. "~/mmm" into "/home/myname/mmm"
  (setq load-path (cons  mmm-dir                           load-path))
  (setq load-path (cons (concat mmm-dir "/mmm-mode-0.4.8") load-path))

  ;; Load it up
  (load-library "mmm-genesis2-mode-init.el")

  ;; (Optional): Leaving submode-decoration at the default "1" value gives Perl a
  ;; lovely aquamarine bg maybe better suited to black-text-on-white-page displays
  ;; I set it to zero because I use white-text-on-black-page.
  (setq mmm-submode-decoration-level 1)
  (setq mmm-submode-decoration-level 0)

  ;; If you have trouble with quotes and indents in Perl regions,
  ;; try turning the following features on or off:
  ;; (fixquote-off-srmmm) ;; (Default is ON).
  ;; (fixindent-on-srmmm) ;; (Default is OFF).

  ;; END genesis2-mode setup
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

For emacs 24 and above

When using emacs 24 or above, genesis2 mode fails. The problem seems to be with a function called make-local-hook:

"make-local-hook has been obsolete for years, and was removed entirely in emacs 24" (more details here).

NEW (better) FIX:

The new fix disables the deprecated/superfluous and now obsolete function "make-local-hook" for emacs versions 24 and above.

  1. Find the file $CHIPGEN/elisp/mmm-genesis2-mode-init.el
  2. Append the following code at the end of the file:
;; emacs v24 apparently borke some stuff, but this seems to fix it.
;; specifically, mmm-region.el uses deprecated, superfluous (and now
;; obsolete) function "make-local-hook"
;; (note emacs-major-version only exists for v19 and above!)
(if (boundp 'emacs-major-version)
    (if (> emacs-major-version 23)
        (defun make-local-hook (dummy_arg)
          (message "make-local-hook disabled for emacs version 24 and above")
          )
      )
)

Close and restart emacs. Good luck!

OLD (simpler) FIX:

  1. Find the file $CHIPGEN/elisp/mmm-mode-0.4.8/mmm-region.ml
  2. comment out the following line, using a couple of semicolons at the beginning:
 
BEFORE: (make-local-hook 'post-command-hook)
AFTER:  ;;  (make-local-hook 'post-command-hook)

So that when you diff the old and new files it should look like this:

% diff mmm-region.el mmm-region.el.old  
589c589                                     
< ;;  (make-local-hook 'post-command-hook)  
---                                         
>   (make-local-hook 'post-command-hook)    

Close and restart emacs. Good luck!

Setting Genesis2 Mode for Vim

"Vim users unite..." Thanks to James Mao and Glen Gibb, there is now a Genesis2 syntax highlighting mode for Vim. Actually two... To install it:

  1. Download File:Vim-genesis2.tar.bz2
  2. Extract the files
     tar -xjf vim-genesis2.tar.bz2 -C ./ 
  3. Call "make install"

That's it.


For more advanced users, a slightly modified version from Glen (vim-genesis2.tar.gz). It requires three things:

  1. The Verilog/SystemVerilog syntax highlighting file in verilog_systemverilog.tar.gz
    1. Download File:Verilog systemverilog.tar.bz2
    2. Extract the files
       tar -xjf verilog_systemverilog.tar.bz2 -C ./ 
  2. A recent version of the vim-perl syntax highlighting available from: https://github.com/vim-perl/vim-perl
  3. The new genesis2 mode
    1. Download File:Vim-genesis2-v2.tar.bz2
    2. Extract the files
       tar -xjf vim-genesis2-v2.tar.bz2 -C ./ 

This version changes the highlighting of //; and `, and with the latest vim-perl file it improves the highlighting of Perl code slightly.

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. In all cases reported to us, we added the missing libraries as part of the distribution so theoretically, you should not need to do anything. So far, libraries that I have seen missing include XML::Simple and PAR and their dependencies.

All the libraries used in Genesis2 are libraries that are freely available from CPAN. To install these libraries simply follow the steps below.

Ubuntu (requires root/sudo permission):

apt-get install libxml-simple-perl

Or

apt-get install libpar-perl

Generic Method:

  1. Login as root
    • If you cannot login as root you may also install these modules locally, but you first need a your cpan distribution to be 1.9463.
    • Alternatively you can also follow the instructions here: "Installing Perl modules without root access". This webpage teaches how to create a local::lib, which sets everything up so you can install distributions from CPAN into your home directory. This means you won't need root access, and ensures that anything you install will not interfere with the either the system Perl or any other users.
  2. Open a CPAN shell:
     perl -MCPAN -e shell
  3. Install a package:
    1. Example 1: Install the library XML::SAX (required by XML::Simple). Make sure to answer yes for installing all library dependencies!
       cpan> install XML::SAX 
      Install the library XML::Simple
       cpan> install XML::Simple 
    2. Example 2: Or Install the library PAR::Packer
       cpan> install PAR::Packer 

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 (or base_module_name.svp if you like the SystemVerilog suffix notation better). 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.

New Feature -- Special File Extensions For SystemVerilog C and TCL :

  • Use file.svp and file.svph for SystemVerilog files and headers
  • Use file.cp or file.cph for C files and headers (for High Level Synthesis)
  • Use file.tclp or file.tclph for TCL files and headers

'genesis_work' Directory And SomeModule.pm Files

Genesis2 generates intermediate Perl module files (Given the file filename1.vp, Genesis2 would generate filename1.pm). These files are generated into a newly created folder named 'genesis_work'. Typically there is no reason to look at these files, except for extreme cases for debugging of parsing errors that had abscured error messages.

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.

genesis_verif/SomeModule.v and genesis_synth/AnotherModule.v Files (or .sv for .svp source 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 a "small_" output xml representation which can serve as a template for creating the input XML program. It will also generate a complete output xml representation which is a superset of the input xml representation, with much more information, and can also serve as a program template (when used as input, Genesis ignores the extra meta-information). The "small_" version is more useful for human manipulation, but when GUI or optimization tools are added to the flow, the latter version is usually preferred. See Genesis2SchemaXSD for a complete XML schema!

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

  • There are a few reserved element names: HierarchyTop, BaseModuleName, SynonymFor, InstanceName, Parameters, ImmutableParameters, ParameterItem, Name, Val, Doc, Range, List, Min, Max, Step, Opt, 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>

Config File Via Perl Script

XML config files are the official and formal representation of the design. However, it is sometimes useful to have an easy method of overriding a parameter value here and there. For these purpose, it is often convenient to be able to write a short script that manipulates those values. Genesis2 accept those scripts using the -cfg command line flag as described here. Many configuration scripts may be applied one after the other to cover different aspects of the configuration. If a parameter value binding is overridden, a warning is issued. Note that parameters values that are configured through the configuration file will NOT override definitions by the XML file (actually XML definitions override the Perl configuration scripts). Also note that parameter values that are configured through the config file will NOT override parameters that were already bound using the generate statement in the .vp files, since that assignment has higher priority. For a complete explanation of parameters override priorities see here.

Basic Config Files

Basic configuration files are any simple Perl script which uses the following predefined functions:

  • configure($path_to_param, $override_value) is the main function to enable overriding parameters. Example:
    my $path = 'top.dut.inst';
    my $path_to_prm = $path.'Width';
    configure($path_to_prm, 32);
    my $path_to_prm = $path.'Size';
    configure($path_to_prm, 4);
    my $path_to_prm = $path.'RAM';
    configure($path_to_prm, [0x1, 0x2, 0x3, 0x4]);
    
  • include($another_filename) is a productivity construct to enable you to break the config file into smaller portions. Include inlines the other file into the current file. Example:
    In Cache.cfg:
    -------------
    die unless defined $path;
    foreach $cache ('cache1', 'cache2', 'cache3', 'cache4'){
      configure($path . '.' . $cache . '.' . 'Width', 32);
    }
    
    In Main.cfg:
    ------------
    my $path = 'top.dut.tile';
    include('Cache.cfg');
    
  • exists_configuration('path.to.param') quarries weather 'param' exists in path 'path.to.param'. It returns 1 if exists and 0 otherwise. Exists here means that that parameter configuration was previously defined through the configuration scripts. Since configuration scripts are executed long before the design is elaborated, it does check the existence of the parameter in the actual design. See get_configuration (next) for an example.
  • get_configuration('path.to.param') returns the value of a previously configured parameter. Note that 'previously configured' means it was previously configured via the configuration script. If the parameter was not previously configured, an error will be thrown (because parameters can be defined to have an 'undef' value, the only way to check if a parameter was previously configured is through the exists_configuration function as described above).
    if( exists_configuration('top.bus.SlaveList') ){
       my $sl = get_configuration('top.bus.SlaveList');
       --- Some code that manipulates the $sl list ---
       configure('top.bus.SlaveList', $sl); # <- override previous configuration with new configuration
    }else{
       --- Some code that defines a new list ---
       configure('top.bus.SlaveList', $sl);
    }
    
  • remove_configuration('path.to.param') removes an existing parameter from the configuration database.
  • get_top_name() returns the name of the top module, as set using the command line "-top TopModuleName" flag.
    my $top = get_top_name();
    configure("$top.ParamName", 17);
    
  • get_synthtop_path returns the path from the top module to the synthesis top.
    my $synthpath = get_synthtop_path();
    configure("$synthpath.ParamName", 19);
    
  • print_configuration outputs a (very :) pretty printout of all existing configurations to the screen (to stderr). Try it, it's beautiful...
  • error("error message") print the error message as well as the line number and file, then exits with error code 7

Config Libraries

It is sometimes desireable to create project-specific API. For example, create a few high level functions that can configure many internal parameters. Doing that with Genesis2 is super simple: Simply create your favorite package that holds the project specific configuration functions (e.g. CMP_Builder.pm), and from your configuration script use Perl's 'use' mechanism to call it. To allow CMP_Builder access to the same configuration methods as described above in Genesis2#Basic_Config_Files, CMP_Builder must use the predefined Genesis2 base package 'Genesis2::UserConfigBase'. Example:

CMP_Builder.pm:
----------------
use Exporter;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
@ISA = qw(Exporter);
@EXPORT = qw(create_cache add_core);
@EXPORT_OK = qw();
$VERSION = '1.0';

use Genesis2::UserConfigBase;

sub add_core {
  my $coreList = [];
  if (exists_configuration('top.cmp.CoreList'){
    $coreList = get_configuration('top.cmp.CoreList');
  }
  push (@$coreList, {coreType=>RISC, coreArch=>64});
  configure('top.cmp.CoreList', $coreList);
}

sub create_cache{
  ...
}


4core.cfg:
-----------
use CMP_Builder;
add_core();
add_core();
add_core();
add_core();
create_cache();
...

Additional Output File Types

Genesis2 produces some additional outputs, on top of the Verilog files: A log file (using the -log name.log flag), 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).

Log File

By default, Genesis2 produces a log file called genesis.log. The name can be modified using the -log filename switch. On top of capturing all messages from Genesis2, the log file includes both Genesis2's release information and the complete command used for that run.

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 or .sv) 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 by downstream tools.

Genesis2 produces three lists: one for all files generated (for validation/simulation); one for synthesis subset; and one with testbench only (for gate level simulation). The synthesis subset is determined by the -synthtop flag as described here. The name of the 'product' list of generated files is set by the -product command line flag and defaults to genesis_vlog.vf. The name of the 'for-synthesis' product list is set by taking the name of the 'product' list, and adding .synth. between the file name and its suffix. The name of the 'verif-only' product list is set by taking the name of the 'complete' list, and adding .verif. between the file name and its suffix. For example, for the default 'product' file name genesis_vlog.vf, the 'for-synthesis' file name would be genesis_vlog.synth.vf and the 'verif-only' file is genesis_vlog.verif.vf'.

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.

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, SynonymFor, InstanceName, ImmutableParameters, Parameters, SubInstances, UniqueModuleName
    • BaseModuleName: The name of the template module before uniquification
    • SynonymFor: If the base module (or template) is just a synonym for some other base module (created by using the synonym function), the field SynonymFor appears in addition to the BaseModuleName. The SynonymFor value is the base module name for which this module is synonym. If module ModuleC is synonym to ModuleB which is in turn synonym to ModuleA, than the value of SynonymFor is the basis of the chain---ModuleA.
    • 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 parameter(Name=>'prm', Val=>..., Force=>1) call or at instantiation using the generate(TemplateName, InstanceName, prm=>val) 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.
      • Opt: This field may only show up if a Range<i> field was used. It is optional however. Allowed values are {Yes, No, Try} when it shows in the <i>Parameters list. Allowed values are {No, NotRightNow} when it shows in the ImmutableParameters list.
    • 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).
"small_" Hierarchy Out

Tools need the complete XML (hierarchy_out.xml), but for humans it is quite annoying... right? So Genesis produces both the hierarchy_out.xml (for tools) and small_hierarchy_out.xml (for more human tools). The "small_" version, still contains the entire hierarchy, but only prints tweakable parameters (i.e. skips ImmutableParameters) and also skips other meta data that most humans don't care about (thus probably half the size or less).

The result is a minimalistic XML file that conforms with the input xml structure. Refer to the input xml program section for the basic structure of the XML tree.

"tiny_" Hierarchy Out

The "tiny_" version of the XML (e.g., tiny_hierarchy_out.xml) is an even more minimalistic structure than the "small_" file. It contains only information about parameters and nothing else, but it contains only information about parameters whose value, during the last round of generation, was set from the input xml. That is, it contains only parameters that are not at their default value. In most cases, this is equivalent to the input XML file, unless the input actually contained unused parameters (eg for modules that no longer exist in this round of generation).

The result is a minimalistic XML file that conforms with the input xml structure. Refer to the input xml program section for the basic structure of the XML tree.

Example of Full Hierarchy Out

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>

genesis_clean.cmd

This file contains commands to clean all files generated by Genesis2. To use it simply source it:

>> source genesis_clean.cmd

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

Old Verilog Style Macros Escapes

Using old style tick macros from Verilog/System Verilog is highly un-recommended for many reasons. Instead one should either use variables or genesis2 parameters. If you still must use them, I guess you can but don't say I didn't warn you! Simply escape your tick as follows:

`this is a perl escape`
\`but this is a verilog old style tick

Special Built-in Methods

As mentioned before, the entire effort of creating a tool like this is to enable scopes, enhanced parameterization 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_top
Returns a pointer to the top level of the hierarchy
//; my $top_module = $self->get_top(); 
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 exists_subinst
Returns a 1 if a sub instance (by name) exists. Zero otherwise.
//; my $subinst_exists = $someinst->exists_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 search_subinst
API method for searching the entire design hierarchy or portions of it according to user defined criteria(s)
All criteria are optional. The returned value is a list of objects that matched ALL specified criteria.
From
Either pointer or text path to an instance work here (default is the design top)
Depth
How deep in the hierarchy should we search? (default is 10000 ;-)
PathRegex
Return only instances who's path matches some regular expression (e.g., '.*\.ahb0\..*')
INameRegex
Return only instances who's instance name matches a regular expression
MNameRegex
Return only instances who's finalized module name matches a regular expression
BNameRegex
Return only instances who's base module name (before uniquification) matches a regular expression
SNameRegex
Return only instances who's source file name matches a regular expression
HasParamRegex
Return only instances that has a parameter who's name matches the regular expression The HasParamRegex arg can be either a string (e.g., 'Width') or an a string array ref (e.g., ['Width', 'Radix']). Note that in the string array case, we search for instances that has a param that matchs regex1 AND a param that matches regex2 AND...
ApplyMap
If you have some complex way of determining if an instance should be returned, you can create your own function that accept/reject an objects. Your function must return 0/1. E.g., sub func{ my $obj = shift; return ($obj-iname eq 'ofer'); }
Reverse
Search hierarchy in DFS or in Reverse DFS order
 
@subinst_arr = $anyObj->search_subinst(
                        From=>$ObjToStartFrom   OR  'path.to.objToStartFrom', 
                        Depth=>$HowDeepToSearch,
                        PathRegex=>'Path.to.Inst',  
                        INameRegex=>'InstanceName',
                        MNameRegex=>'ModuleName',
                        BNameRegex=>'BaseModuleName', 
                        SNameRegex=>'SourceTemplateName',
                        HasParamRegex=>'ParamName' OR \@ParamList,
                        ApplyMap=>\&func,
			Reverse=>0/1);
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); 
synonym
API function/method call that helps you make fancy names for your module templates.
NOTE: This function manipulates the names of templates, and therefore the names of the generated modules and the generated verilog files). Not the names of instances of those modules.
//; synonym("sourceTemplateName", "renamedTemplateName"); 
For example, say you have addr.vp that has a bunch of parameters. And say you want to create multiple versions of it that you can easily grep for (e.g., in your physical design scripts). So you don't want those elaborated modules to be called adder_unq1, addr_unq2, and so on. Instead you want fancy_adder and simple_adder. For the case stated above this would be:
//; synonym("adder", "simple_adder");
//; synonym("adder", "fancy_adder");
OR as method call:
//; $self->synonym("adder", "simple_adder");
//; $self->synonym("adder", "fancy_adder");
A synonym of a synonym is also ok:
//; synonym("fancy_adder", "super_fancy_adder");
Therefore the following code will result in the generation the verilog modules adder_unq1, adder_unq2 but also simple_adder_unq1, super_fancy_adder_unq1 and super_fancy_adder_unq2, even though simple_adder_unq1 is functionally equivalent to adder_unq1 and super_fancy_adder_unq1 is functionally equivalent to adder_unq2:
//; my $obj1 = generate('adder', 'adder_u1', WIDTH=>4);
//; my $obj2 = generate('adder', 'adder_u2', WIDTH=>8);
//; my $obj3 = generate('simple_adder', 'adder_u3', WIDTH=>4);
//; my $obj4 = generate('super_fancy_adder', 'adder_u4', WIDTH=>8);
//; my $obj5 = generate('super_fancy_adder', 'adder_u5', WIDTH=>12);
Note that you could also create adder, simple_adder and so on (i.e., without the "_unq1" suffix) by using the generate_base call (see below), as long as you only generate those once in your design. Otherwise Genesis will through an error message and stop.
//; my $obj1 = generate_base('adder', 'adder_u1', WIDTH=>4);
//; my $obj2 = generate_base('simple_adder', 'adder_u2', WIDTH=>4);
//; my $obj3 = generate_base('super_fancy_adder', 'adder_u3', WIDTH=>4);
//; my $obj4 = generate_base('super_fancy_adder', 'adder_u4', WIDTH=>8); <-- This will create an ERROR message because generate_base does not create unique modules.

Parameterization 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.
  • List of older style parameter definition methods here.
//; 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, ...],
//;			   Opt=>'Yes'/'No'/'Try');                 # Optional -- Will pass info to external optimizer

Or
//; my $prmVal = $self->parameter(name=>'prmName', 
//;                               val=>$prmVal,
//;                               force=>0/1,
//;                               doc=>'message' 
//;                               min=>$minVal, max=>$maxVal, step=>$step OR list=>[$valA, $valB, ...],
//;			          Opt=>'Yes'/'No'/'Try');
Style tip: Often, we would like to declare a parameter that MUST be overridden at instantiation or from external configuration. One way to do that is to provide a default value which is out of range. If the parameter value is not overridden, Genesis will issue an error. For example:
//; my $width = parameter(Name=>'BitWidth', Val=>-1, Min=>0, Doc=>'...');
//; my $enc = parameter(Name=>'Encrypt ', Val=>'', List=>['Yes', 'No', 'Maybe'], Doc=>'...');
For compound structures and/or pointers, were simple range limitations could not apply, the following is useful:
//; my $cpu_ref = parameter(Name=>'CPU_ObjRef', Val=>undef, Doc=>'...') or error ("Parameter CPU_ObjRef must be specified");


sub exists_param
API method for checking whether a certain parameter has been defined in a module (without defining it). Can operate on $self or any template $obj that was previously generated. Note that specifying a parameter within a generate call, from the XML, or configuration file, is not the same as defining it, and exists_param will evaluate to false in that case.
//; my $exists = $self->exists_param('SomePrmName');


sub list_params
API method for extracting a list of params defined in a module. Can operate on $self or any template $obj that was previously generated.
//; my @list = $self->list_params();
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');

It should be defined with 'parameter' call (not just in the XML) or you will get an error.

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
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 ($newObj in the code bellow). Use the $newObj->instantiate() and other methods as described above to query this new module and then decide what to print to the generated module code.
Note: This function is syntactic sugar for $self->unique_inst(...)---the main method call for generating (and later instantiating) a new module.
//; 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 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 generate_base
It turns out that some people want to generate only the base module. For example, Mrs. F. in her mixed signal chip wanted to generate only one type of her analog.vp module as that module needs to be replaced with an analog macro at PNR. Furthermore, she prefers if it remains with the name analog and not be renamed to analog_unq1 as genesis generally does at elaboration. To facilitate that, we created the new generate_base function. generate_base will generate the base module and not anything else.
Notes:
  • If you generate multiple instances of a module using generate_base, genesis is still smart enough to make sure that you are always generating exactly the same module, and otherwise through an error that you can't generate the same un-uniquified module twice in two different ways.
  • You CAN use both the unique instantiation (i.e., generate) and the non-unique instantiation (i.e., generate_base) in the same code. No contradictions here.
//; my $MyAnalog_obj = generate_base('Analog', 'MyAnalog', w=>8, n=>4);
`$MyAnalog_obj ->instantiate` (.in1(a), .in2(b), .out(c));

Auxiliary Methods

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

Example for using iname to instantiate a module. In SystemVerilog we might do something like:

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

In Genesis2 we can do something like this:

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

But it is actually better to use instantiate. See sub instantiate, below.

sub mname
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. Note that this is syntactic sugar for the older style method 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 bname
Returns the base module name from which an object was generated. This is the name of the template, before uniquification. Note that this is syntactic sugar for the older style method get_base_name
//; my $BaseName = bname();
//; my $SomeObj_BaseName = $SomeObj->bname();
sub sname
Returns the source file name from which an object was generated. This is the name of the template, before uniquification and before synonyms were applied. Note that this is syntactic sugar for the older style method get_source_name
//; my $SourceName = sname();
//; my $SomeObj_SourceName = $SomeObj->sname();
sub to_string
Returns a nicely formatted string that represents a Perl object.
//; my $variable = {key1=>'val1', key2=>[1..13], key3=>'val3'};
//; my $str = $self->to_string($variable);
sub error
Prints an error message and exits with a printout of the current file and line number. Can be used as either function or method.
//; $self->error("some error message");
//; error("some error message");
sub warning
Prints a warning message and a printout of the current file and line. Does NOT exit. Can be used as either function or method.
//; $self->warning("some message");
//; 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.
Printing objects
The built-in method to_string returns a nicely formatted string that represents a Perl object.
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

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 generate 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.)

Parameter Value Binding Priority

Parameters in Genesis2 are very similar to parameters in SystemVerilog but very much enhanced. For example, as shown next, a Genesis2 parameter type can be scalar, string, array, hash or pointer to some instance, and any combination of those. It is important however to understand the way parameters are bound to a value. In SystemVerilog for example, some of the binding mechanism is bad (defparam which will be deprecated according to the IEEE Standard).

Genesis2, as an extension of SystemVerilog for creating Generators, puts a lot of emphasis on late binding of parameters, even those that are buried deep in the design hierarchy. The following are the various ways to bind / override parameter values. Note the distinct (and unambiguous) order.

  1. A parameter value is assigned by default to the value given in the parameter definition in the module (.vp file) using the parameter method mentioned above.
  2. Parameters that were declared with one value (val1), can be overwritten by the external Perl configuration input file with a different value (val2), as described here
  3. Parameters that where declared with val1, which may or may not been overridden with val2 from the Perl config file, can be further overridden with val3 from an XML configuration file as described here
  4. Parameters that where declared with val1, which may or may not been overridden with val2 from the Perl configuration file, and may or may not been further overridden with val3 from an XML configuration file can be even further overridden from the command line with the command line directive -parameter top.dut.param=val4 as described here
  5. Finally, parameters can also be added or overwritten at instantiation time (this is similar to Verilog 2001)

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

The strongest parameter binding is when the declaration of the parameter in its module as described in (1), also annotates it with Force=>1. That makes it an immutable parameter for any of the methods enumerated above.

  • 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 generate 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 parameters 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 instance 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

If you followed the installation instructions, Genesis2 should be at $GENESIS_HOME/PerlLibs/Genesis2/Genesis2.pl. At Stanford, that expends to /cad/genesis2/rxxxxx/PerlLibs/Genesis2/Genesis2.pl. For help on invoking the tool 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 files to process
        [-inputlist filelist1 .. filelistn]     # List of files that each contain a list of files to
                                                # process (use # to comment lines out in this format)
        [-depend filename]              # Generate a dependency file list (list of input files)

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
	[-synthtop top.module.des_top]	# Name of top module for synthesis
        [-product filename]             # Generate a product file list (list of output files)
        [-hierarchy filename]           # Generate a hierarchy representation tree
        [-cfgpath|configs dir]		# Where to find config files (xml/scripts)
        [-xml filename]                 # Input XML representation of definitions (overrides cfg script definitions)
        [-cfg filename1 .. filenameN]   # Config file to specify parameter values as a Perl script 
        [-parameter path.to.prm1=value1 path.to.another.prm2=value2]
                                        # List of parameter override definitions from command line (overrides xml and cfg definitions)

Help and Debugging

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

Help and Debuging Options:
	[-log filename]	               # Name of log file for genesis2 and user stderr messages
        [-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.

Auxiliary

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

Auxiliary Options:
        [-perl_libs path]               # Additional perl libraries locations (folders). 'path' can 
                                        # be absolute or relative.
        [-perl_modules path/name]       # Additional perl modules to load. 'path' can be absolute 
                                        # or relative. Perl module 'name' is expected to be located 
                                        # in 'name.pm', and contain a package named 'name'.
	[-license file]			# Pointer to license file (default is "Genesis2.lic")

Graphical User Interface and Demo

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 (ceil);
//; 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 = ceil(log($num_regs)/log(2));

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

endmodule // `mname()`

Adding Your Own Perl Libraries

Adding Libraries To The Path

With time, you may want to add more Perl libraries (i.e., .pm files) to extend genesis with functions you use often. Say (for example) you place those under /Path/To/MyGenesisLocalLibs/*.pm. To tell Genesis2 (and all your modules) where to search for those packages, do one of the following:

  1. Just add the following line to your environment so that Genesis knows where to look for them:
     setenv GENESIS_PROJECT_LIBS $GENESIS_HOME/MyGenesisLocalLibs 
  2. Dynamically notify Genesis2 by adding the command line flag -perl_libs /Path/To/MyGenesisLocalLibs as described here.

Adding Library Components to The Namespace

Once the library folder is in the path, there are two ways for your Genesis2 modules to get the functions of a home-made library into their name space. For example, if your library is MyLib.pm:

  1. (Recommended Method -- Selective Inheritance of Selective Functions and Methods Via 'Use') Typical Perl "use" system: (preferred way for not polluting the name space) In your module that requires the additional package MyLib (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 may be embedded in the current namespace (so you can call funcName($args) without the MyLib:: prefix or even call inherited methods as $self->methodName($args)). To enable that, you need to use Exporter and add these function/method names to the EXPORT or EXPORT_OK lists in your MyLib.pm file using the syntax:

    package MyLib;
    use warnings;
    use strict;
    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
    use Exporter;
    @ISA = qw(Exporter);
    $VERSION = '1.00';
    @EXPORT = qw(funcName methodName anotherMethodName);                        <---
    @EXPORT_OK = qw();                                                          <---
    
    sub funcName {...}
    sub methodName {...}
    sub anotherMethodName {...}
    

    Then, in your module (.vp file) add a line that reads:

    //; use MyLib qw(functionName methodName anotherMethodName);
    
  2. (Less Recommended -- Selective Inheritance of All Methods Via @ISA) You can tell all Genesis2 modules to inherit ALL methods from the MyLib module. This will allow you to call MyLib functions and methods as your own using either MyLib::funcName(args), $self->methodName($args), or funcName($args). To do that, the code in MyLib.pm stays the same as described above, and you simply add to your module (.vp file) the following lines:
    //; use MyLib;
    //; push (@ISA, "MyLib");
    
  3. (Only Do If You Know What You're Doing -- None Selective Inheritance via @ISA) In rare cases, you will want all your modules (.vp files) to inherit some function or method from MyLib.pm. In order to do that, we force the UniqueModule (which is the base class of all Genesis2 modules) to inherit from the MyLib package. Then, each and every module in Genesis would be able to call $self->methodName(args). To activate this inheritance your MyLib.pm code should read as follows:
    package MyLib;
    use warnings;
    use strict;
    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
    use Exporter;
    @ISA = qw(Exporter);
    $VERSION = '1.00';
    @EXPORT = qw(funcName methodName anotherMethodName);
    @EXPORT_OK = qw();
    push (@Genesis2::UniqueModule::ISA, qw(MyLib));                        <---
    
    sub funcName {...}
    sub methodName {...}
    sub anotherMethodName {...}
    

    In addition, you need to 'use' MyLib by either calling "//; use MyLib;" in anyone of your modules (.vp) file, or using the command line flag "-perl_modules MyLib" as described here.

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)

Personal tools