====== 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|''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 [[https://github.com/asyncvlsi/act/tree/master/miniscm#readme|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 | This adds short from and detailed long-form help to a user-defined command. | | source [] | 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 | set output window width in characters (min 40) | | build-options | display the options used to build ''interact'' | | error | report error and abort execution | | prompt | change prompt to the specified string | | getenv | this is used to return the value of the environment variable '''' | | putenv | this sets the environment variable '''' to '''' | | 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 | 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 | returns the ''n''th 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 [[https://github.com/asyncvlsi/act/blob/master/miniscm/default.scm|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 [[https://github.com/asyncvlsi/interact/blob/main/scripts/aflat|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 | set number of threads used by Galois runtime to | | 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 | open a file in the specified (r = read, w = write, a = append), and return handle | | sys:close | close file corresponding to the specified | 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 | open a command log file called | | 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 | returns pitch of metal layer | ===== Configuration parameters ===== [[config:start|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 | read configuration file | | conf:save | write the complete current configuration to the specified file | | conf:gettype | returns the configuration parameter type as an integer value. -1 = missing, 0 = int, 1 = string, 2 = real. | | conf:set_int | set the integer configuration parameter to | | conf:set_string | set the string configuration parameter to | | conf:set_real | set the real configuration parameter to | | conf:set_default_int | set default integer configuration parameter to | | conf:set_default_string | set default string configuration parameter to | | conf:set_default_real | set default real configuration parameter to | | conf:get_int | return integer configuration parameter value | | conf:get_string | return string configuration parameter value | | conf:get_real | 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 [[intro_example:name_mangling|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 | print type signature of a user-defined type | | act:getns [] | returns list of sub-namespaces within namespace | | act:getproc [] | returns list of process types in namespace | | act:getdata [] | returns list of data types in namespace | | act:getchan [] | returns list of channel types in namespace | | act:display-type [] | display type of instance in process | | act:save-insts | 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 [[https://github.com/asyncvlsi/actpass|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 [[https://avlsi.csl.yale.edu/act_docs/|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 '''' 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 | set pass parameter to a file handle. The file handle should have been opened earlier by ''sys:open''. | | act:pass:set_int | set pass parameter to the integer | | act:pass:set_string | set pass parameter to the string | | act:pass:set_real | set pass parameter to a real number | | act:pass:get_int | return int parameter from pass | | act:pass:get_real | 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 | run pass, with mode set to | | act:pass:runcmd | run pass command | 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 [[asic:pnr:start|physical implementation flow]]. ===== Circuit manipulation ===== ==== Circuit generation ==== ckt:map - generate transistor-level description ckt:save-sp - save SPICE netlist to ckt:save-flatsp - save flattened spice netlist to file after cell mapping ckt:mk-nets - preparation for DEF generation ckt:save-prs - save flat production rule set to for simulation ckt:save-lvp - save flat production rule set to for lvp ckt:save-sim - save flat .sim/.al file ckt:save-vnet [-nocell] - save Verilog netlist to ==== Cell mapping ==== ckt:cell-map [-l] - map gates to cell library; -l lists used cells ckt:cell-save - save cells to file ckt:cell-addbuf - add buffer to the pin within the process ckt:cell-edit - replace cell for instance within ckt:cell-update - take the design back to the clean state ckt:net->pins - return pins that a net is connected to ckt:cell->pins - return pins for a cell ===== Timing and power analysis ===== timer:lib-read - read liberty timing file and return handle timer:lib-merge - merge into liberty file handle timer:time-units - returns string for time units timer:build-graph - build timing graph timer:tick +/- +/- - add a tick (iteration boundary) to the timing graph timer:add-constraint +/- [*][+/-] [*][+/-] [margin] - add a timing fork constraint timer:init ... - initialize analysis engine with specified liberty handles timer:spef - read in SPEF parasitics from 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 - display information about the net timer:constraint [] - display information about all timing forks that involve 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 # 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 - returns rise time for timer:get-fall - returns fall time for timer:rise-violations