Rethinking Computer Science Part 7: A Language of Computation

A single coherent language that encompasses the expression of computation from high level abstract design through automatic elaboration to the ultimate netlist of primitive behaviors that enlivens the design. A language that characterizes computation as association relations among differentnesses, as patterns of changing differentness relative to structures of persistent differentness as “all of” relations and “one of” relations forming spontaneously behaving, self regulating networks of interacting differentness.

Expressing differentness
A locus is a persistence different from all other loci that can assert one at a time of two or more different values. The asserted value changes in relation to the persistence of the locus. There is no change without reference to persistence and there is no persistence without referring change.

A locus occupies a place of differentness similar to a particle occupying a physical space that no other particle can occupy. Think of a molecule locus that can assert many different chemical values, a wire locus that can assert high or low voltage values, a protein locus that can assert innumerable folded shape values.

An instance of a thousand differentnesses can be expressed by a locus asserting a thousand different values. Loci asserting fewer values can cooperatively associate to express a greater range of differentness than any one individually with combined values forming a differentness name. Three cooperatively associated loci each asserting 20 different values can form 1140 unique combinations of three values which is sufficient to name a thousand differentnesses. If the cooperative association relation is linearly ordered then each locus is different not only by virtue of its locusness but additionally different by virtue of its relative place in the structure of association relations. With this additional differentness the three loci asserting 12 differences each can form 1320 unique permutations.

If all three loci assert the same value set allowing all three loci to simultaneously assert the same value then three linearly associated loci asserting ten values each can form 1000 unique names. If the values are assigned ordinal and cardinal significance (interval equality) then the names acquire ordinal and cardinal significance and the place/value number system emerges.

With 6 values per locus 4 linearly associated loci are required to name 1000 differentnesses. With 2 values per locus 10 linearly associated loci are required to name 1000 differentnesses.

Two values are required to represent an instance of differentness. A locus asserting one value is a non sequitur. But the two values can be assigned differing expressional duties.

Traditionally, the two values represent an instance of binary data. A persistence that perpetually asserts one of two data values and that can never not assert a data value, cannot assert its own boundary of validity and invalidity and must relegate its coordination behavior to some other form of expression. With pure association representation one value represents a “data” condition while the other value represents a “not data” condition, i.e. emptiness of value, which enables the expression of differentness itself to directly manage its own coordination behavior creating a phase change in the representation of differentness.

Conventional representation of a computation is typically locked into a particular encoding because persistence and its values are represented differently, a transient voltage on a persistent wire, a transient position of a persistent cogwheel, transient values of a persistent variable. With pure association expression both the transience relations and the persistence relations are expressed in terms of association relationship and the boundary between the two becomes fluid. Pure association expression presents a background of “not data” out of which arises transitions to “data”. With the single “data” condition the mutually exclusive values of a persitence are represented as a group of “one of” related associations only one of which will transition from  “not data” to “data”. The “one of” related group as a whole with one association at “data” represents a persistence, a locus, asserting a value. There is no formality determining the size of a mutually exclusive group of associations and no particular need for a consistent boundary between persistence and transience.

Declaring Differentness
A persistence is named, each value of a persistence is named and each differentness can be characterized as a structure of  “one of” and “all of” relations among names. The “one  of” relation expresses the mutual exclusivity of value. It means exactly one of. Not one or more of. The “all of” relation expresses mutual inclusivity of persistence. It means all of. Each relation is represented with a unique delimiting syntax.

[A, B, C, D] means all of A, B, C and D.

{A, B, C, D} means one of A, B, C or D.

A path declaration names an instance of differentness, its hierarchical composition structure, how the differentness is referenced at all levels of composition, the transition behavior of the compositional elements and its completeness of transition criterion. The declaration

path B/[25:0]/{0, 1, 2}

specifies a differentness named B composed of 26 “all of “related persistence names each containing three “one of” related value names. Assuming B to be a trinary number, then:

B/4/0 references value 0 of digit 4 of B

B/5 references digit 5 of B

B references B

The composition names of a differentness are hierarchically encompassed and isolated. All of the differentnesses within B are isolated within the differentness of B allowing names to be used within B that are also used within other differentnesses. The declaration

path C/[7:0]/{1,0};     // expands to  path C/[7,6,5,4,3,2,1,0]/{1,0};

declares an eight bit binary number. The reference C/5/0 and the reference B/5/0 are different By virtue of the differentness of B and C. Within B, B/4/0 is different from B/5/0 by virtue of the differentness of 4 and 5.

An instance of differentness is asserted with one “one of” related association name transitioning from “not data” to “data” within each “all of” related association name. Given that [25:0] specifies ordinal association, the 26 ordered persistence names of B, each with 3 “one of” values, can form 326 different patterns of persistence-name/value-name, each being a unique name of a differentness, making B a composite persistence, a locus, that can assert one at a time of 326 different values. B completely asserts an instance of differentness value when for each “all of” related association name one of its “one of” related association names transitions to “data”, i.e. every digit asserts one “data”. B is empty, not asserting an instance of differentness, when all of its values have transitioned to “not data”.

How does a persistence know which value to assert?
Assuming directionalized persistences/loci as presented in part 2, a persistence asserts its output value in response to the combination of values presented to its input by one or more persistences associated to its input. The asserted value of the persistence is in turn presented to the input one or more further persistences influencing the values they assert and so on in a directed network of progressive influence. The values presented to a persistence cross associate to form all possible interaction names. Each receiving persistence searches to recognize the formed name and match it to a value interaction rule which specifies the output value for the persistence.

