Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
language:impl [2021/11/21 12:34]
rajit
language:impl [2023/04/09 18:06] (current)
rajit [Overrides]
Line 20: Line 20:
 When a type implements another one, the new type can be used in places When a type implements another one, the new type can be used in places
 the old type was used. While this is superficially similar to the old type was used. While this is superficially similar to
-subtyping in programming languages, it is better viewed as a +subtyping in programming languages, it is better viewed as an 
-refinement relationship. So, if type ''tA'' implements type+implementation relationship. So, if type ''tA'' implements type
 ''tB'', then ''tA'' has a more detailed description of the ''tB'', then ''tA'' has a more detailed description of the
 implementation compared to ''tB''. Type ''tB'' is the implementation compared to ''tB''. Type ''tB'' is the
Line 37: Line 37:
 equivalent to each other. equivalent to each other.
  
-A more interesting option is to use refinement between two +A more interesting option is to use the implementation relationship 
-user-defined types. Refinement is used to create related versions of+between two user-defined types. This option is used to create related versions of
 an existing type. If type ''foo'' implements ''bar'', then the an existing type. If type ''foo'' implements ''bar'', then the
 basic rule is that one can use ''foo'' instances in all the same basic rule is that one can use ''foo'' instances in all the same
Line 45: Line 45:
 detail below. detail below.
  
-==== Refinement ====+==== Aspects of the implementation relation ====
  
 When a user defined type implements another, there are several items When a user defined type implements another, there are several items
Line 59: Line 59:
 port list. As an illustration, consider: port list. As an illustration, consider:
  
-<code>+<code act>
 defproc type1 (bool a, b) { ... } defproc type1 (bool a, b) { ... }
 defproc type2 <: type1 (bool c) { ... } defproc type2 <: type1 (bool c) { ... }
Line 72: Line 72:
 the port list example above. the port list example above.
  
-<code>+<code act>
 template<pint N> template<pint N>
 defproc type1 (bool a, b) { ... } defproc type1 (bool a, b) { ... }
Line 82: Line 82:
 However, we can also define ''type2'' in the following manner: However, we can also define ''type2'' in the following manner:
  
-<code>+<code act>
 template<pint N> template<pint N>
 defproc type1 (bool a, b) { ... } defproc type1 (bool a, b) { ... }
Line 103: Line 103:
 as follows: as follows:
  
-<code>+<code act>
 type2<5> x; type2<5> x;
 // x.N, x.M are both accessible! // x.N, x.M are both accessible!
Line 113: Line 113:
 the instance the instance
  
-<code>+<code act>
 type2<5,7> x; type2<5,7> x;
 // x.M=5, x.N=7 // x.M=5, x.N=7
 </code> </code>
  
-would set ''N'' (the new template parameter) to ''5'', and +would set ''M'' (the new template parameter) to ''5'', and 
-''M'' (the parent, still definable parameter) to ''7''. Finally,+''N'' (the parent, still definable parameter) to ''7''. Finally,
 the following would be an error: the following would be an error:
  
-<code>+<code act>
 template<pint N> defproc type1 (bool a, b) { ... } template<pint N> defproc type1 (bool a, b) { ... }
 template<pint N> defproc type2 <: type1 (bool c) { ... } template<pint N> defproc type2 <: type1 (bool c) { ... }
 +</code>
 +<code>
 -[ERROR]-> Duplicate meta-parameter name in port list: `N' -[ERROR]-> Duplicate meta-parameter name in port list: `N'
            Conflict occurs due to parent type: type1            Conflict occurs due to parent type: type1
Line 134: Line 136:
 consider the following example:  consider the following example: 
  
