interact: Interactive ACT

The interact tool provides a command-line and scripting interface to the ACT tools. Most of the core ACT tools can be replaced by interact scripts, and the finer grain access to various phases of the ACT tool-flow means that you can customize your design/flow in ways that are not easy to do using just command-line options of existing tools. Over time, most of the ACT tools will be deprecated and subsumed entirely by interact.

interact uses the same command-line scripting language as the ''actsim'' tool. In other words, there is a complete programming language on the command-line. The language is a subset of the Scheme programming language, and the implementation is provided as part of the core ACT library. The implemented subset of Scheme is documented on github. This means it is possible to define custom commands and extend the scripting interface.

To start interact, simply run:

$ interact
interact>

Most of the time you will want to specify the technology of interest and a refinement level. For example, to work on the output of chp2prs in the sky130l technology, you may say:

$ interact -ref=1 -Tsky130l
interact>

interact also takes an optional script file as a command-line argument, and this can be used for batch jobs rather than interactive jobs.

The following documents the commands supported by interact. When a command doesn't have any meaningful return value, the default return value is the constant true (#t).

The flow state

interact keeps track of the current state of the design flow. The flow states are:

  • No design: this is the initial state when interact is started
  • Unexpanded design: this is the state after the first ACT file has been read in by the user
  • Expanded design: this is the state after the ACT design has been expanded/elaborated.
  • Dirty: ACT commands can be used to edit the design via a script (e.g. for buffer insertion and gate resizing)

Normally once a design is expanded, no new files can be added to the design. Since updating everything in the design database is costly, we enter a dirty state while editing and then can use an interact command to update the database after all the edits are complete, returning back to the expanded state.

Only a subset of the commands can be used in a given state, and a flow state error will be reported when a command is used in the wrong state.

Basic commands

Standard built-ins

The following commands are built into the scripting framework:

Command Meaning
help [cmd] print help information/list commands. If cmd is specified, it is used as a string prefix and all commands that begin with that string are displayed. If no cmd is specified, then a summary of the built-in commands for interact is displayed. If the command is specified and there are multiple matches, then a summary of the short form help for the matched commands is displayed. If there is a single match and it also has a long-form help, then the long form help for the matched command is also displayed.
help-add <name> <short> <text> This adds short from and detailed long-form help to a user-defined command.
source <filename> [<repeat-count>] This reads in an interact script, optionally repeating it a number of times
exit terminates the session
quit the same as exit

Interacting with the user and environment

The following commands are used to interact with the environment, and for miscellaneous operations that are generic and not related to the ACT flow.

Command Meaning
echo [-n] args display the arguments to this command to the screen. The -n option omits the final newline
window-width <width> set output window width in characters (min 40)
build-options display the options used to build interact
error <str> report error and abort execution
prompt <str> change prompt to the specified string
getenv <string> this is used to return the value of the environment variable <string>
putenv <name> <value> this sets the environment variable <name> to <value>
read [prompt] read input with an optional prompt, and return the entered string
curtime return a pair of elapsed (cputime realtime) in ms since the last call

interact can be used to create scripts using the Unix #! construction. In particular, you can create a script like this:

#!/usr/bin/env interact

echo "Hello" (read "Who are you? ") "Technology:" (getenv "ACT_TECH")

Running this script will prompt the user to enter a string, and then display Hello followed by the string (which will likely include a newline), followed by “Technology:” and the name of the technology being used.

Using #! and setting the permissions to executable makes a text script look like an executable. In this use case, the executable will often need command-line arguments. To handle this, the following commands are supported:

Command Meaning
getopt <string> run the C getopt function. This is used to parse any additional command-line arguments that may be passed to the interact executable as command-line options. The string uses the standard format for the C getopt() function. After calling this command, the user-specified options can be accessed using the getargc and getargv commands.
getargc return number of arguments. This returns the number of remaining arguments after command-line processing.
getargv <n> returns the nth command-line argument

The following script illustrates how these commands can be used to parse command-line options.

#!/usr/bin/env interact
 
getopt "mC:"
 
echo (getargc)
echo (getargv 0)
echo (getargv 1)
echo (getargv 2)
echo (getargv 3)

Running this will result in the following:

