dnl $Id: l2c_arith.m4 406 2010-04-27 14:41:17Z eb771 $
dnl --------------------------------------
dnl Arithmetic routines

include(l2c_util.m4)

dnl A full adder
dnl                   ${pfx}_ci
dnl                       |
dnl                       |
dnl                    +-----+
dnl       ${pfx}_a  ---|     |
dnl                    |     |
dnl                    |     |
dnl       ${pfx}_b  ---|     |--- ${pfx}_s
dnl                    |     |
dnl                    +-----+
dnl                       |
dnl                       |
dnl                   ${pfx}_co 
dnl
dnl DEF_ADDER(prefix)
define(`DEF_ADDER',`
	pushdef(`A', ``$1'_a')
	pushdef(`B', ``$1'_b')
	pushdef(`CI', ``$1'_ci')
	pushdef(`CO', ``$1'_co')
	pushdef(`S', ``$1'_s')

# l2c_arith::DEF_ADDER, prefix = [$1]
	def A B CI CO S

	popdef(`A', `B', `CI', `CO', `S')
')

dnl ADDER(prefix)
define(`ADDER',`
	pushdef(`A', ``$1'_a')
	pushdef(`B', ``$1'_b')
	pushdef(`CI', ``$1'_ci')
	pushdef(`CO', ``$1'_co')
	pushdef(`S', ``$1'_s')

# l2c_arith::ADDER, prefix = [$1]
	(
		(S <=> (A @ B) @ CI) .
		(CO <=> (A . B) + (CI . (A + B)))
	)

	popdef(`A', `B', `CI', `CO', `S')
')

dnl Define pins on a Multi bit adder
dnl DEF_MULTI_ADDER(prefix, num_adders)
define(`DEF_MULTI_ADDER',`
# l2c_arith::DEF_MULTI_ADDER, prefix = [$1], num = [$2]
	FOR(`x', `0', `eval($2-1)',`DEF_ADDER(`$1'x)ifelse(x,eval($2-1),,`;')')
')

dnl Define a multi_adder a with connected carry-in -> carry outs
dnl MULTI_ADDER(prefix, num_adders)
define(`MULTI_ADDER',`
# l2c_arith::MULTI_ADDER, prefix = [$1], num = [$2]
	(
	FOR(`x', `0', `($2-1)', `ADDER(`$1'x)ifelse(x,eval($2-1),,` .')')
	) .
	(
	FOR(`y', `0', `eval($2-2)', `(`$1'y`_co <=> $1'eval(y+1)`_ci)'ifelse(y,eval($2-2),,` .')')
	)
')
