/**
	\file "logic.hac"
	Standard and common logic gates.  
	To consider: size/delayed versions?
	non-CMOS logic? rather not.
	Directive to inline instances of these definitions?
	Convention: when inputs are commutative and associative, 
		then bundle them into an array.  
	Nomenclature:
		cfb: explicit combinational feeedback (for state-holding)
	$Id: logic.hac,v 1.5 2008/06/27 00:01:40 fang Exp $
 */

namespace std {
namespace logic {
//=============================================================================
// COMBINATIONAL LOGIC
/**
	Your basic inverter.  
	\param i input
	\param o output
 */
export
defproc	inv(bool i, o) {
prs {
	i			=> o-
}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	NAND gate.
	\param N number of inputs
	\param i the inputs
	\param i nand result
 */
export
template <pint N>
defproc	nand(bool i[N], o) {
prs {
	(&:j:N:	i[j] )		=> o-
}
}

typedef	nand<2>			nand2;
typedef	nand<3>			nand3;
typedef	nand<4>			nand4;
typedef	nand<5>			nand5;
typedef	nand<6>			nand6;
typedef	nand<7>			nand7;
typedef	nand<8>			nand8;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	NOR gate.
	\param N number of inputs
	\param i the inputs
	\param i nor result
 */
export
template <pint N>
defproc	nor(bool i[N], o) {
prs {
	(|:j:N:	i[j] )		=> o-
}
}

typedef	nor<2>			nor2;
typedef	nor<3>			nor3;
typedef	nor<4>			nor4;
typedef	nor<5>			nor5;
typedef	nor<6>			nor6;
typedef	nor<7>			nor7;
typedef	nor<8>			nor8;

//=============================================================================
// STATE-HOLDING LOGIC

/**
	Generalized inverting C-element.  
	\param D number of pull-downs in series.  
	\param U number of pull-ups in series.  
	\param id inputs.
	\param iu inputs.
	\param o output.
	NOTE: id not necessarily aliased to iu!
 */
export
template <pint D, U>
defproc	gceleminv(bool id[D], iu[U], o) {
prs {
	(&:j:D:	id[j] )		-> o-
	(&:j:U:	~iu[j] )	-> o+
}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Symmetric inverting C-element.  
	No resets.
	\param N number of inputs
	\param i inputs
	\param o output, completion result
 */
export
template <pint N>
defproc celeminv(bool i[N], o) {
//	gceleminv<N, N> c(i, i, o);	// equivalent
prs {
	(&:j:N:	i[j] )		-> o-
	(&:j:N:	~i[j] )		-> o+
}
}

typedef	celeminv<2>		celeminv2;
typedef	celeminv<3>		celeminv3;
typedef	celeminv<4>		celeminv4;
typedef	celeminv<5>		celeminv5;
typedef	celeminv<6>		celeminv6;
typedef	celeminv<7>		celeminv7;
typedef	celeminv<8>		celeminv8;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Symmetric inverting C-element, with explicit combinational 
	feedback using internal inverse node.  
	No resets.
	\param N number of inputs
	\param i inputs
	\param o output, completion result
 */
export
template <pint N>
defproc celeminv_cfb(bool i[N], o) {
	bool o_;
prs {
	(&:j:N:	i[j] )		-> o-
	(&:j:N:	~i[j] )		-> o+
	o			=> o_-
	~o_ & (|:j:N:	~i[j] )	-> o+
	 o_ & (|:j:N:	 i[j] )	-> o-
}
}

typedef	celeminv_cfb<2>		celeminv2_cfb;
typedef	celeminv_cfb<3>		celeminv3_cfb;
typedef	celeminv_cfb<4>		celeminv4_cfb;
typedef	celeminv_cfb<5>		celeminv5_cfb;
typedef	celeminv_cfb<6>		celeminv6_cfb;
typedef	celeminv_cfb<7>		celeminv7_cfb;
typedef	celeminv_cfb<8>		celeminv8_cfb;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Symmetric non-inverting C-element.  
	No resets.
	\param N number of inputs
	\param i inputs
	\param o output, completion result
 */
export
template <pint N>
defproc celem(bool i[N], o) {
	bool _o;
prs {
	(&:j:N:	i[j] )		-> _o-
	(&:j:N:	~i[j] )		-> _o+
	_o			=> o-
}
}

typedef	celem<2>		celem2;
typedef	celem<3>		celem3;
typedef	celem<4>		celem4;
typedef	celem<5>		celem5;
typedef	celem<6>		celem6;
typedef	celem<7>		celem7;
typedef	celem<8>		celem8;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
	Symmetric non-inverting C-element, with explicit combinational 
	feedback using internal inverse node.  
	No resets.
	Q: export internal node as port?
	\param N number of inputs
	\param i inputs
	\param o output, completion result
 */
export
template <pint N>
defproc celem_cfb(bool i[N], o) {
	bool _o;
prs {
	(&:j:N:	i[j] )		-> _o-
	(&:j:N:	~i[j] )		-> _o+
	_o			=> o-
	~o & (|:j:N:	~i[j] )	-> _o+
	 o & (|:j:N:	 i[j] )	-> _o-
}
}

typedef	celem_cfb<2>		celem2_cfb;
typedef	celem_cfb<3>		celem3_cfb;
typedef	celem_cfb<4>		celem4_cfb;
typedef	celem_cfb<5>		celem5_cfb;
typedef	celem_cfb<6>		celem6_cfb;
typedef	celem_cfb<7>		celem7_cfb;
typedef	celem_cfb<8>		celem8_cfb;

//-----------------------------------------------------------------------------
// RESETTABLE STATE-HOLDING LOGIC

//=============================================================================
// INTERFACE: define celem and celeminv as interfaces, 
//	same with standard logic functions.  
// IMPLEMENTATIONS: defined as implementations of interfaces
//=============================================================================
// TODO: recursive definitions of celem_tree and celeminv_tree

//=============================================================================
}	// end namespace logic
}	// end namespace std