$ ./test.ia -m -C test
3
./test.ia
-m
-Ctest
getargv: argument (3) out of range
Execution aborted.
Stack trace:
	called from: getargv
	called from: echo
	called from: -top-level-

To only display the number of arguments specified, we can use the following:

#!/usr/bin/env interact
 
getopt "mC:"
 
define i 0
repeat (getargc) (lambda () (begin (echo (getargv i)) (set! i (+ i 1))))

As a side remark, this is a very un-Scheme like way of implementing the required functionality, since we are defining the variable i and incrementing it in a loop. Also, the repeat function is in fact defined in the default scheme functions that are always loaded in. But it gets the job done:

$ ./test.ia 
./test.ia
$ ./test.ia -m
./test.ia
-m
$ ./test.ia -C test -m 
./test.ia
-Ctest
-m

Also, at this point, I hope it is clear that having complex Scheme commands in a standard interact script is going to be hard to read/debug as it would be a single, complex line. Instead, it is better to define such Scheme commands in an auxiliary Scheme file and load it in via the built-in load-scm command, which expects a Scheme script as its command-line argument.

Given that options parsing is a standard use-case, interact comes with a simple command-line parsing package. After calling getopt, load the act-opt.scm package using load-scm. The two key functions are act:get-options and act:remaining-args. Look at aflat as a script for an example. The parsing package treats options without arguments as flags that are stored in variables, and options with arguments as options that are stored as a string.

Misc support functions

The Galois parallel programming system is used for multi-threaded execution of some of the ACT tools. The number of threads used can be dynamically set the number of active threads used for parallel execution.

Command Meaning
sys:nthreads <num> set number of threads used by Galois runtime to <num>
sys:end-galois shutdown Galois runtime

File I/O is supported via file handles, which are integers corresponding to open files.

Command Meaning
sys:open <name> <mode> open a file in the specified <mode> (r = read, w = write, a = append), and return handle
sys:close <handle> close file corresponding to the specified <handle>

A transcript of interact commands can be saved to a log file to make it easier to create an interact command script for re-use later. Note that interact's execution is deterministic, so this can be used to reproduce results.

Command Meaning
sys:log <name> open a command log file called <name>
sys:endlog close the currently open log file

Technology parameters

When interact is initialized, it reads in technology information. When the layout generation module is loaded, it also reads in technology parameters like a subset of the design rules. It can be useful to query various technology parameters in a script. In particular, the following query commands are supported.

Command Meaning
tech:uscale returns the scale factor used when returning any technology design rules in units of microns
tech:scale similar to tech:uscale, except it returns scale factor in units of nanometers
tech:getpitch <layer> returns pitch of metal layer <layer>

Configuration parameters

Configuration files are used to setup technology-specific information and running mode for all aspects of the ACT flow. interact includes commands can query the value of any configuration option, as well as change the option.

Command Meaning
conf:read <file> read configuration file
conf:save <file> write the complete current configuration to the specified file
conf:gettype <name> returns the configuration parameter type as an integer value. -1 = missing, 0 = int, 1 = string, 2 = real.
conf:set_int <name> <val> set the integer configuration parameter <name> to <val>
conf:set_string <name> <val> set the string configuration parameter <name> to <val>
conf:set_real <name> <val> set the real configuration parameter <name> to <val>
conf:set_default_int <name> <val> set default integer configuration parameter <name> to <val>
conf:set_default_string <name> <val> set default string configuration parameter <name> to <val>
conf:set_default_real <name> <val> set default real configuration parameter <name> to <val>
conf:get_int <name> return integer configuration parameter value
conf:get_string <name> return string configuration parameter value
conf:get_real <name> return real configuration parameter value

When the conf:set_{int,string,real} family of commands is used, reading a configuration file will not change the value of the configuration parameter. If instead the conf:set_default_{int,string,real} command is used, then its value can be changed by reading a configuration file.

ACT functions

The following functions use the act: prefix, and are used for reading/writing ACT files, expansion, as well as loading and using dynamically loaded passes in the ACT framework.

ACT core functions

The standard way an interact session begins is by reading in an ACT file.

interact> act:read "top.act"

This command will read in the ACT design. This should be used only for the first ACT file that is read in. Typically the rest of the design is imported by the top-level ACT file, so this command reads in the entire design. This takes the flow state from no design to unexpanded design.