With pure association each persistence and its values are represented with association relations and a value is asserted with its association transitioning from the background condition of “not data” to “data”. With only one “data” condition the only discriminable differentness is quantity of “data”s present at each name forming association. Only one cross associated interaction name will receive a sufficient number of “data”s to form a complete interaction name which sufficiency can be represented with a threshold behavior. The primitive threshold behaviors for a persistent place of association are “all of” the presenting associations transition to “data” or “one of” the presenting associations transitions to “data”.

The recognition of a formed interaction name will cause an output value to transition to “data” as specified by a set of value interaction rules which are represented with interaction statements. An interaction statement specifies the relations among presented inputs that will cause an output value to transition to “data”. An arrow in the interaction statement below shows the flow of influence.

[A, B, C] -> Z;

Means, if “all of” A and B and C are at “data”, the name ABC is formed, then Z will transition to “data”.

{A, B, C} -> Z;

Means, if “one of” A or B or C is at “data”, the name A or B or C is formed, then Z will transition to “data”.

Primitive threshold behaviors are represented graphically with the symbols shown below. The number in the graphic indicates the “data” threshold.

Z transitions to “data” when “all of” the inputs transition to “data”.

Z transitions to “data” when “one of “ the inputs transitions to “data”.

An interaction is expressed by specifying each interacting differentnesses with a path declaration and then specifying, with interaction statements, the cross associated interaction names and the mapping of each to an output value. Interaction structure is orthogonal to path structure.

The expression below specifies two 2 value differentnesses interacting and specifying a third 2 value differentness. The interaction statements specify how the values of A and B interact and influence the value of C.

path A/{1,0};
path B/{1,0};
path C/{1,0};
{[A/0, B/0], [A/1, B/1]} -> C/0;
{[A/1, B/0], [A/0, B/1]} -> C/1;

The expression maps directly to the network of primitive threshold behaviors below which implements a dual-rail XOR.

The interaction statements flowing to C and their derived network is a persistence with output value C. The persistence has an input boundary of 2 mutually inclusive names each with 2 mutually exclusive values which cross associate to form interaction names. The rank of 2of2 behaviors is the search to recognize the formed interaction name. From an initial all “not data” condition only one of the behaviors will be presented with two “data”s matching its threshold and transitioning its output to “data”. which, through the rank of 1of2 behaviors, will transition the appropriate value of C to “data”. The expression and its network represents four value interaction rules, the search to recognize the formed interaction name and the output of the specified value.

A more general example shows a two value differentness combined with a three value differentness to influence a four value differentness.

path A/{1,0};
path B/{2,1,0};
path C/{3,2,1,0};
[A/0, B/0] -> C/0;
{[A/1, B/0], [A/0, B/1]} -> C/1;
{[A/1, B/1], [A/0, B/2]} -> C/2;
[A/1, B/2] -> C/3;

Again the specification maps directly to  a network of primitive threshold behaviors. And again, the interaction statements represent a persistence with output value C, its value transform rules and its search for which the network below is an active realization. From an initial all “not data” condition only one threshold 2 behavior will meet its “data” threshold and transition its output to “data” which will cause the transition of only one value of C to transition to “data”.

Once a network has transitioned from the completely “not data” condition to a condition of representing “data” the network must be returned to the completely “not data” condition to perform a next computation.

The Completeness Criterion
Every computation begins in a completely “not data” condition. Interaction occurs with associations transitioning  to “data” asserting specific differentnesses within the network. Every differentness has a completeness of representation which is defined by its path declaration and which can be recognized from the pattern of “data”s in the network. Completeness of representation is preserved as transitions to “data” flow through the network such that when transitions to “data” at the output of the network are complete it means that the presented inputs are complete, that the resolution has propagated through the network and that the asserted output is the correct resolution of the presented input – that the network computation is done. This is the completeness criterion.

The completeness of the output implies the completeness of the input and the completeness of the computation.

This output completeness can be recognized and used to regulate the input to the network.

The Next Computation
The transition to “not data” has a universal completeness behavior which is that “all of “ the network associations are asserting “not data”. In other words all the associations that had transition to “data” are transitioned back to “not data”. Recognition of completely “not data” is a second threshold behavior embodied in the primitive threshold behaviors. The primitives illustrated in Figure 5 transition their output to “data” only when the “data” completeness threshold is matched or to “not data” only when the completely “not data” threshold is matched. Otherwise they maintain their asserted output.

The same primitives that behave in relation to the completeness of “data” transition also behave in relation to the completeness of “not data” transition such that when transitions to “not data” at the output of the network are complete it means that the presented inputs are completely “not data”, that the reset to “not data” has propagated through the network and that the network is completely reset and ready for a next presentation of “data”. The same network of primitive behaviors fulfills the completeness criterion for transition to “not data” as well as for the transition to “data”.

The Oscillation
For both cases the output boundary completeness detection is fed back to the input boundary, transitioned to the opposite condition (inverted) and presented to the input in an “all of” relation to allow transitions to the opposite condition to flow through the input boundary into the network. The feedback closes a cycle which with the condition inversion and the input enabling forms a cyclic network spontaneously striving to alternately transition between “data” completeness and completely “not data” referred to as an oscillation.

Example with the output completeness and feedback enable flow:

