<?
require_once "lib/utils.php";
require_once "lib/mux.php";
?>
# counter modulo 2
# inc   when i=1
# reset when r=1
# cf p.129

s,o = cm2m(i,r){
	s = Z((i^s)&(~r))
	o = s&i
}

# idem but when c=1, the counter use the value of v at next clock cycle
# and output next value n (as if c=0)

s,o,n = cm2c(i,r,c,v){
	n = i^s
	s = Z((n | c) & (v | ~c) & ~r)
	o = s&i
}
<? 
/**
 * This function creates a $n bits counter
 * s[n], ..., s[0], o = counter$n(i,r)
 **/
function counter($n){ 
	if(isAlreadyCreated("counter$n")){
		return;
	}
?>
<?=listV("s",0,$n)?>, c[<?=$n?>] = counter<?=$n?>(c[0], r){

<? for($i=0;$i<$n;$i++){ ?>
	inst s[<?=$i?>], c[<?=$i+1?>] = cm2m(c[<?=$i?>],r)
<? } ?>

}
<?
}
?>
<?
/**
 * This function creates a $n bits counter
 * which can be charged (when c=1) with value v
 * and output next value
 * s[n], ..., s[0], o, next[n], ..., next[0]  = counterC$n(i,c,v[n],...,v[0])
 **/
function counterC($n){ 
	if(isAlreadyCreated("counterC$n")){
		return;
	}
?>
<?=listV("s",0,$n)?>, c[<?=$n?>], <?=listV("next",0,16)?> = counterC<?=$n?>(c[0], c, <?=listV("v",0,$n)?>){

<? for($i=0;$i<$n;$i++){ ?>
	inst s[<?=$i?>], c[<?=$i+1?>], next[<?=$i?>] = cm2c(c[<?=$i?>],0,c,v[<?=$i?>])
<? } ?>

}
<?
}
?>

<?
/**
 * This function create a count modulo $m
 * s[n], ..., s[0], o = counterMod$m(i,r)
 **/
function counterMod($m){
	if(isAlreadyCreated("counterMod$m")){
		return;
	}
	$n = ceil(log($m-1,2));	// Compute the number of bits
?>
<?
counter($n);
?>

<?=listV("s",0,$n)?>, o = counterMod<?=$m?>(i, r){

	inst <?=listV("s",0,$n)?>, c[<?=$n?>] = counter<?=$n?>(i, rb)
	o = <? for($i=0;$i<$n-1;$i++){ if(($m-1) & (1<<$i)){ ?>s[<?=$i?>] & <? } } ?>s[<?=$n-1?>] & i
	rb = r | o
}
<?
}
?>

<?
/**
 * This function create a count modulo m with $n bits
 * Charge possible like counterC
 * s[n], ..., s[0], o = counterModV$n(i,c,v[n],...,v[0],m[n],...,m[0])
 **/
function counterModV($n){
	if(isAlreadyCreated("counterModV$n")){
		return;
	}
?>
<?
counter($n);
?>

<?=listV("s",0,$n)?>, o = counterModV<?=$n?>(c[0], c, <?=listV("v",0,$n)?>, <?=listV("m",0,$n)?>){

	
<? for($i=0;$i<$n;$i++){ ?>
	inst s[<?=$i?>], c[<?=$i+1?>], next[<?=$i?>] = cm2c(c[<?=$i?>],rb,c,v[<?=$i?>])
<? } ?>

	# when modulo is not 0
	oN0 = <? for($i=0;$i<$n;$i++){ ?> ~(next[<?=$i?>] ^ m[<?=$i?>]) & <? } ?> c[0] 
	# when modulo is 0
	o0 = c[<?=$n?>]

	# =1 when modulo is not 0
	neq0 = <?=listV("m",0,$n,"|")?>

	inst o = mux(o0,oN0,neq0)
	rb = o
}
<?
}
?>
