Skip to content

Volatile State

Julian Kemmerer edited this page May 30, 2022 · 2 revisions

volatile

Below is one 'lie' I could make up about volatile static local/global behavior, you could do all sorts of things...


In C, a volatile variable is one whose state can be changed by something other than the currently running code. In PipelineC it specifically means that the stateful variables associated with a function change to having a zero value for some >=0 number of iterations. During this time writes to the variable are invalid and cause malfunctions / incorrect behavior. After some >=0 number of iterations the real values of the variables are available for reading. Writes to the variables in that iteration can be read back as needed during that iteration. The values written to variables will show up again, and again, in cycles of some >=0 number of iterations. If no valid value is cycling through around during those iterations then you can write to the volatile during any iteration and begin the cycles again.

The number of invalid iterations in this cycle increases based on the complexity of the computation done in the volatile stateful function. Thus, the more complicated the volatile function the less often it can read/modify/write it's stateful variables.

So volatile stateful functions are like regular stateful functions except that they do not limit the pipeline operating frequency but instead increase latency/decrease throughput.

That sounds complicated. But most of the time it just means keeping some 'valid' indicator around and only doing stuff to volatiles when that == 1.

// Accumulating into a 128 bit stateful variable would be slow if not pipelined
// Allow pipelining by using volatiles
volatile uint128_t sum;
volatile uint1_t valid = 1; // Read only, volatile behavior changes value

// Return value indicating the accumulated sum 
// and if an increment occurred during this iteration.
// The logic calling main would be in charge of supplying a
// new 'increment' value after main returns 'did_accumulate=1'
typedef struct result_t
{
    uint128_t accumulated_sum;
    uint1_t did_accumulate;
} result_t;

result_t main(uint128_t increment)
{
    result rv;
    // By default we dont know if volatile sum is valid
    rv.accumulated_sum = 0;
    // Assume we will not accumulate
    rv.did_accumulate = 0;
    // Only increment volatile variable if volatiles are valid
    if(valid)
    {
	sum = sum + increment; // Addition will be pipelined
	rv.accumulated_sum = sum; // Return the result
	rv.did_accumulate = 1;
    }
    return rv;
}

What hardware does that actually implement? This implements a pipelined adder followed by a mux driven by the valid indicator, and registers for the volatile stateful variables. I am essentially forcing you to include a register "clock enable" around for the delay of your pipelined logic.