path A/{1,0};
path B/{2,1,0};
path M/{1,0};
path N/{2,1,0};
path C/{3,2,1,0};
path C.COMP, AB.ENABLE;  // names either asserted with “data” or not
[AB.ENABLE , A/0] -> M/0;
[AB.ENABLE , A/1] -> M/1;
[AB.ENABLE , B/0] -> N/0;
[AB.ENABLE , B/1] -> N/1;
[AB.ENABLE , B/2] -> N/2;
[M/0, N/0] -> C/0;
{[M/1, N/0], [M/0, N/1]} -> C/1;
{[M/1, N/1], [M/0, N/2]} -> C/2;
[M/1, N/2] -> C/3;
C.COMP <- {C/0, C/1, C/2, C/3};

The backward flow is represented with leftward flowing arrow <- and is called closure because it closes an oscillation. C.COMP represents the completeness of the output, “data” completeness with one rail of C at “data”, “not data” completeness with all rails of C at “not data”. A ~ indicates transition to the opposite condition (inversion) resulting in AB.ENABLE which is presented to the input with an “all of” relation and enables the next transitions to “not data” with “data” completeness and to “data” with “not data” completeness, to flow through the input.

Closure flows are specified in two stages, before the inversion and after the inversion. Closure flows before the inversion (completenesses) are specified with the suffix .COMP. Closure flows after the inversion (enables) are specified with the suffix .ENABLE.

The above expression maps to the network below.

Black paths are forward computation flow. Orange paths are backward closure flow.

With the “data” completeness of the output C.COMP will transition to “data” and AB.ENABLE will transition to “not data” which is associated to the threshold 2 behaviors with the inputs. When the inputs transition to “not data” “not data” transitions will flow through the network and the completeness of “not data” at the output will be recognized by the 1of4 behavior. C.COMP will transition to “not data”, AB.ENABLE will transition to “data” allowing the input transitions to “data” into the network. When the output is “data” completeness AB.ENABLE will transition to “not data” allowing “not data” into the network and so on.

The network is initialized to “not data” before the first input “data” is presented. The inversion is forced (initialized) to “not data” setting AB.ENABLE to “not data” which allows an initial input presentation of “not data” to propagate through the network to the inversion setting the entire network to “not data” including C.COMP. The force is released, AB.ENABLE transitions to “data” allowing the first “data presentation into the network.

The closed cycle with opposite condition transition (inversion) forms a spontaneously oscillating network that will continue oscillating as long as the input transitions monotonically between “data” completeness and completely “not data”.

The Link
Oscillations can be linked by placing the output completeness of a sending oscillation after the input regulation of a receiving oscillation. The receiving oscillation will not get its enabled input until after the sending oscillation presents it. The sending oscillation will not get closure on its sent input until until after the receiving oscillation has enabled and accepted it. While being individually spontaneously alive, the oscillations, mutually regulate each other’s behavior.

path A/{1,0};
path (B, N)/{2,1,0};
path M/{1,0};
path (C, P)/{3,2,1,0};
[AB.ENABLE , A/0] -> M/0;
[AB.ENABLE , A/1] -> M/1;
A.COMP <- {A/0, A/1};
[AB.ENABLE , B/0] -> N/0;
[AB.ENABLE , B/1] -> N/1;
[AB.ENABLE , B/2] -> N/2;
B.COMP <- {B/0, B/1, B/2};
[M/0, N/0] -> P/0;
{[M/1, N/0], [M/0, N/1]} -> P/1;
{[M/1, N/1], [M/0, N/2]} -> P/2;
[M/1, N/2] -> P/3;
[C.ENABLE, P/0] -> C/0;
[C.ENABLE, P/1] -> C/1;
[C.ENABLE, P/2] -> C/2;
[C.ENABLE, P/3] -> C/3;
C.COMP <- {C/0, C/1, C/2, C/3};
C.ENABLE <- ~?.COMP;  //  ? represents the name(s) of the destination(s) of C

Maps to the network below.

The oscillation link
A flow computation is a network of linked oscillations. Each link is a completeness and coordination boundary that links two or more oscillations and that demarcates the forward computation flow and the backward closure flow of each individual oscillation. The link is a standard composition structure and deserves a dedicated representation.

While the output of a link might fanout to several accepting links the direct output of a link is a single differentness and is a point of identity in the network. So a link, its completeness and its enabling will be determined by the path declaration of the output differentness of the link.

The linkname of the example is Y. While completenesses may be combined before the inversion and enables may be combined after the inversion the immediate completeness of a link is designated linkname.COMP and the ultimate enable of a link is designated linkname.ENABLE. Below is a 2 bit dual rail link.

path (X,Y)/[1,0]/{1,0};
path acpt.COMP, Y.COMP, Y.ENABLE;
[X, Y.ENABLE] -> Y;  // the forward flow
Y.COMP <- Y/#;  // # specifies completeness from hierarchical level of #
Y.ENABLE <- ~?.COMP;  // ~ specifies an inverter that is initialized to “not data”

The inversion initializes to “not data” to allow an initial presentation of “not data” to flow through the link.

The keyword link is a macro that expands in relation to the referenced path. The above link expression is specified by:

path (X,Y)/[31:0]/{1,0};
link X -> Y;  // expands in relation to the path declaration – a 32 bit dual rail link.

From here on, a network boundary will be formally represented as a half oscillation, a forward computation flow and its associated closure flow. With the link convention, typically, only the forward computation flow need be specified. The completeness, closure flow and enabling is implied and can be automatically derived and filled in.

