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
interactis 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