/**
	\file "env.hac"
	TODO: document/comment everything -- all definitions
		especially reset conventions
	TODO: CMOS implementability of production rules?
		cmos_source_ev, etc...
	Names: does 'bitbucket' make sense for general 1ofN?
		Just call it sink?
	$Id: env.hac,v 1.11 2008/06/27 00:01:40 fang Exp $
 */

import "channel.hac";
import "alternator.hac";

/**
	TODO: get rid of this and make it a relaxed parameter 
		possibly with default value.
		(requires relaxed parameters to work first.)
 */
pint EnvDelay = 100;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	unit cell for N state alternator
	TODO: consider making this CMOS implementable.
 */
template <pbool start>
defproc source_cell(bool l,le,s,se,r,re,_Reset)
  {
  bool x,y;
  s=r;
//  hse {*[[l]; le-; [~l]; le+; [se & re]; s+; [~se & ~re]; s-]}
  prs{
    [after=EnvDelay] _Reset & ~x & ~y & l -> le-
    [after=EnvDelay] _Reset &  ~y & ~le -> x+
    [after=EnvDelay] ~ _Reset | x & ~y & ~l -> le+
    [after=EnvDelay] _Reset & x & le -> y+
    [after=EnvDelay] _Reset & x & y & se & re -> s+
    [after=EnvDelay] ~_Reset | y & s -> x-
    [after=EnvDelay]  ~_Reset | ~x & y & ~se & ~re -> s-
    [after=EnvDelay] ~_Reset | ~x & ~s -> y-
    }
  }

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	initializes a token in the alternator
 */
defproc start_cell(bool l,le,r,re,_Reset)
  {
  bool x,y;
//  hse {*[[re]; r+; [~re]; r-; [l]; le-; [~l]; le+]}
  prs{
    [after=EnvDelay] _Reset & ~x & ~y & re -> r+
    [after=EnvDelay] _Reset & ~y & r -> x+
    [after=EnvDelay] ~_Reset | x & ~y & ~re -> r-
    [after=EnvDelay] _Reset & x & ~r -> y+
    [after=EnvDelay] _Reset & x & y & l -> le-
    [after=EnvDelay] ~_Reset | y & ~le -> x-
    [after=EnvDelay] ~_Reset | ~x & y & ~l -> le+
    [after=EnvDelay] ~_Reset | ~x & le -> y-
    }
  }

//-----------------------------------------------------------------------------
/**
	step through N values for an e1of(M) channel
 */
template <pint M><pint N, d[N]>
defproc source_e(e1of<M> rr; bool _Reset)
  {
  c1of<M> r;
  e1of<N> s;
  s.e=rr.e;
  bool l[N+1],le[N+1];
  source_cell<false> sc[N];
  (;i:0..N-1: sc[i](l[i],le[i],s.d[i],s.e,l[i+1],le[i+1],_Reset);)
  start_cell stc(l[N],le[N],l[0],le[0],_Reset);
  prs{
    (:i:N: [after=EnvDelay] s.d[i] -> r.d[d[i]]+ )
    (:i:M: [after=EnvDelay] (&:j:0..N-1: ~s.d[j] ) -> r.d[i]- ) 
    (:i:M: [after=EnvDelay] r.d[i] -> rr.d[i]+ )
    (:i:M: [after=EnvDelay] ~r.d[i] -> rr.d[i]- )
    }
  }

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	step through N values for an a1of(M) channel
 */
template <pint M><pint N, d[N]>
defproc source_a(a1of<M> rr; bool _Reset)
  {
  c1of<M> r;
  e1of<N> s;
  bool l[N+1],le[N+1];
  source_cell<false> sc[N];
  (;i:0..N-1: sc[i](l[i],le[i],s.d[i],s.e,l[i+1],le[i+1],_Reset);)
  start_cell stc(l[N],le[N],l[0],le[0],_Reset);
  prs{
    (:i:N: [after=EnvDelay] s.d[i] -> r.d[d[i]]+ )
    (:i:M: [after=EnvDelay] (&:j:0..N-1: ~s.d[j] ) -> r.d[i]- )
    (:i:M: [after=EnvDelay] r.d[i] -> rr.d[i]+ )
    (:i:M: [after=EnvDelay] ~r.d[i] -> rr.d[i]- )
    [after=EnvDelay] rr.a -> s.e-
    [after=EnvDelay] ~rr.a -> s.e+
    }
  }

//=============================================================================
// CMOS-implementable TOKEN SOURCES