A Network of Oscillations
Networks of oscillations are composed by linking half oscillations to form complete oscillations. The following combinational expression converts a quaternary differentness B into a binary differentness X and back into a quaternary differentness D.

path (B, D)/{3,2,1,0};
path (X)/[1,0]/{1,0};
{B/0, B/2} -> X/0/0;
{B/1, B/3} -> X/0/1;
{B/0, B/1} -> X/1/0;
{B/3, B/2} -> X/1/1;
[X/1/0, X/0/0] -> D/0;
[X/1/0, X/0/1] -> D/1;
[X/1/1, X/0/0] -> D/2;
[X/1/1, X/0/1] -> D/3;

maps to the network below.

A combinational network is assumed to have an associated closure flow.

A Pipeline Network
The combinational network is turned into a pipeline network of linked oscillations by linking X and D and linking B to an input A.

path (A, B, C, D)/{3,2,1,0};
path X/[1,0]/{1,0};
link A -> B;
{B/0, B/2} -> X/0/0;
{B/1, B/3} -> X/0/1;
{B/0, B/1} -> X/1/0;
{B/3, B/2} -> X/1/1;
link X;
[X/1/0, X/0/0] -> D/0;
[X/1/0, X/0/1] -> D/1;
[X/1/1, X/0/0] -> D/2;
[X/1/1, X/0/1] -> D/3;
link D;

Notice that only the link statements are added to the specification. Each link assumes the the path declaration, of the boundary it is linking. The detailed structure of the link and the relations of the closure flow between links are derived from the path declarations and the interaction statements. With expansion of the link statements the specification maps to the network below.

To make the insertion of the link combinationally transparent the output X of the combinational network becomes the output of the link and the path between the output of the combinational network and the input of the link becomes an intermediate differentness assigned the name with the same path declaration as X.

The pipeline initializes with all inversions forced to “not data” and “not data” presented to the input. The “not data flows through all the links to initialize the entire pipeline to ”not data”. The initialization is released, all inversions transition to “data”. With an input presentation of “data” a wavefront of “data” propagates through the network followed by an input presentation and wavefront of “not data”, followed by a wavefront of “data” and so on.

The pipeline is composed of two complete oscillations and is bounded by half oscillations.

Composing Networks
A network of linked oscillations is bounded by half oscillations. The statements, network name ( xtrnlnames ) body endnetwork, encompass a network of isolated name space with a window to externally visible half oscillation names within the parentheses which form the boundaries of the network.  A boundary is a locus of completeness and coordination behavior, a persistent place of association which encompasses a mutually exclusive set of formed names of which only one name at a time can completely form and flow through the boundary.

Networks are composed by connecting output half oscillations to input half oscillations forming a complete oscillation which becomes an internal oscillation of the newly composed network. Half oscillations that are not composed form the boundaries of the new network.

While input always flows eventually to output, as composition proceeds, the input and output boundaries grow farther apart and less directly associated with the boundaries becoming more and more complex. The boundaries must begin being represented with individual boundary statements rather than jumbled into a single interface list. The boundary statement specifies encompassed half oscillations and the completeness relations for the formable names at the reference level of the boundary. The statement boundary (B -> ); specifies an input boundary encompassing the single differentness B which must be complete for the boundary to flow. The statement boundary ( -> Z); specifies an output boundary encompassing the single differentness Z which must be complete for the boundary to flow.

The pipeline above can be specified in terms of composed networks as well as in terms of inserted links. The combinational network is severed at X and two networks are defined each with an output link and a reference name. The pipeline is then specified with reference to the networks shown below.

A network named QuadToDual with externally visible names A and Z.

