#include "ace.h" | |
#include "bdd.h" | |
#include "cube.h" | |
//#include "vecPtr.h" | |
//#include "cudd.h" | |
void ace_bdd_get_literals(Abc_Ntk_t * ntk, st_table ** lit_st_table, | |
Vec_Ptr_t ** literals) { | |
Abc_Obj_t * obj; | |
int i; | |
*literals = Vec_PtrAlloc(0); | |
*lit_st_table = st_init_table(st_ptrcmp, st_ptrhash); | |
Abc_NtkForEachObj(ntk, obj, i) | |
{ | |
if (Abc_ObjIsCi(obj)) { | |
st_insert(*lit_st_table, (char*) obj, | |
(char*) Vec_PtrSize(*literals)); | |
Vec_PtrPush(*literals, obj); | |
} | |
} | |
} | |
int check_pi_status(Abc_Obj_t * obj) { | |
int i; | |
Abc_Obj_t * fanin; | |
Abc_ObjForEachFanin(obj, fanin, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
if (info->status == ACE_UNDEF) { | |
return 0; | |
} | |
} | |
return 1; | |
} | |
void ace_bdd_count_paths(DdManager * mgr, DdNode * bdd, int * num_one_paths, | |
int * num_zero_paths) { | |
DdNode * then_bdd; | |
DdNode * else_bdd; | |
if (bdd == Cudd_ReadLogicZero(mgr)) { | |
*num_zero_paths = *num_zero_paths + 1; | |
return; | |
} else if (bdd == Cudd_ReadOne(mgr)) { | |
*num_one_paths = *num_one_paths + 1; | |
return; | |
} | |
then_bdd = Cudd_T(bdd); | |
ace_bdd_count_paths(mgr, then_bdd, num_one_paths, num_zero_paths); | |
//bdd_free(then_bdd); | |
else_bdd = Cudd_E(bdd); | |
ace_bdd_count_paths(mgr, else_bdd, num_one_paths, num_zero_paths); | |
//bdd_free(else_bdd); | |
} | |
#if 0 | |
int ace_bdd_build_network_bdds( | |
Abc_Ntk_t * ntk, | |
st_table * leaves, | |
Vec_Ptr_t * inputs, | |
int max_size, | |
double min_Prob) | |
{ | |
Abc_Obj_t * obj; | |
double * P1s; | |
int i; | |
Vec_Ptr_t * nodes; | |
assert(Vec_PtrSize(inputs) > 0); | |
nodes = Abc_NtkDfsSeq(ntk); | |
P1s = malloc(sizeof(double) * Vec_PtrSize(inputs)); | |
Vec_PtrForEachEntry (Abc_Obj_t *, inputs, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
P1s[i] = info->static_prob; | |
info->prob0to1 = ACE_P0TO1(info->static_prob, info->switch_prob); | |
info->prob1to0 = ACE_P1TO0(info->static_prob, info->switch_prob); | |
} | |
Vec_PtrForEachEntry(Abc_Obj_t *, nodes, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
if (Abc_ObjIsCi(obj)) | |
{ | |
continue; | |
} | |
switch (info->status) | |
{ | |
case ACE_SIM: | |
assert (info->static_prob >= 0.0 && info->static_prob <= 1.0); | |
assert (info->switch_prob >= 0.0 && info->switch_prob <= 1.0); | |
if (!st_lookup(leaves, (char*) obj, NULL)) | |
{ | |
st_insert(leaves, (char*) obj, (char*) Vec_PtrSize(inputs)); | |
Vec_PtrPush(inputs, obj); | |
P1s = realloc(P1s, sizeof(double) * Vec_PtrSize(inputs)); | |
P1s[Vec_PtrSize(inputs) - 1] = info->static_prob; | |
info->prob0to1 = ACE_P0TO1(info->static_prob, info->switch_prob); | |
info->prob1to0 = ACE_P1TO0(info->static_prob, info->switch_prob); | |
} | |
break; | |
case ACE_UNDEF: | |
assert(0); | |
if (check_pi_status(obj)) | |
{ | |
while(1) | |
{ | |
DdNode * bdd = obj->pData; | |
int n0; | |
int n1; | |
ace_bdd_count_paths(ntk->pManFunc, bdd, &n1, &n0); | |
if (n1 <= max_size && n0 <= max_size) | |
{ | |
break; | |
} | |
//m == choose_root_fanin | |
//st_insert(leaves, (char*) ) | |
} | |
} | |
break; | |
case ACE_DEF: | |
assert(info->static_prob >= 0 && info->static_prob <= 1.0); | |
assert(info->switch_prob >= 0 && info->switch_prob <= 1.0); | |
break; | |
case ACE_NEW: | |
case ACE_OLD: | |
default: | |
assert(0); | |
} | |
} | |
free(P1s); | |
Vec_PtrFree(nodes); | |
return 0; | |
} | |
#endif | |
double calc_cube_switch_prob_recur(DdManager * mgr, DdNode * bdd, | |
ace_cube_t * cube, Vec_Ptr_t * inputs, st_table * visited, int phase) { | |
double * current_prob; | |
short i; | |
Abc_Obj_t * pi; | |
DdNode * bdd_if1, *bdd_if0; | |
double then_prob, else_prob; | |
if (bdd == Cudd_ReadLogicZero(mgr)) { | |
if (phase == 0) | |
return (1.0); | |
if (phase == 1) | |
return (0.0); | |
} else if (bdd == Cudd_ReadOne(mgr)) { | |
if (phase == 1) | |
return (1.0); | |
if (phase == 0) | |
return (0.0); | |
} | |
if (st_lookup(visited, (char *) bdd, (char **) ¤t_prob)) { | |
return (*current_prob); | |
} | |
/* Get literal index for this bdd node. */ | |
//assert(0); | |
i = Cudd_Regular(bdd)->index; | |
pi = Vec_PtrEntry(inputs, i); | |
current_prob = malloc(sizeof(double)); | |
if (Cudd_IsComplement(bdd)) { | |
bdd_if1 = Cudd_E(bdd); | |
bdd_if0 = Cudd_T(bdd); | |
} else { | |
bdd_if1 = Cudd_T(bdd); | |
bdd_if0 = Cudd_E(bdd); | |
} | |
Ace_Obj_Info_t * fanin_info = Ace_ObjInfo(pi); | |
then_prob = calc_cube_switch_prob_recur(mgr, bdd_if1, cube, inputs, visited, | |
phase); | |
assert(then_prob + EPSILON >= 0 && then_prob - EPSILON <= 1); | |
else_prob = calc_cube_switch_prob_recur(mgr, bdd_if0, cube, inputs, visited, | |
phase); | |
assert(else_prob + EPSILON >= 0 && else_prob - EPSILON <= 1); | |
switch (node_get_literal (cube->cube, i)) { | |
case ZERO: | |
*current_prob = fanin_info->prob0to1 * then_prob | |
+ (1.0 - fanin_info->prob0to1) * else_prob; | |
break; | |
case ONE: | |
*current_prob = (1.0 - fanin_info->prob1to0) * then_prob | |
+ fanin_info->prob1to0 * else_prob; | |
break; | |
case TWO: | |
*current_prob = fanin_info->static_prob * then_prob | |
+ (1.0 - fanin_info->static_prob) * else_prob; | |
break; | |
default: | |
fail("Bad literal."); | |
} | |
st_insert(visited, (char *) bdd, (char *) current_prob); | |
assert(*current_prob + EPSILON >= 0 && *current_prob - EPSILON < 1.0); | |
return (*current_prob); | |
} | |
double calc_cube_switch_prob(DdManager * mgr, DdNode * bdd, ace_cube_t * cube, | |
Vec_Ptr_t * inputs, int phase) { | |
double sp; | |
st_table * visited; | |
visited = st_init_table(st_ptrcmp, st_ptrhash); | |
sp = calc_cube_switch_prob_recur(mgr, bdd, cube, inputs, visited, phase); | |
st_free_table(visited); | |
assert(sp + EPSILON >= 0. && sp - EPSILON <= 1.0); | |
return (sp); | |
} | |
double calc_switch_prob_recur(DdManager * mgr, DdNode * bdd_next, DdNode * bdd, | |
ace_cube_t * cube, Vec_Ptr_t * inputs, double P1, int phase) { | |
short i; | |
Abc_Obj_t * pi; | |
double switch_prob, switch_prob_t, switch_prob_e; | |
double prob; | |
DdNode * bdd_if1, *bdd_if0; | |
ace_cube_t * cube0, *cube1; | |
Ace_Obj_Info_t * info; | |
assert(inputs != NULL); | |
assert(Vec_PtrSize(inputs) > 0); | |
assert(P1 >= 0); | |
if (bdd == Cudd_ReadLogicZero(mgr)) { | |
if (phase != 1) | |
return (0.0); | |
prob = calc_cube_switch_prob(mgr, bdd_next, cube, inputs, phase); | |
prob *= P1; | |
assert(prob + EPSILON >= 0. && prob - EPSILON <= 1.); | |
return (prob * P1); | |
} else if (bdd == Cudd_ReadOne(mgr)) { | |
if (phase != 0) | |
return (0.0); | |
prob = calc_cube_switch_prob(mgr, bdd_next, cube, inputs, phase); | |
prob *= P1; | |
assert(prob + EPSILON >= 0. && prob - EPSILON <= 1.); | |
return (prob * P1); | |
} | |
/* Get literal index for this bdd node. */ | |
i = Cudd_Regular(bdd)->index; | |
pi = Vec_PtrEntry(inputs, i); | |
info = Ace_ObjInfo(pi); | |
if (Cudd_IsComplement(bdd)) { | |
bdd_if1 = Cudd_E(bdd); | |
bdd_if0 = Cudd_T(bdd); | |
} else { | |
bdd_if1 = Cudd_T(bdd); | |
bdd_if0 = Cudd_E(bdd); | |
} | |
/* Recursive call down the THEN branch */ | |
cube1 = ace_cube_dup(cube); | |
set_remove(cube1->cube, 2 * i); | |
set_insert(cube1->cube, 2 * i + 1); | |
switch_prob_t = calc_switch_prob_recur(mgr, bdd_next, bdd_if1, cube1, | |
inputs, P1 * info->static_prob, phase); | |
ace_cube_free(cube1); | |
/* Recursive call down the ELSE branch */ | |
cube0 = ace_cube_dup(cube); | |
set_insert(cube0->cube, 2 * i); | |
set_remove(cube0->cube, 2 * i + 1); | |
switch_prob_e = calc_switch_prob_recur(mgr, bdd_next, bdd_if0, cube0, | |
inputs, P1 * (1.0 - info->static_prob), phase); | |
ace_cube_free(cube0); | |
assert(switch_prob_t + EPSILON >= 0. && switch_prob_t - EPSILON <= 1.); | |
assert(switch_prob_e + EPSILON >= 0. && switch_prob_e - EPSILON <= 1.); | |
return (switch_prob_t + switch_prob_e); | |
} | |
double ace_bdd_calc_switch_act(DdManager * mgr, Abc_Obj_t * obj, | |
Vec_Ptr_t * fanins) { | |
int d; | |
int n0, n1; | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
Abc_Obj_t * fanin; | |
ace_cube_t * cube; | |
double switch_act; | |
int i; | |
DdNode * bdd; | |
d = info->depth; | |
assert(d > 0); | |
d = (int) d * 0.4; | |
if (d < 1) { | |
d = 1; | |
} | |
if (Vec_PtrSize(fanins) < 1) { | |
return 0.5; | |
} | |
bdd = obj->pData; | |
n0 = n1 = 0; | |
ace_bdd_count_paths(mgr, bdd, &n1, &n0); | |
Vec_PtrForEachEntry(fanins, fanin, i) | |
{ | |
Ace_Obj_Info_t * fanin_info = Ace_ObjInfo(fanin); | |
fanin_info->prob0to1 = | |
ACE_P0TO1 (fanin_info->static_prob, fanin_info->switch_prob / (double) d); | |
fanin_info->prob1to0 = | |
ACE_P1TO0 (fanin_info->static_prob, fanin_info->switch_prob / (double) d); | |
prob_epsilon_fix(&fanin_info->prob0to1); | |
prob_epsilon_fix(&fanin_info->prob1to0); | |
assert( | |
fanin_info->prob0to1 + EPSILON >= 0. | |
&& fanin_info->prob0to1 - EPSILON <= 1.0); | |
assert( | |
fanin_info->prob1to0 + EPSILON >= 0. | |
&& fanin_info->prob1to0 - EPSILON <= 1.0); | |
} | |
cube = ace_cube_new_dc(Vec_PtrSize(fanins)); | |
switch_act = 2.0 | |
* calc_switch_prob_recur(mgr, bdd, bdd, cube, fanins, 1.0, n1 > n0) | |
* (double) d; | |
//switch_act = 2.0 * calc_switch_prob_recur (mgr, bdd, bdd, cube, fanins, 1.0, 1) * (double) d; | |
return switch_act; | |
} | |
int node_error(int code) { | |
switch (code) { | |
case 0: | |
fail("node_get_cube: node does not have a function"); | |
/* NOTREACHED */ | |
case 1: | |
fail("node_get_cube: cube index out of bounds"); | |
/* NOTREACHED */ | |
case 2: | |
fail("node_get_literal: bad cube"); | |
/* NOTREACHED */ | |
case 4: | |
fail("foreach_fanin: node changed during generation"); | |
/* NOTREACHED */ | |
case 5: | |
fail("foreach_fanout: node changed during generation"); | |
/* NOTREACHED */ | |
default: | |
fail("error code unused"); | |
} | |
return 0; | |
} |