/**
	Generalized channel source
	Implementation notes: no large shared dynamic logic nodes, 
		the only part that is O(N) is the fanout of R.e.  
	Note: this does not use any EnvDelay parameters.  
	Reset: R.e may be high or low on reset, 
		EXCEPT for N == 2, where R.e must be high (inactive).
	Tested: env-cmos-source-sink-e-0{1-4}.{hac,prsimrc}
	\param M is the number of rails of channel
	\param N is the number of values in sequence > 0
	\param D is the array of values to cycle through
 */
template <pint M><pint N, D[N]>
defproc cmos_source_e(e1of<M> R; bool _Reset, Reset) {
bool _o[M];
[ (N > 2) ->	// ring-counter implementation
bool _s[N], s[N];
// bool _se[N], se[N];
onehot_stage_init i0(R.e, _s[N-2], s[N-1], _s[0], s[0], _s[1], Reset);
onehot_stage i[1..N-1];
(;j:1..N-1:
	i[j](R.e, _s[(N+j-2)%N], s[j-1], _s[j], s[j], _s[(j+1)%N], _Reset);
)
[] N == 2 && (D[0] != D[N-1]) ->	// 2-way alternator implementation
c1of2 x, y;
_c1of2 _r;
bool o[M];
	// could fold rail-pull into alternator stage implementation... lazy
symmetric_alternator_stage a[2];
	a[0](R.e, x.d, y.d, _r.d[1], o, _Reset);
	a[1](R.e, {x.d[1], x.d[0]}, {y.d[1], y.d[0]}, _r.d[0],
		{o[1], o[0]}, _Reset);
]
// else single rail implementation
prs {
[(N > 2) ->	// ring-counter implementation
		// first one needs a reset
		// ~_Reset				-> _se[0]+
	(:j:M:	// for each rail
		~_Reset				-> _o[j]+
			// reset is only needed for nodes that never fire
		_o[j]				=> R.d[j]-	// output inv.
	(:r:N:	// for each value
		// all rails reset
	[j == D[r] ->
		// if rail-number matches value, then add rules
/**
		~R.e & ~s[r]			-> _se[r]+
		R.e & s[r]			-> _se[r]-
		// _se[r]				=> se[r]-
		_se[r] & s[(r+1)%N]		-> se[r]-
		~_se[r]				-> se[r]+
		Reset				-> se[r]-

		// ~se[r] & ~_s[(r+1)%N] & ~s[(r+2)%N]	-> _o[j]+
		~se[r] & ~s[(r+2)%N]		-> _o[j]+
		se[r] & s[(r+1)%N]		-> _o[j]-
**/
		// ewww... 4p, but single-fanout
		~R.e & ~s[r] & ~_s[(r+1)%N] & ~s[(r+2)%N]	-> _o[j]+
		 R.e &  s[r] &  s[(r+1)%N]			-> _o[j]-
	]
	)
	)
]
// TODO: rewrite using cascaded else-if construct
[ N == 2 && (D[0] != D[N-1]) ->	// 2-way alternator implementation
	// partially copied from alternator_source_1of2
	Reset					-> o[0]-
//	Reset					-> o[1]-      // not needed

	Reset					-> x.d[0]-
	~_Reset					-> x.d[1]+
	// the following two resets only needed for active-acknowledge on reset
	Reset					-> y.d[1]-
	~_Reset					-> y.d[0]+

	(:j:M:	// for each rail
		~_Reset				-> _o[j]+
			// reset is only needed for nodes that never fire
		_o[j]				=> R.d[j]-	// output inv.
	(:r:2:	// for each value
		// all rails reset
	[j == D[r] ->
		// be careful, in case same value is used both times!
		~R.e & ~o[r]			-> _o[j]+
		 R.e &  o[r]			-> _o[j]-
	]
	)
	)
]
// TODO: rewrite using cascaded else-if construct
[ N == 1 || (N == 2 && (D[0] == D[N-1])) ->	// single rail implementation
	(:j:M:	// for each rail
		~_Reset				-> _o[j]+
			// reset is only needed for nodes that never fire
		_o[j]				=> R.d[j]-	// output inv.
	)
		~R.e	 			-> _o[D[0]]+
		 R.e & _Reset			-> _o[D[0]]-
]
}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	CMOS-implementable a1ofN source.  
	\param M is the number of rails of channel
	\param N is the number of values in sequence
	\param D is the array of values to cycle through
 */
template <pint M><pint N, D[N]>
defproc cmos_source_a(a1of<M> R; bool _Reset, Reset) {
// being cheap...
e1of<M> r;
R.d = r.d;
prs {
	R.a					=> r.e-
}
cmos_source_e<M> s<N,D>(r, _Reset, Reset);
}

//-----------------------------------------------------------------------------
/**
	TODO: faster, pipelined cmos_sources, using onehot_counter
	and full or half-buffers.
 */
// defproc fast_cmos_source_e(...)

//=============================================================================
// TOKEN SINKS

/**
	bitbucket for e1of(N) channel
	This is now CMOS-implementable.  
	This bucket resets with the enable 'e' low.  
 */
template <pint N>
defproc bitbucket_e1of(e1of<N> l; bool _Reset)
  {
  bool __le,_le;
  prs{
    [after=EnvDelay] (|:i:0..N-1: l.d[i]) -> __le-
    [after=EnvDelay] (&:i:0..N-1: ~l.d[i]) -> __le+
    [after=EnvDelay] ~_Reset | ~__le -> _le+
    [after=EnvDelay] _Reset & __le -> _le-
    [after=EnvDelay] _le -> l.e-
    [after=EnvDelay] ~_le -> l.e+
    }
  }

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	bitbucket for a1of(N) channel
	This is now CMOS-implementable.  
	This bucket resets with the acknowledge 'a' high.  
 */
template <pint N>
defproc bitbucket_a1of(a1of<N> l; bool _Reset)
  {
  bool _la;
  prs{
    [after=EnvDelay] (|:i:0..N-1: l.d[i]) -> _la-
    [after=EnvDelay] (&:i:0..N-1: ~l.d[i]) -> _la+
    [after=EnvDelay] ~_Reset | ~_la -> l.a+
    [after=EnvDelay] _Reset & _la -> l.a-
    }
  }

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bitbucket for ev channels, just wrapper around e1of1 bucket.  
	The data rails may be ignored because they are assumed (and required)
	to be checked by the validity signal.  
 */
template <pint N>
defproc bitbucket_ev1of(ev1of<N> L; bool _Reset) {
e1of1 LL;
L.v = LL.d[0];
L.e = LL.e;
bitbucket_e1of<1> B(LL, _Reset);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bitbucket for av channels, just wrapper around a1of1 bucket.  
	The data rails may be ignored because they are assumed (and required)
	to be checked by the validity signal.  
 */
template <pint N>
defproc bitbucket_av1of(av1of<N> L; bool _Reset) {
a1of1 LL;
L.v = LL.d[0];
L.a = LL.a;
bitbucket_a1of<1> B(LL, _Reset);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bitbucket for en channels, just wrapper around e1of1 bucket.  
	The data rails may be ignored because they are assumed (and required)
	to be checked by the validity signal.  
 */
template <pint N>
defproc bitbucket_en1of(en1of<N> L; bool _Reset) {
e1of1 LL;
L.e = LL.e;
bitbucket_e1of<1> B(LL, _Reset);
prs {
	L.n			=> LL.d[0]-
}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bitbucket for an channels, just wrapper around a1of1 bucket.  
	The data rails may be ignored because they are assumed (and required)
	to be checked by the validity signal.  
 */
template <pint N>
defproc bitbucket_an1of(an1of<N> L; bool _Reset) {
a1of1 LL;
L.a = LL.a;
bitbucket_a1of<1> B(LL, _Reset);
prs {
	L.n			=> LL.d[0]-
}
}

//-----------------------------------------------------------------------------
/**
	bundled bitbucket for a M x e1of(N) channel
 */
template <pint N, M>
defproc bitbucket_Mxe1of(e1of<N> r[M-1]; bool _Reset)
  {
  e1of<N> s[0..M-1];
  bool se, _se;
  bitbucket_e1of<N> be[M-1];
  (;i:0..M-1: r[i].d=s[i].d; r[i].e=se;)
  (;i:0..M-1: be[i](s[i],_Reset);)
  prs{
    [after=EnvDelay] (&:i:0..M-1: ~s[i].e) -> _se+
    [after=EnvDelay] (&:i:0..M-1: s[i].e) -> _se-
	_se				=> se-
    }
  }

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	bundled bitbucket for a M x a1of(N) channel
 */
template <pint N, M>
defproc bitbucket_Mxa1of(a1of<N> r[M-1]; bool _Reset)
  {
  a1of<N> s[0..M-1];
  bool sa, _sa;
  bitbucket_a1of<N> ba[M-1];
  (;i:0..M-1: r[i].d=s[i].d; r[i].a=sa;)
  (;i:0..M-1: ba[i](s[i],_Reset);)
  prs{
    [after=EnvDelay] (&:i:0..M-1: s[i].a) -> _sa-
    [after=EnvDelay] (&:i:0..M-1: ~s[i].a) -> _sa+
	_sa				=> sa-
    }
  }

/***************** WRAPPERS FOR SPECIFIC 1of(N) SOURCES *******************/
// name aliases
typedef	source_e	source_e1of;
typedef	source_a	source_a1of;
typedef	cmos_source_e	cmos_source_e1of;
typedef	cmos_source_a	cmos_source_a1of;

template <><pint N, d[N]>
typedef source_e<1> source_e1of1;

template <><pint N, d[N]>
typedef source_a<1> source_a1of1;

template <><pint N, d[N]>
typedef cmos_source_e<1> cmos_source_e1of1;

template <><pint N, d[N]>
typedef cmos_source_a<1> cmos_source_a1of1;

template <><pint N, d[N]>
typedef source_e<2> source_e1of2;

template <><pint N, d[N]>
typedef source_a<2> source_a1of2;

template <><pint N, d[N]>
typedef cmos_source_e<2> cmos_source_e1of2;

template <><pint N, d[N]>
typedef cmos_source_a<2> cmos_source_a1of2;

template <><pint N, d[N]>
typedef source_e<3> source_e1of3;

template <><pint N, d[N]>
typedef source_a<3> source_a1of3;

template <><pint N, d[N]>
typedef cmos_source_e<3> cmos_source_e1of3;

template <><pint N, d[N]>
typedef cmos_source_a<3> cmos_source_a1of3;

template <><pint N, d[N]>
typedef source_e<4> source_e1of4;

template <><pint N, d[N]>
typedef source_a<4> source_a1of4;

template <><pint N, d[N]>
typedef cmos_source_e<4> cmos_source_e1of4;

template <><pint N, d[N]>
typedef cmos_source_a<4> cmos_source_a1of4;

template <><pint N, d[N]>
typedef source_e<5> source_e1of5;

template <><pint N, d[N]>
typedef source_a<5> source_a1of5;

template <><pint N, d[N]>
typedef cmos_source_e<5> cmos_source_e1of5;

template <><pint N, d[N]>
typedef cmos_source_a<5> cmos_source_a1of5;

template <><pint N, d[N]>
typedef source_e<6> source_e1of6;

template <><pint N, d[N]>
typedef source_a<6> source_a1of6;

template <><pint N, d[N]>
typedef cmos_source_e<6> cmos_source_e1of6;

template <><pint N, d[N]>
typedef cmos_source_a<6> cmos_source_a1of6;

template <><pint N, d[N]>
typedef source_e<7> source_e1of7;

template <><pint N, d[N]>
typedef source_a<7> source_a1of7;

template <><pint N, d[N]>
typedef cmos_source_e<7> cmos_source_e1of7;

template <><pint N, d[N]>
typedef cmos_source_a<7> cmos_source_a1of7;

template <><pint N, d[N]>
typedef source_e<8> source_e1of8;

template <><pint N, d[N]>
typedef source_a<8> source_a1of8;

template <><pint N, d[N]>
typedef cmos_source_e<8> cmos_source_e1of8;

template <><pint N, d[N]>
typedef cmos_source_a<8> cmos_source_a1of8;


/***************** WRAPPERS FOR SPECIFIC 1of(N) BITBUCKETS *******************/

typedef	bitbucket_e1of<1>	bitbucket_e1of1;
typedef	bitbucket_e1of<2>	bitbucket_e1of2;
typedef	bitbucket_e1of<3>	bitbucket_e1of3;
typedef	bitbucket_e1of<4>	bitbucket_e1of4;
typedef	bitbucket_e1of<5>	bitbucket_e1of5;
typedef	bitbucket_e1of<6>	bitbucket_e1of6;
typedef	bitbucket_e1of<7>	bitbucket_e1of7;
typedef	bitbucket_e1of<8>	bitbucket_e1of8;

typedef	bitbucket_a1of<1>	bitbucket_a1of1;
typedef	bitbucket_a1of<2>	bitbucket_a1of2;
typedef	bitbucket_a1of<3>	bitbucket_a1of3;
typedef	bitbucket_a1of<4>	bitbucket_a1of4;
typedef	bitbucket_a1of<5>	bitbucket_a1of5;
typedef	bitbucket_a1of<6>	bitbucket_a1of6;
typedef	bitbucket_a1of<7>	bitbucket_a1of7;
typedef	bitbucket_a1of<8>	bitbucket_a1of8;

typedef	bitbucket_ev1of<1>	bitbucket_ev1of1;
typedef	bitbucket_ev1of<2>	bitbucket_ev1of2;
typedef	bitbucket_ev1of<3>	bitbucket_ev1of3;
typedef	bitbucket_ev1of<4>	bitbucket_ev1of4;
typedef	bitbucket_ev1of<5>	bitbucket_ev1of5;
typedef	bitbucket_ev1of<6>	bitbucket_ev1of6;
typedef	bitbucket_ev1of<7>	bitbucket_ev1of7;
typedef	bitbucket_ev1of<8>	bitbucket_ev1of8;

typedef	bitbucket_av1of<1>	bitbucket_av1of1;
typedef	bitbucket_av1of<2>	bitbucket_av1of2;
typedef	bitbucket_av1of<3>	bitbucket_av1of3;
typedef	bitbucket_av1of<4>	bitbucket_av1of4;
typedef	bitbucket_av1of<5>	bitbucket_av1of5;
typedef	bitbucket_av1of<6>	bitbucket_av1of6;
typedef	bitbucket_av1of<7>	bitbucket_av1of7;
typedef	bitbucket_av1of<8>	bitbucket_av1of8;

typedef	bitbucket_en1of<1>	bitbucket_en1of1;
typedef	bitbucket_en1of<2>	bitbucket_en1of2;
typedef	bitbucket_en1of<3>	bitbucket_en1of3;
typedef	bitbucket_en1of<4>	bitbucket_en1of4;
typedef	bitbucket_en1of<5>	bitbucket_en1of5;
typedef	bitbucket_en1of<6>	bitbucket_en1of6;
typedef	bitbucket_en1of<7>	bitbucket_en1of7;
typedef	bitbucket_en1of<8>	bitbucket_en1of8;

typedef	bitbucket_an1of<1>	bitbucket_an1of1;
typedef	bitbucket_an1of<2>	bitbucket_an1of2;
typedef	bitbucket_an1of<3>	bitbucket_an1of3;
typedef	bitbucket_an1of<4>	bitbucket_an1of4;
typedef	bitbucket_an1of<5>	bitbucket_an1of5;
typedef	bitbucket_an1of<6>	bitbucket_an1of6;
typedef	bitbucket_an1of<7>	bitbucket_an1of7;
typedef	bitbucket_an1of<8>	bitbucket_an1of8;


/***************** BUNDLED ACKNOWLEDGE BITBUCKETS ***************/

template <pint M>
typedef bitbucket_Mxe1of<2,M>	bitbucket_Mxe1of2;

template <pint M>
typedef bitbucket_Mxa1of<2,M>	bitbucket_Mxa1of2;

template <pint M>
typedef bitbucket_Mxe1of<4,M>	bitbucket_Mxe1of4;

template <pint M>
typedef bitbucket_Mxa1of<4,M>	bitbucket_Mxa1of4;


/******************** INACTIVE RESET BITBUCKETS ******************/

/**
	TODO: explain naming convention.  
	Q: what does inactive mean?
	This is CMOS-implementable.  
	Does it imply 'e' is high on reset? (my guess)
 */
template <pint N>
defproc inactive_reset_bitbucket_e1of(e1of<N> r; bool _Reset)
  {
  bool __re,_re;
  prs{
    [after=EnvDelay] _Reset & (|:i:N: r.d[i] ) -> __re- 
    [after=EnvDelay] ~_Reset | (&:i:N: ~r.d[i] ) -> __re+ 
    [after=EnvDelay] __re -> _re- 
    [after=EnvDelay] ~__re -> _re+
    [after=EnvDelay] _re -> r.e-
    [after=EnvDelay] ~_re -> r.e+ 
    }
  }

typedef	inactive_reset_bitbucket_e1of<1>	inactive_reset_bitbucket_e1of1;
typedef	inactive_reset_bitbucket_e1of<2>	inactive_reset_bitbucket_e1of2;
typedef	inactive_reset_bitbucket_e1of<3>	inactive_reset_bitbucket_e1of3;
typedef	inactive_reset_bitbucket_e1of<4>	inactive_reset_bitbucket_e1of4;
typedef	inactive_reset_bitbucket_e1of<5>	inactive_reset_bitbucket_e1of5;
typedef	inactive_reset_bitbucket_e1of<6>	inactive_reset_bitbucket_e1of6;
typedef	inactive_reset_bitbucket_e1of<7>	inactive_reset_bitbucket_e1of7;
typedef	inactive_reset_bitbucket_e1of<8>	inactive_reset_bitbucket_e1of8;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	TODO: explain naming convention.  
	This is CMOS-implementable.  
	Does it imply 'a' is low on reset? (my guess)
 */
template <pint N>
defproc inactive_reset_bitbucket_a1of(a1of<N> r; bool _Reset)
  {
  bool _ra;
  prs{
    [after=EnvDelay] (|:i:N: r.d[i] ) & _Reset -> _ra- 
    [after=EnvDelay] (&:i:N: ~r.d[i] ) | ~_Reset -> _ra+ 
    [after=EnvDelay] _ra -> r.a-
    [after=EnvDelay] ~_ra -> r.a+ 
    }
  }

typedef	inactive_reset_bitbucket_a1of<1>	inactive_reset_bitbucket_a1of1;
typedef	inactive_reset_bitbucket_a1of<2>	inactive_reset_bitbucket_a1of2;
typedef	inactive_reset_bitbucket_a1of<3>	inactive_reset_bitbucket_a1of3;
typedef	inactive_reset_bitbucket_a1of<4>	inactive_reset_bitbucket_a1of4;
typedef	inactive_reset_bitbucket_a1of<5>	inactive_reset_bitbucket_a1of5;
typedef	inactive_reset_bitbucket_a1of<6>	inactive_reset_bitbucket_a1of6;
typedef	inactive_reset_bitbucket_a1of<7>	inactive_reset_bitbucket_a1of7;
typedef	inactive_reset_bitbucket_a1of<8>	inactive_reset_bitbucket_a1of8;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bucket for ev channel, where e is inactive (high) during reset.  
	Just a wrapper around e1of1 bucket.  
 */
template <pint N>
defproc inactive_reset_bitbucket_ev1of(ev1of<N> R; bool _Reset) {
e1of1 RR;
R.v = RR.d[0];
R.e = RR.e;
inactive_reset_bitbucket_e1of<1> B(RR, _Reset);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bucket for av channel, where a is inactive (low) during reset.  
	Just a wrapper around a1of1 bucket.  
 */
template <pint N>
defproc inactive_reset_bitbucket_av1of(av1of<N> R; bool _Reset) {
a1of1 RR;
R.v = RR.d[0];
R.a = RR.a;
inactive_reset_bitbucket_a1of<1> B(RR, _Reset);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bucket for en channel, where e is inactive (high) during reset.  
	Just a wrapper around e1of1 bucket.  
 */
template <pint N>
defproc inactive_reset_bitbucket_en1of(en1of<N> R; bool _Reset) {
e1of1 RR;
R.e = RR.e;
inactive_reset_bitbucket_e1of<1> B(RR, _Reset);
prs {
	R.n			=> RR.d[0]-
}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Bucket for an channel, where a is inactive (low) during reset.  
	Just a wrapper around a1of1 bucket.  
 */
template <pint N>
defproc inactive_reset_bitbucket_an1of(an1of<N> R; bool _Reset) {
a1of1 RR;
R.a = RR.a;
inactive_reset_bitbucket_a1of<1> B(RR, _Reset);
prs {
	R.n			=> RR.d[0]-
}
}

//=============================================================================
/****************** MULTI-CHANNEL SOURCES *******************************/
/* Below are the old CAST versions of multi-channel sources
   They are commented out until relaxed templates are ready in HACKT.
define source_Mxe1of4(int M,N; int[N] d)(e1of4[M] r)
  {
  int[N,M] f;
  int[M] pow;
  pow[0]=1; <i:1..M-1: pow[i]=pow[i-1]*4;>
  <i:M: <j:N: f[j,i]=(d[j]/pow[i])%4;> source_e1of4(N,f[0..N-1,i])(r[i]);>
  }

define source_Mxa1of4(int M,N; int[N] d)(a1of4[M] r)
  {
  int[N,M] f;
  int[M] pow;
  pow[0]=1; <i:1..M-1: pow[i]=pow[i-1]*4;>
  <i:M: <j:N: f[j,i]=(d[j]/pow[i])%4;> source_a1of4(N,f[0..N-1,i])(r[i]);>
  }

*/