In some cases, additional ACT files may need to be added. For example, for cell mapping during the physical implementation flow, a cell file may be merged with the design so that existing cells can be used during the mapping process.

interact> act:merge "cells.act"

This merges in cells.act with the entire design, and can be used in the unexpanded design flow state.

One of the standard ACT command-line options is -D. This allows the user to both create a global parameter and set its value prior to reading in the entire ACT file. This can be used, for example, if an ACT file operates in different modes, and the value of the mode is set via a parameter prior to reading in the file. While interact also supports the -D command-line option, the same effect can be achieved using the following ACT commands.

interact> act:defpint "MYINT" 5

This creates a new pint named MYINT, and sets its value to 5.

interact> act:defpbool "MYBOOL" #t

This creates a new “pbool” named MYBOOL, and sets its value to true.

The ACT language supports global variables that are visible in processes even though they are not passed in through the port list. This can be inconvenient when interacting with commercial tools. The act:localize command can be used to convert a global signal into a local signal name throughout the entire design. This effectively modifies the port list where needed by adding the global signal name to the port list. This must be done prior to expansion. For example, to convert the Reset signal into a local signal, use

interact> act:localize "Reset"

The next step is usually expanding the design. This substitutes all parameters and creates specialized types using parameter values.

interact> act:expand

This takes the flow state from unexpanded design to expanded design.

Finally, the implementation flow needs to know the process that corresponds to the top level of the design hierarchy.

interact> act:top design_top_proc

This sets the top-level process for the design, and can only be used in the expanded design flow state.

A script may want to know the name of the top-level process. This value is returned as a string using

interact> echo "Top level is:" (act:gettop)
Top level is: design_top_proc<>

(assuming this was the name of the expanded process that is set to the top-level). An empty string is returned if there is no top-level process set.

The current ACT data structure (either expanded or unexpanded) can be saved to a file using the act:save command as follows:

interact> act:save "out.act"

When using types that have template parameters, the expanded type names use mangled names. While there is a systematic way to convert mangled names to/from unmangled names, it is convenient to use commands to do the conversion.

The act:mangle-print command can be used to display the mangled name corresponding to a string. The function always returns the mangled string, and the display behavior can be turned off by passing an optional second argument of #f.

interact> act:mangle-print "hello<>"
`hello<>' is mangled to `hello_3_4'

The inverse operation is act::unmangle-print (which also takes an optional argument to suppress the display).

interact> act:unmangle-print "hello_3_4"
`hello_3_4' is unmangled to `hello<>'

Finally, if you need to change the name mangling behavior, use

interact> act:mangle ":()<>[],{}."$\@"

This sets the currently mangled characters to those from the string. The string used in this example is the default name mangling characters in the generic ACT configuration that is distributed with the ACT library.

ACT design query API

Once the design is expanded, the query API can be used to inspect various aspects of the ACT data structures. Note that even if a design is expanded, the unexpanded types are still present. For example, if there was a process named test, and it was expanded, then the expanded ACT data structure contains both “test” (the unexpanded type) as well as “test<>” (the expanded type).

The following functions can be used to inspect different aspects of the ACT data structure

Command Meaning
act:typesig <name> print type signature of a user-defined type
act:getns [<ns>] returns list of sub-namespaces within namespace <ns>
act:getproc [<ns>] returns list of process types in namespace <ns>
act:getdata [<ns>] returns list of data types in namespace <ns>
act:getchan [<ns>] returns list of channel types in namespace <ns>
act:display-type [<proc>] <name> display type of instance <name> in process <proc>
act:save-insts <file> save circuit instance hierarchy to the specified file

ACT dynamic pass management

ACT supports dynamically loaded passes. This allows a user to write any functionality that manipulates the ACT data structure and then load it in at run-time. This can be used to create a custom optimization tool or circuit analysis that directly operates on the core data structures. This dynamic pass feature is used to implement logic synthesis, layout generation, as well as static timing analysis. A template for how to implement an ACT dynamic pass is provided on github.