-<code>+<code act>
 defproc buffer (e1of2? l, e1of2! r) defproc buffer (e1of2? l, e1of2! r)
 { {
Line 149: Line 151:
 define a specific implementation as follows: define a specific implementation as follows:
  
-<code>+<code act>
 defproc wchb <: buffer () defproc wchb <: buffer ()
 { {
Line 167: Line 169:
 specification for a buffer at the CHP level of abstraction would be: specification for a buffer at the CHP level of abstraction would be:
  
-<code>+<code act>
 defproc buffer (chan?(bool) l, chan!(bool) r) defproc buffer (chan?(bool) l, chan!(bool) r)
 { {
Line 191: Line 193:
 implementation of the original. The syntax for this is shown below: implementation of the original. The syntax for this is shown below:
  
-<code>+<code act>
 defproc wchb <: buffer() defproc wchb <: buffer()
 +{ e1of2 l, r; } // override block +{ e1of2 l, r; } // override block
Line 210: Line 212:
 only syntax permited is of the form within an override block is only syntax permited is of the form within an override block is
  
-<code>+<code act>
 +{ +{
     type list-of-ids;     type list-of-ids;
Line 243: Line 245:
 representation of the Boolean variable. representation of the Boolean variable.
  
 +=== Overriding conditional instances and templated types ===
  
 +An instance created in a type definition may be created only under certain circumstances. 
 +This can occur in templated types, where template parameters can affect the instances within the type.
 +The override block has the simple syntax shown above. However, to account for conditional instances,
 +the override block directives implicitly check if the instance exists before applying the override. (Note that
 +ACT does not permit different types for the same instance name under different conditions.)
  
 +When a type is being overridden by another, the new implementation may have additional template parameters.
 +The override syntax above requires the complete list of template parameters to be specified. Instead, we also
 +provide a single extension override syntax
  
-===== The ptype ===== +<code act> 
- ++{ 
-**XXX: this section not yet implemented** +    type<param1,param2,...,paramN>+ id  // single ID only 
- +    ... 
-The special ''ptype'' meta-parameter type is used to pass in types + }
-into a process definitionThese types can be used to build a process +
-using other processes as building blocksThe syntax for using a +
-''ptype'' is the following: +
- +
-<code> +
-ptype(foo) x;+
 </code> </code>
- +The ''+'' indicates that these are //extra// template parameter(s) that should be added to the existing ones that have already been specified for the instance ''id'' in the original type definition.
-This says that ''x'' is a variable that is a type, with the +
-constraint that ''x'' must satisfy the type signature specified by +
-''foo''. In other words, ''x'' is guaranteed to support all the +
-operations supported by type ''foo''.  +
- +
-''ptype'' parameters can also be used in templates. Consider the +
-following example: +
- +
-<code> +
-// A constructor for a datapath with W-bit ripple connections, and +
-// where each component has M inputs and one output +
- +
-// A skeleton +
-template<pint W, pint M> +
-defproc bitslice (e1of2? rin[W]; e1of2! rout[W];  +
-                  e1of2? in[M]; e1of2! out) { } +
- +
-// the constructor +
-template<pint N, pint M, pint W, ptype(bitslice<W,M>) t> +
-defproc build_dpath (e1of2? rin[W]; e1of2! rout[W];  +
-                     e1of2? in[M*N]; e1of2! out[N]) +
-+
-   t x[N]; +
- +
-   // ripple connections +
-   (;i:N-1: x[i].rout=x[i+1].rin); +
-   x[0].rin=rin; +
-   x[N-1].rout=rout;    +
- +
-   // i/o connections +
-   (;i:N: x[i].in[i*M..(i+1)*M-1] = in[i*M..(i+1)*M-1]; +
-          x[i].out=out[i] ) +
-+
- +
-// A one-bit adder +
-defproc onebit (e1of2? in[2], rin[1]; e1of2! out, rout[1]) { ... } +
- +
-defproc ripple_adder (e1of2? a[32], b[32], cin; e1of2! out[32], cout) +
-+
-    build_dpath<32,2,1,onebit> dp; +
- +
-    (; i : 32 : dp.in[2*i] = a[i]; dp.in[2*i+1] = b[i]); +
-    dp.out = out; +
-    dp.rin[0] = cin; +
-    dp.rout[0] = cout +
-+
-</code> +
- +
- +
- +
- +
- +