prs2net: automated netlist generation

The tool prs2net can be used to automatically generate a hierarchical spice netlist from an .act file. Parameters that control defaults and the output format are specified in a configuration file.

The overall way the tool works is as follows. First, it reads in the .act file. This file is then “expanded”, which means that all parameters are expanded out. This requires instances of cells in the top-level file. In general, it might make sense to have a file test.act that imports the necessary act file and instantiates the top-level cell of interest.

Expanded versions of cells have their expanded template attached to their names. In the following example, after expansion, there are two cells: foo (the unexpanded cell), and foo<> (the expanded cell).

    defproc foo(bool a, b)
    {
      prs {
        a => b-
      }
    }
    
    foo f;

If the instance foo f; were missing, then foo would not be expanded into foo<> (since it is not used).

Basic Netlist Specification

Production rules are syntactically translated into a netlist. The gate order is taken from left to right, where the power supply is the leftmost node and the output is the rightmost node. This means that the rule

   a & b -> c-

gets translated into a netlist that starts from GND, then has transistors gated by a followed by b, and the drain of the final transistor is connected to c. The netlist corresponding to just this rule is given by:

  M0_ GND a #3 GND nch W=0.3U L=0.12U
  M1_ #3 b c GND nch W=0.3U L=0.12U

(The details may vary depending on your configuration file.) A close examination shows the gate ordering a followed by b, where a is closer to GND.

Widths, Lengths, Flavors. The width and length of any transistor can be specified using size specifiers. For the same rule above, we could specify a different width for a as follows:

  a<20> & b -> c-

This says the width of the transistor for a is 20 units (the multiplier is specified in the configuration file). Once a size specifier is provided, it is used by the expression until another specifier is seen. This is convenient, for example, when you need to specify that an entire stack uses the same width.

Length specifiers can also be used to change the default length of a transistor. The same example with a longer transistor (length 5) is given by:

  a<20,5> & b -> c-

Finally, different transistor flavors can also be specified. The recognized flavors are specified in the ACT configuration file. Commonly used names are:

  • svt : standard Vt
  • lvt : low Vt
  • hvt : high Vt

The following shows how these can be used:

   a<20,lvt> & b<20> -> c-
   q<10,5,hvt> & r<10,5> -> d-

In this example, the transistor gated by a is low Vt, while the one gated by q is high Vt. All others are standard Vt. Additional details are available in the prs sub-language documentation.

Pass Transistors. Pass transistors are specified using passn, passp, and transgate. These also take the same width/size/flavor specifiers as described above. The syntax of these three constructs is:

  • passn(gate,src,drain): n-type pass transistor
  • passp(gate,src,drain): p-type pass transistor
  • transgate(ngate,pgate,src,drain): a transmission gate with ngate and pgate corresponding to the signals connected to the n-type and p-type transistor respectively (normally they will be complements of each other).

Each of these can contain a size directive as shown in the examples below:

   prs {
     passn<10,3> (g,s,d)
     passp<10,4,lvt> (_g,s,d)
   }

Internal Precharges. Precharges are only on internal nodes, and new internal nodes are only created with an & operator. So how about we say

  a &{+expr} b

for a precharge to Vdd (indicated by +), and

  a &{-expr} b

for a precharge to GND (indicated by -). Also, the type of the expression indicates which transistor type gets used. So, for instance

  a &{+en} b -> c-

specifies a precharge to Vdd with n-type transistors (since en is uninverted). The same precharge with p-type transistors would be written

  a &{+~_en} b -> c-

(assuming _en was the complement of en.)

Shared Gate Networks

The syntax supports building arbitrary shared-gate networks. This can be done via labels, indicated with the @ symbol. To illustrate, the following example builds a shared gate network:

 a & b -> @x-
 ~@x & w -> r0-
 ~@x & r -> r1-

The idea is that “@” is a label for the internal node. Note that @'s always appeared in the “wrong sense” in the production rule. The label @x should not be confused with a bool variable. This label is only internal to the production rule body.

The second construct is

tree {
  a & b & w -> r0-
  a & b & r -> r1-
}

This specifies maximal sharing, i.e. build the shared-gate network by maximal prefix-sharing within the group. Finally, we can limit the size of the prefix by specifying a sharing-limit as follows

tree<1> {
  a & b & w -> r0-
  a & b & r -> r1-
}

Attributes

Attributes can be attached to a production rule or pass transistor/transmission gate using standard .act syntax. Some commonly used ones are:

  • keeper=0 : do not generate a keeper for this node, even if it looks like a state-holding gate.
  • comb=1 : use combinational feedback rather than a standard staticizer if the node is state-holding.
  • output=v : used for pass transistors to force either the source, drain, or both to be labelled as an output. This is useful for the PININFO directive emitted by prs2net. If the value v has bit zero set, then the source is marked as an output node. If v has bit one set, then the drain is marked as an output. By default, a node is considered an input if it does not have a production rule driving it.
  • loadcap=v : sets the load capacitance on the output to be a the specified value in fF. This is used to override the default setting specified in the configuration file.

The following shows how you can specify two C-elements, one with no staticizer, and another with combinational feedback.

    prs {
      [keeper=0] a & b #> c-
 
      [comb=1] p & q #> r-
    }

Attributes currently recognized by prs2net are:

Attribute Meaning
keeper The production rules for a signal are analyzed to determine if the pull-up and pull-down networks are perfect complements of each other. If they aren't, then a keeper is generated. There are two common scenarios when this behavior is undesired: (i) the gate is intended to be dynamic, and so it is state-holding but a staticizer should not be generated. Set keeper to 0 for this behavior. (ii) the gate looks state-holding, but it is actually a combinational gate because certain inputs are supposed to be complements of each other. In this case, set keeper to 2.
comb If set to 1, uses combinational feedback rather than a weak inverter for the staticizer; if 0, uses a weak inverter instead of combinational feedback
iskeeper used to let prs2net know that the specified production rule is in fact the manually specified staticizer/keeper circuit. prs2net labels transistors used for keepers in the spice netlist, and this attribute can be used to ensure that manually specified keepers are also labeled (with _keeper).
isckeeper used to let prs2net know that the specified production rule is a combinational feedback style keeper circuit. These will be labeled with _ckeeper.
loadcap sets the load capacitance on the output to be a the specified value in pF. This is used to override the default setting specified in the configuration file
oresis sets output resistance for node. This resistance is added in series to the output of the gate, and overrides the default from the prs2net configuration file
output used for pass transistors to force either the source, drain, or both to be labelled as an output. This is useful for the PININFO directive emitted by prs2net. If the value v has bit zero set, then the source is marked as an output node. If v has bit one set, then the drain is marked as an output. By default, a node is considered an input if it does not have a production rule driving it.
N_reff sets the n-stack effective resistance, overriding the default computed by prs2net. This is used to compute strengths of staticizers. The resistance for one transistor is computed as L/W where L and W are the length and width of the transistor respectively.
P_reff same as N_reff, except sets strength of p-stack