To load a dynamic pass, three items are needed:

  • The name of the shared object library (the dynamic library) that has the definitions of the functions required for a dynamic pass.
  • The name of the pass. This name is used to refer to the pass in other commands. A pass must have a unique name. Several passes are already built into the ACT infrastructure, and the following names are already taken by built-in passes: booleanize, sizing, prs2net, prs2cells, collect_state, apply, finline, chpmem, chparb. The following names are already taken by other dynamically loaded passes: annotate, stk2layout, net2stk, taggedTG.
  • The common prefix used by all the functions used to implement the pass. Look at the dynamic pass example on github to understand what this means. The prefixes for dynamic passes are annotate_pass, layout, stk, tgraph.

If defining your own pass, please use a different name and prefix to avoid confusion.

The following loads the annotate pass:

interact> act:pass:load "annotate_pass.so" "annotate" "annotate_pass"

The first argument is the shared object library that holds the pass definition, the second is the name of the pass, and the third is the prefix used for all the functions that correspond to the API required to implement a pass.

In all the commands below, the <pass-name> parameter corresponds to the name of the pass that was loaded. Each pass has pass-specific parameters that can be set to enable/configure different functionality; this can be viewed as the mechanism that is used to pass arguments to a dynamically loaded pass, as well as return values from the pass to the interact script. The following commands are supported:

Command Meaning
act:pass:set_file <pass-name> <name> <filehandle> set pass parameter to a file handle. The file handle should have been opened earlier by sys:open.
act:pass:set_int <pass-name> <name> <ival> set pass parameter <name> to the integer <ival>
act:pass:set_string <pass-name> <name> <string> set pass parameter <name> to the string <string>
act:pass:set_real <pass-name> <name> <rval> set pass parameter <name> to a real number <rval>
act:pass:get_int <pass-name> <name> return int parameter from pass
act:pass:get_real <pass-name> <name> return real parameter from pass

Finally, each pass can be run in different modes. Modes are integer-valued, with the default being mode 0. Specific pass-defined commands can also be run from interact, where the arguments to the pass-defined commands are handled via the parameter mechanism above.

Command Meaning
act:pass:run <pass-name> <mode> run pass, with mode set to <mode>
act:pass:runcmd <pass-name> <cmd> run pass command <cmd>

If you've installed the entire actflow repository, check $ACT_HOME/lib/scm for examples. The file stk-pass.scm loads the dynamic pass stk2layout, and a number of the layout generation commands are defined using the act:pass:… API. For example, the LEF generation function is

      (define act:layout:run (lambda (mode) (act:pass:run "stk2layout" mode)))
 
      (define act:layout:create (lambda () (act:layout:run 0)))
 
      (define act:layout:lef
        (lambda (lef cell)
          (let ( (f1 (sys:open lef "w")) (f2 (sys:open cell "w")) )
            (begin
              (act:pass:set_file "stk2layout" "lef_file" f1)
              (act:pass:set_file "stk2layout" "cell_file" f2)
              (act:layout:run 1)
              (sys:close f1)
              (sys:close f2)
              )
            )
          )
        )

These layout creation functions are called via phydb:create (look at phydb.scm in the same path), which is the standard first step in the physical implementation flow.

Circuit manipulation

Circuit generation

 ckt:map - generate transistor-level description
 ckt:save-sp <file> - save SPICE netlist to <file>
 ckt:save-flatsp <file> - save flattened spice netlist to file after cell mapping
 ckt:mk-nets - preparation for DEF generation
 ckt:save-prs <file> - save flat production rule set to <file> for simulation
 ckt:save-lvp <file> - save flat production rule set to <file> for lvp
 ckt:save-sim <file-prefix> - save flat .sim/.al file
 ckt:save-vnet [-nocell] <file> - save Verilog netlist to <file>

Cell mapping

 ckt:cell-map [-l] - map gates to cell library; -l lists used cells
 ckt:cell-save <file> - save cells to file
 ckt:cell-addbuf <proc> <inst> <pin> <buf> - add buffer to the pin within the process
 ckt:cell-edit <proc> <inst> <newcell> - replace cell for instance within <proc>
 ckt:cell-update - take the design back to the clean state
 ckt:net->pins <net> - return pins that a net is connected to
 ckt:cell->pins <inst> - return pins for a cell

