Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
language:types2 [2024/07/18 16:28] – [Macros and Functions] rajitlanguage:types2 [2025/05/02 10:18] (current) – [Default parameters] rajit
Line 160: Line 160:
 adder and five-bit adder. adder and five-bit adder.
  
 +==== Default parameters ====
  
-===== Direction flags and user-defined types =====+When defining complex user-defined types with many parameters, it can be useful to have 
 +default parameter values. ACT has syntax to support default parameter values for trailing 
 +parameters in a template definition. 
 + 
 +<code act> 
 +template <pint N; pbool active_high true> 
 +defproc driver(bool? inp; bool! outp) 
 +
 +  bool sig; 
 +  prs { 
 +    inp => sig- 
 +  } 
 +  [active_high -> prs { sig => outp- } 
 +  [] else -> sig outp; 
 +  ] 
 +
 +</code> 
 +(Note: this is not a real signal driver, but the idea here is the you have a parameterized 
 +driver that can drive a fanout of ''N'' gates.) This definition has a default value for the  
 +''active_high'' parameter as ''true'' So an instance 
 +<code act> 
 +driver<4> x; 
 +</code> 
 +will have four production rules: 
 +<code act> 
 + x.inp -> sig- 
 +~x.inp -> sig+ 
 + sig -> x.outp- 
 +~sig -> x.outp+ 
 +</code> 
 +However, this behavior can be changed by using: 
 +<code act> 
 +driver<4,false> x; 
 +</code> 
 +In this case, ''sig'' will be connected to ''x.outp''
 + 
 +Note that ACT is very strict about type-checking; so, for example, ''driver<4>'' and ''driver<4,true>'' are //not// treated as the same type even though the default parameter value for the second template parameter is ''true''
 + 
 +==== Grouping parameters ==== 
 + 
 +Parameters can be combined into [[language:types2:data#parameter_structures|parameter structures]], to organize a large number of parameters and treat them as a group. Parameter structures can also be used as a template parameter types
 + 
 +===== Direction flags  =====
  
  
Line 205: Line 248:
 is detailed in the section on connections. is detailed in the section on connections.
  
-===== Macros and Functions =====+===== Macros and Functions within User-defined types =====
  
 User-defined types support additional methods (beyond the special ones for channels and data types). User-defined types support additional methods (beyond the special ones for channels and data types).
Line 213: Line 256:
  
 ==== Macros ==== ==== Macros ====
 +
 +A macro is, as the name sounds, a CHP fragment. This fragment is used to substitute for the macro in the places where it is used. Macros can be defined for any user-defined type (except for parameter structures).  As an example, consider a process that implements a data structure like a stack.
 +
 +<code act>
 +defproc stack (chan(int)? in; chan(int)!out )
 +
 +  ...
 +}
 +</code>
 +
 +In ordinary circumstances, one would instantiate a copy of the stack, and then use the ''in'' and ''out'' channels to push or pop elements from the stack as follows:
 +
 +<code act>
 +...
 +stack s;
 +int x;
 +...
 +chp {
 +   ...
 +   s.in!5; // push value 5
 +   ...
 +   s.pop?x; // pop x out of the stack
 +   ...
 +}
 +</code>
 +
 +As an alternative, the user could provide //macros// to push and pop elements from the stack as follows:
 +
 +<code act>
 +defproc stack (chan(int)? in; chan(int)!out )
 +
 +  ...
 +  methods {
 +      macro push(int val) {
 +          in!val
 +      }
 +      macro pop(int res) {
 +          out?res
 +      }
 +  }
 +}
 +</code>
 +
 +The same stack use case can be written as:
 +<code act>
 +...
 +stack s;
 +int x;
 +...
 +chp {
 +   ...
 +   s.push(5);
 +   ...
 +   s.pop(x);
 +   ...
 +}
 +</code>
  
 ==== Functions ==== ==== Functions ====
  
 +In addition to macros, [[language:types2:data#pure_structures|pure structures]] can also include user-defined functions. User-defined functions within pure structures have similar syntax to macros. The following is an illustrative example
 +
 +<code act>
 +deftype signed_int (bool s; int<7> v)
 +{
 +    methods {
 +        function negative() : bool
 +        {
 +            chp {
 +              self := s
 +            }
 +        }
 +        function mag() : int<7>
 +        {
 +            chp {
 +               self := v
 +            }
 +        }       
 +   }
 +}
 +</code>
 +
 +With this definition, a user can use method calls to access the fields of the structure as follows:
 +
 +<code act>
 + signed_int s;
 + ...
 +chp {
 +    ... 
 +    [ s.negative() -> log ("Negative number!")
 +    [] else -> log ("Positive number!")
 +    ]
 +}    
 +...
 +</code>
 +
 +Note that functions cannot have any side-effects; in particular, this means that a function cannot change
 +any of the members of the pure structure. Macros can be used to change those.
 +
 +=== Operator overloading ===
 +
 +Functions within pure structures are also used to support operator overloading. In particular, the following function methods are interpreted to be the definition of operator overloading for arithmetic operators:
 +   * ''plus'', ''minus'', ''mult'', ''div'', ''mod'' : addition, subtraction, multiplication, division, and modulo operators
 +   * ''uminus'' : unary minus
 +   * ''and'', ''or'', ''xor'' : logical operators
 +   * ''lsl'', ''lsr'', ''asr'' : logical shift left, logical shift right, arithmetic shift right
 +   * ''lt'', ''gt'', ''le'', ''ge'', ''eq'', ''ne'' : comparison operators
 +   * ''not'' : logical negation
 +An example of a fixed-point arithmetic datatype is provided in the [[https://github.com/asyncvlsi/stdlib/blob/main/math/fxp.act|ACT standard library]], and serves as a useful reference for using operator overloading.
 +In the linked example, ''fixpoint<a,b>'' corresponds to a fixed-point number with ''a'' integer bits and ''b'' fractional bits following the standard Q(a,b) format.