network QuadToDual (
path A/{3,2,1,0};
path Z/[1,0]/{1,0};
boundary (A -> );  // input boundary
{A/0, A/2} -> Z/0/0;
{A/1, A/3} -> Z/0/1;
{A/0, A/1} -> Z/1/0;
{A/3, A/2} -> Z/1/1;
link Z;
boundary ( -> Z);  // output boundary

A network named DualToQuad with externally visible names A and Z.

network DualToQuad (
path A/[1,0]/{1,0};
path Z/{3,2,1,0};  )
boundary (A -> );  // input boundary
[A/1/0, A/0/0] -> Z/0;
[A/1/0, A/0/1] -> Z/1;
[A/1/1, A/0/0] -> Z/2;
[A/1/1, A/0/1] -> Z/3;
link Z;
boundary ( -> Z);  // output boundary

The two networks are composed by associating the boundaries. The A and Z of each network is made unique (different) by including the name of the network and an instance name in the reference. This can be represented with syntactic structure association or with name correspondence association.

Syntax structure association
path (B, D), /{3,2,1,0};
path X/[1,0]/{1,0};
QuadToDual 1 (B -> X)
DualToQuad 1 (X -> D )

associates B, X and D with As and Zs of the referenced networks by syntactic structure association.

Name correspondence association
path (B, D), /{3,2,1,0};
B -> QuadToDual/1/A;  //  name correspondence
QuadToDual/1/Z -> DualToQuad/1/A;
DualToQuad/1/Z -> D;

associates the As and Zs of the referenced networks by direct name correspondence association: no X.

The composition
The specification for the composed network is in terms of name correspondence association.

network pipeB ( path (A, D)/{3,2,1,0}; )  //  The external names
boundary (A -> );  // referenced as pipeB/instance/A
path B/{3,2,1,0};
path X/[1,0]/{1,0};
boundary(A -> );
link ( A -> B)
B -> QuadToDual/1/A;  //  name correspondence
QuadToDual/1/Z -> DualToQuad/1/A;
DualToQuad/1/Z -> D;
boundary( -> D);

Composing a bigger pipeline
The network pipeB can be composed into a longer pipe in terms of syntax structure association or in terms of name correspondence association.

Boundary reference with name correspondence association between boundaries.

pipeB/1/D -> pipeB/2/A;
pipeB/2/D -> pipeB/3/A;

composes an 8 oscillation pipeline between input name pipeB/1/A and output name pipeB/3/D. The instance names have to kept track of but there is no appeal to a referential encompassing network. The interaction statements are external to both networks but not hierarchically superior to either.

Syntax structure association between networks within an encompassing network.

network (
path (W, Z)/{3,2,1,0};
path (X, Y)/{3,2,1,0};
pipeB (W -> X);
pipeB (X -> Y);
pipeB (Y -> Z);

also composes an 8 oscillation pipeline between input name W and output name Z. The associations are in terms of pathnames of an encompassing network.

A network ring
A pipeline network that feeds back on itself forms a ring which remembers previous wavefronts. A ring must have a data wavefront initialized in it. In this case The link G is initialized to the value name 0. This is specified in the path declaration of G which determines the configuration of path initializations and initialized and uninitialized inversions. The threshold 2D means that the path is initialized to “data”, 2N initializes to “not data”. It is assumed that at initialization B will present “not data”. The specification:

network bitriquatring(
path B/{1,0};
path Y/{3,2,1,0};
path (C, D)/{3,2,1,0};
path G/{3,2,1,0}(0);
path (A, E)/{2,1,0};
path F/{1,0};
// forward computation flow
boundary( -> B);
link B -> F;
[E/0, F/0] -> C/0;
{[E/1, F/0], [E/0, F/1]} -> C/1;
{[E/2, F/0], [E/1, F/1]} -> C/2;
[E/2, F/1] -> C/3;
link C -> D;
link D -> Y;
link D -> G;
{G/0, G/1} -> A/0;
G/2 -> A/1;
G/3 -> A/2;
link A -> E;
boundary( -> Y);

Maps to the network below.

The example ring always contains a single data wavefront. It will behave as a pipeline segment with memory and is alive as long as the input and output continue alternating between “data”completeness and completely “not data”.

Rings can be composed into a pipeline of rings or a ring of rings. Two or more rings may share one or more oscillations. Multiple rings may share multiple oscillations in complex ways such as with an LFSR. Rings can be structured into an addressable memory.

Example: Binary full adder

network binaryfulladd(
path (A, B, CI, S, CO)/{1,0}; )
boundary([A, B, CI] -> );
{[A/0, B/0, CI/0], [A/1, B/1, CI/0], [A/0, B/1, CI/1], [A/1, B/0, CI/1]} -> S/0;
{[A/0, B/1, CI/0], [A/1, B/0, CI/0], [A/0, B/0, CI/1], [A/1, B/1, CI/1]} -> S/1;
{[A/0, B/0, CI/0], [A/0, B/1, CI/0], [A/1, B/0, CI/0], [A/0, B/0, CI/1]} -> C/0;
{[A/1, B/1, CI/0], [A/0, B/1, CI/1], [A/1, B/0, CI/1], [A/1, B/1, CI/1]} -> C/1;
boundary(  -> [S, CO]);

Example: 32 bit adder
Interaction reference over a range of names.

[XYZ/4:7] -> T;
expands to
[XYZ/4, XYZ/5, XYZ/6, XYZ/7] -> T;

func(XYZ/[4:6] -> T/[2:4]);
expands to
func(XYZ/4 -> T/2;
func(XYZ/5 -> T/3;
func(XYZ/6 -> T/4;

network binaryadd32(
path (inA, inB, outS)/[31:0]/{1,0};
path (inCI, outCO)/{1,0}; )

boundary ([inA, inB, inCI] -> );
path carry/[32:0]/{1,0};
inCI -> carry/0;
binaryfulladd([inA/[0:31], inB/[0:31], carry/[0:31]] -> [outS/[0:31], carry/[1:32]]);
carry/32 -> outCO;
boundary ( -> [outS, outCO]);

The first three instantiations binaryfulladd are
binaryfulladd([inA/0, inB/0, carry/0] -> [outS/0, carry/1]);
binaryfulladd([inA/1, inB/1, carry/1] -> [outS/1, carry/2]);
binaryfulladd([inA/2, inB/2, carry/2] -> [outS/2, carry/3]);

Example: Counter
A ring network with output only. S is linked through the output boundary half oscillation. The next count is delivered with each transition of  the closure for S to “data”.

network counter32(
path S/[31:0]/{1,0}; )
path A/[31:0]/{1,0};
path B/[31:0]/{1,0}(0);   // initialize B to value name 0
path carry/[31:0]/{1,0};
A/0/0 -> S/0/1;    // add one
A/0/0 -> carry/0/0
A/0/1 -> S/0/0;
A/0/1 -> carry/0/1
binaryhalfadd(inA/1:30, carry/1:30 -> S/1:30, carry/2:31);
carry/31 -> S/31;
link S;
link S -> B;  // straight through buffer link
link B -> A;  // three oscillation pipeline ring
boundary( -> S);

network binaryhalfadd(
path (A, CI, S, CO)/{1,0}; )
boundary([A, CI] -> );
[A/0, CI/0] -> [S/0, CO/0];
[A/0, CI/1] -> [S/1, CO/0];
[A/1, CI/0] -> [S/1, CO/0];
[A/1, CI/1] -> [S/0, CO/1];
boundary(  -> [ S, CO]);

Example: ALU
An ALU example illustrates steering a common input through the different functions of the ALU and modifying each function with specific instruction values using factored reference.

A value name of one differentness is “all of” associated with a higher level name of another differentness and consequently the entire structure of names encompassed by the higher level name is enabled by the value name.

path (A, B, C)/[31:0]/{31:0};
path STEER/{toB, toC};
[A, steer/toB] -> B;  // the value toB enables the entire structure of  A to B
[A, steer/toC] -> C;  // the value toC enables the entire structure of  A to C

Factored reference and its expansion by distributing the factor
[rs1in, instin/{ADD, ADDI}] -> alpha;
expands to
[rs1in, {instin/ADD, instin/ADDI}] -> alpha;

TheALU network has externally visible names instin, r1in, rs2in, immin and ALUout. The input boundary, encompassing several half oscillations, specifies all the possible names formed from the values of instin and rs1in, rs2in and immin. The output boundary is just ALUout.

network ALU(
path (rs1in, rs2in, immin, ALUout)/[31:0]/{31:0}; )
boundary( instin{[/{ADD, SUB}, rs1in, rs2in],
[/ADDI, rs1in, immin],
[/{XOR, OR, AND}, rs1in, rs2in],
[/{XORI, ORI, ANDI}, rs1in, immin],
[/{SLL, SRL, SRA}, rs1in, rs2in],
[/{SLLI, SRLI, SRAI}, rs1in, immin]}
  -> );
path (alpha, beta, zeta)/[31:0]/{1:0};
path addop/{ADD, SUB};
[rs1in, instin/{ADD, ADDI}] -> alpha;
{[rs2in, instin/ADD], [immin, instin/ADDI]} -> beta;
instin/{ADD, ADDI} -> addop/ADD;
instin/SUB -> addop/SUB;
adder(alpha, beta, addop -> zeta);
path (logicA, logicB, logicC)/[31:0]/{1,0};
path logicop/{XOR, OR, AND};
[rs1in, instin/{XOR, OR, AND, XORI, ORI, ANDI}] -> logicA;
{[rs2in, instin/{XOR, OR, AND}], [immin, instin/{XORI, ORI, ANDI}]} -> logicB;
instin/{XOR, XORI} -> logicop/XOR;
instin/{OR, ORI} -> logicop/OR;
instin/{AND, ANDI} -> logicop/AND;
logic(logicA, logicB, logicop -> logicC);
path (shiftA, shiftamt, shiftZ)/[31:0]/{1,0};
path shiftop/{LL, RL, RA};
[rs1in, instin/{SLL, SRL, SRA, SLLI, SRLI}] -> shiftA;
{[rs2in, instin/{SLL, SRL, SRA}], [immin, instin/{SLLI, SRLI}]} -> shiftamt;
instin/{SLL, SLLI} -> shiftop/LL;
instin/{SRL, SRLI} -> shiftop/RL;
instin/SRA -> shiftop/RA;
logic(shiftA, shiftamt, shiftop -> shiftC);
// ALU output
{zeta, logicC, shiftC} -> ALUout;
link ALUout;
boundary( -> ALUout);

Example: Decoder Segment
The following segment decodes the ALUI instructions and their immediate value.

A reference range over a list of values
A reference range associates with a list of values to reference a series of values.

[inst/6:2/(0, 0, 1, 0, 0)] -> aluimma;
expands to
[inst/(6, 5, 4, 3, 2)/(0, 0, 1, 0, 0)] -> aluimma;
expands to
[inst/6/0, inst/5/0, inst/4/1, inst/3/0, inst/2/0] -> aluimma;

If “all of” the referenced differentnesses transition to “data” then aluimma will transition to “data”.

Decoder segment
path inst[31:0]/{1,0};
path aluimma;
/////// ALU immediate instruction decodes ///////////////////
[inst/6:2/(0, 0, 1, 0, 0)] -> aluimma;
[aluimma, inst/14:12/(0, 0, 0)] -> ALU2op/ADDI;
[aluimma, inst/14:12/(0, 1, 0)] -> ALU2op/SLTI;
[aluimma, inst/14:12/(0, 1, 1)] -> ALU2op/SLTIU;
[aluimma, inst/14:12/(1, 0, 0)] -> ALU2op/XORI;
[aluimma, inst/14:12/(1, 1, 0)] -> ALU2op/ORI;
[aluimma, inst/14:12/(1, 1, 1)] -> ALU2op/ANDI;
[aluimma, inst/14:12/(0, 0, 1), inst/31:25/(0, 0, 0, 0, 0, 0, 0)] -> ALU2op/SLLI;
[aluimma, inst/14:12/(1, 0, 1), inst/31:25/(0, 0, 0, 0, 0, 0, 0)] -> ALU2op/SRLI;
[aluimma, inst/14:12/(1, 0, 1), inst/31:25/(0, 1, 0, 0, 0, 0, 0)] -> ALU2op/SRAI;

path enableALUimmA, enableALUimmB;
path (ALUimmA, ALUimmB)/[31:0]/{1,0};
// ALU immediate enables
ALU2op/{SLLI, SRLI, SRAI} -> enableALUimmB;
// ALU immediate decodes
[enableALUimmA, inst/31] -> ALUimmA/31:12; // sign extend
[enableALUimmA, inst/31:20] -> ALUimmA/11:0;
enableALUimmB -> ALUimmB/31:5/0; // zero extend
[enableALUimmB, inst/24:20] -> ALUimmB/4:0;

The decoder has a very simple input boundary
boundary (inst -> );

But a very complex output boundary different for eachc instruction class.
boundary (operation{ 
[/ALUIop/{ADDI, SLTI SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI}, rs1, rd, PCcontrol/next,


Example: Program Counter
The program counter has a more complex input boundary than the ALU with more conditionality of name formation. It also has two separately declared output boundaries. Initially, only the computation flow is specified as shown in Figure 13. The language processor will derive and fill in the completenesses and the closure flow.

network PC (
path PCcontrolin/{next, branch, JAL, JALR, AUIPC};
path immin/[31:0]/{1:0};
path rs1in/[31:0]/{1:0};
path condin{TRUE, FALSE};
path newPC/[31:0]/{1:0};
path returnPC/[31:0]/{1:0};
boundary (PCcontrol{
[/branch, PCimm, cond],
[/JAL, PCimm],
[/JALR, PCimm, rs1],
[/AUIPC, PCimm]
} ->  );

path D/[31:0]/{1:0}(/31:0/0); // initialize the 0 rail for all 32 digits to data
path curPC/[31:0]/{1:0};
// specify ring in terms of links –
link D/31:0;
link curPC/31:0;
link suminc/31:0;
link newPC/31:0;
// non ring links
link returnPC/31:0;
link sumadd/31:0;
// /31:0 specifies the closure granularity for the link in this case digitwise
// link sumadd would specify fullword completeness and closure

D -> curPC
/// The incrementer /////////////////////
path (carryincr, suminc)/[31:0]/{1:0};
curPC/1:0 -> suminc/1:0; // pass low order 2 bits
halfadd1(curPC/2 -> suminc/2, carryincr/3); // constant cayyin 1 to bit 2
halfadd(curPC/30:3, carryincr/30:3 -> suminc/30:3, carryincr/31:4); // bits 3 to 30 halfsumA(curPC/31, carryincr/31 -> suminc/31); // no carryout
/// the ripple adder /////////////////////
path (carryadd, sumadd)/[31:0]/{1:0};
halfadd([{[curPC/0, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/0, PCcontrolin/JALR]}, immin/0] -> sumadd/0, carryadd/1); // constant carryin 0
fulladd({[curPC/30:1, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/30:1, PCcontrolin/JALR]}, immin/30:1}], carryadd/1:30 -> sumadd/1:30, carryadd/2:31);   // digits 1-30
fullsum({[curPC/31, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/31, PCcontrolin/{JALR]}, immin/31], carryadd/31 -> sumadd/31); // last digit
/// steer to newPC and returnPC and to D /////////////////////
{[suminc, {PCcontrolin/{next, AUIPC}, condin/FALSE}], [sumadd, {PCcontrolin/{JAL, JALR}, condin/TRUE}]} -> newPC/;
{[suminc, PCcontrolin/{JAL, JALR}], [summadd, PCcontrolin/AUIPC]} -> returnPC;
newPC -> D;
boundary ( -> newPC);
boundary ( -> returnPC);

Maps to the computation flow network below.

Example: Program Counter Expanded
The design source specifies just the computation flow from which the language processor derives the completeness conditions, the closure flow and the link enables which are all presented in the same language simply by expanding the language specification. The final result is a fully expanded specification of the computation in the design language. The designer and the language processor speak the same language at all stages of design and implementation.

In the example the derived and expanded specifications added by the language processor are shown in red.

network PC (
// the closure part of each boundary half oscillation is in attached parentheses
path PCcontrolin/{next, branch, JAL, JALR, AUIPC}(PCcontrolin.COMP);
path immin/[31:0]/{1:0}(sumadd.COMP/[31:0]);
path rs1in/[31:0]/{1:0}(rs1in.COMP/[31:0]);
path condin{TRUE, FALSE}(condin.COMP);
path newPC/[31:0]/{1:0}(newPCdest.COMP/31:0,);
path returnPC/[31:0]/{1:0}(returnPCdest.COMP/31:0);
boundary (PCcontrolin{
[/branch, immin, condin],
[/JAL, immin],
[/JALR, immin, rs1in],
[/AUIPC, immin]
} ->  );

path D/[31:0]/{1:0}(/31:0/0); // initialize the 0 rail for all 32 digits to data
path curPC/[31:0]/{1:0};
// specify ring in terms of links –

//  link D/31:0;  expansion
path (D.COMP, D.ENABLE)/[31:0];
D.ENABLE/31:0 <- ~ curPC.COMP/31:0 ;
[newPC/31:0, D.ENABLE/31:0] -> D/31:0;
D.COMP/31:0 <- D/31:0/#];

//  link curPC/31:0   expansion
path (curPC.COMP, curPCall.COMP, curPC.ENABLE)/[31:0];
curPCall.COMP/31:0 <- [suminc.COMP/31:0
, {sumadd.COMP/31:0, PCcontrolin/{next, JALR}}]

curPC.ENABLE/31:0  <- ~ curPCall.COMP/31:0;
[D/31:0, curPC.ENABLE/31:0] -> curPC/31:0;
curPC.COMP/31:0 <- curPC/31:0/#;

//  link suminc/31:0   expansion
path (suminc.LINK, suminc.COMP, sumincall.COMP, suminc.ENABLE)/[31:0];
sumincall.COMP/31:0 <- [newPC.COMP/31:0, {returnPC.COMP/31:0, PCcontrolin/{next, branch, AUIPC}}];

suminc.ENABLE/31:0 <- ~ sumincall.COMP/31:0;
// the suminc flow below is changed to suminc.LINK
[suminc.LINK//31:0, suminc.ENABLE/31:0] -> suminc/31:0;
suminc.COMP/31:0 <- suminc/31:0/#;

//  link newPC/31:0;   expansion
path (newPC.LINK, newPC.COMP, newPCall.COMP, newPC.ENABLE)/[31:0];
newPCall.COMP/31:0 <- [newPCdest.COMP/31:0, D.COMP/31:0];

newPC.ENABLE/31:0 <- ~ newPCall.COMP/31:0;
// the newPC flow below is changed to newPC.LINK
[newPC.LINK//31:0, newPC.ENABLE/31:0] -> newPC/31:0;

newPC.COMP/31:0 <- newPC/31:0/#;

// non ring links
//  link returnPC/31:0;  expansion
path (returnPC.LINK, returnPC.COMP, returnPC.ENABLE)/[31:0];
returnPC.ENABLE/31:0 <- ~ returnPCdest.COMP/31:0;
// the returnPC flow below is changed to returnPC.LINK
[returnPC.LINK//31:0, returnPC.ENABLE/31:0] -> returnPC/31:0;
returnPC.COMP/31:0 <- returnPC/31:0/#;

//  link sumadd/31:0;  expansion
path (sumadd.LINK, sumadd.COMP, sumaddall.COMP, sumadd.ENABLE)/[31:0];
sumaddall.COMP/31:0 <- {[newPC.COMP/31:0, PCcontrolin/{branch, JAL, JALR}], [returnPC.COMP/31:0, PCcontrolin/AUIPC]};
sumadd.ENABLE/31:0 <- ~ sumaddall.COMP/31:0;
// the sumadd flow below is changed to sumadd.LINK
[sumadd.LINK//31:0, sumadd.ENABLE/31:0] -> sumadd/31:0;
sumadd.COMP/31:0 <- sumadd/31:0/#;

/// The incrementer /////////////////////

path (carryincr, suminc)/[31:0]/{1:0};
curPC/1:0 -> suminc.LINK/1:0; // pass low order 2 bits
halfadd1(curPC/2 -> suminc.LINK/2, carryincr/3); // constant carryin 1 to bit 2
halfadd(curPC/30:3, carryincr/30:3 -> suminc.LINK/30:3, carryincr/31:4); // bits 3 to 30 halfsumA(curPC/31, carryincr/31 -> suminc.LINK/31); // no carryout
/// the ripple adder /////////////////////
path (carryadd, sumadd)/[31:0]/{1:0};
halfadd([{[curPC/0, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/0, PCcontrolin/JALR]}, immin/0] -> sumadd.LINK/0, carryadd/1); // constant carryin 0
fulladd({[curPC/30:1, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/30:1, PCcontrolin/JALR]}, immin/30:1}], carryadd/1:30 -> sumadd.LINK/1:30, carryadd/2:31);  // digits 1-30
fullsum({[curPC/31, PCcontrolin/{branch, JAL, AUIPC}], [rs1in/31, PCcontrolin/{JALR]}, immin/31], carryadd/31 -> sumadd.LINK/31);  // digit 31
/// steer to newPC and returnPC and to D

{[suminc/31:0, {PCcontrolin/{next, AUIPC}, condin/FALSE}], [sumadd/31:0, {PCcontrolin/{JAL, JALR}, condin/TRUE}]} -> newPC.LINK/31:0;
{[suminc, PCcontrolin/{JAL, JALR}], [summadd, PCcontrolin/AUIPC]} -> returnPC.LINK;
newPC -> D;

// need fullword completeness to close with PCcontrolin and condin
PCcontrolin.COMP <- [newPC/#, {returnPC/#, PCcontrolin/{next, branch}}];
rs1in.COMP/31:0 <- [sumadd.COMP, PCcontrolin/JALR];
condin.COMP <- [newPC/#, PCcontrolin/branch];

boundary ( -> newPC);
boundary ( -> returnPC);

The expanded network can now be reduced to a network of relations with four or fewer inputs. There are 24  relation classes of “all of” and “one of” relations with four or fewer inputs. Each relation class is enlivened as a dual threshold behavior The reduced network becomes an network of dual threshold behaviors enlivening the design network as a whole.  The network below is the network derived from the PC specification.

The 24  relation classes is the Null Convention Logic function library. Null Convention Logic turns out to be not so much a coherent logic as it is a convenient level of granularity of the language. The language can be mapped to a network of two input relations, but four input relations makes a smaller network. There are 24 classes of four or fewer input relations. There are 92 classes of five input relations so four input relations is a sweet spot for implementation generality and convenience. However, a small selection of five or greater input relations could be convenient for efficient implementation of completeness behaviors for instance. Threshold function classification can be found in Muroga, Saburo “Threshold Logic and its Applications” Wiley Interscience, 1971, AppendixQ&A

The differentnesses of the network can be mapped in to a memory and the computation realized one interaction at a time with a sequence of interaction such that the input to every interaction is generated as output before it is used as input. The final state of the memory contains the result of the computation.

Leave a Reply