Timing and power analysis

 timer:lib-read <file> - read liberty timing file and return handle
 timer:lib-merge <lh> <file> - merge <file> into liberty file handle <lh>
 timer:time-units - returns string for time units
 timer:build-graph - build timing graph
 timer:tick <net1>+/- <net2>+/- - add a tick (iteration boundary) to the timing graph
 timer:add-constraint <root>+/- [*]<fast>[+/-] [*]<slow>[+/-] [margin] - add a timing fork constraint
 timer:init <l1> <l2> ... - initialize analysis engine with specified liberty handles
 timer:spef <file> - read in SPEF parasitics from <file>
 timer:phydb-link - link timer to phydb for timing-driven physical design flow
 timer:run - run timing analysis, and returns list (p M)
 timer:crit - show critical cycle
 timer:info <net> - display information about the net
 timer:constraint [<net>] - display information about all timing forks that involve <net>
 timer:num-constraints - returns the number of constraints in the design
 timer:get-violations - returns a list of constraint ids (cids) that have violations
 timer:check-constraint cid [ticks] - does a path analysis to check paths for timing fork #<cid> exist
 timer:get-slack cid - returns the slack of the violating constraint id #cid
 timer:get-witness cid - displays the witness for the violation
 timer:get-rise <net> - returns rise time for <net>
 timer:get-fall <net> - returns fall time for <net>
 timer:rise-violations <time> - returns a list of drivers that have rise time worse than <time> in timer units
 timer:fall-violations <time> - returns a list of drivers that have fall time worse than <time> in timer units
 timer:save <file> - save abstract timing graph to file in graphviz format

Physical database

 phydb:init - initialize physical database
 phydb:set-placement-grid <grid_value_x> <grid_value_y> - set placement grid
 phydb:read-lef <file> - read LEF and populate database
 phydb:get-used-lef - return list of macros used by the design
 phydb:read-def <file> - read DEF and populate database
 phydb:read-cell <file> - read CELL file and populate database
 phydb:read-techconfig <file> - read technology configuration file
 phydb:read-cluster <file> - read Cluster file and populate database
 phydb:get-columns - return a list of coordinates of columns in grid point coords
 phydb:get-gaps - return a list of coordinates of gaps in the minirows
 phydb:place-cell <cell-type> <llx> <lly> <N|FS> - add a new cell to a fixed location
 phydb:place-inst <inst> <llx> <lly> <N|FS> - place an instance at a fixed location
 phydb:add-io <iopin_name> <net_name> <direction> <use> - add a new I/O pin
 phydb:place-io <iopin_name> <metal_name> <lx> <ly> <ux> <uy> <placement_status> <x> <y> <orientation> - place an I/O pin at a fixed location
 phydb:write-def <file> - write DEF from database
 phydb:write-guide <file> - write GUIDE from database
 phydb:write-cluster <file> - write CLUSTER from database
 phydb:write-aux-rect <file> - write PP/NP cover and well rect files
 phydb:close - tear down physical database

Placement

Partitioning

 bipart:partition <file> [k] [depth] - compute a k-way partition (default 2)

Dali placer

 dali:init <verbosity_level(0-5)> - initialize Dali placement engine
 dali:add-welltap <-cell cell_name -interval max_microns> [-checker_board] - add well-tap cell
 dali:place-design <target_density> [number_of_threads] - place design
 dali:place-io <metal_name> - place I/O pins
 dali:global-place <target_density> [number_of_threads] - global placement
 dali:refine-place <engine> - refine placement using an external placer
 dali:export-phydb - export placement to phydb
 dali:close - close Dali

Routing

Power detailed routing

 pwroute:init <verbose> -initialize pwroute engine <verbose> 
 pwroute:set_parameters <reinforcement_width, reinforcement_step, cluster_mesh_width> - run pw route with mesh configuration. Default is <8, 16, 2>
 pwroute:set_reinforcement <bool>, enable/disable reinforcement connection (default: 1) 
 pwroute:run run pwroute
 pwroute:export-phydb -export power and ground wires to phydb
 pwroute:close -close pwroute

Global routing

 sproute:init initialize sproute engine
 sproute:set-num-threads set num threads, default = 1
 sproute:set-algo Det/NonDet, default is NonDet
 sproute:set-max-iterations set max iterations of maze routing, default = 30
 sproute:run run sproute
 sproute:close close sproute