#include #include "vtr_assert.h" #include "ace.h" #include "misc/vec/vecPtr.h" #include "bdd.h" #include "cube.h" #include "bdd/cudd/cuddInt.h" //#include "vecPtr.h" //#include "cudd.h" int check_pi_status(Abc_Obj_t * obj); void ace_bdd_count_paths(DdManager * mgr, DdNode * bdd, int * num_one_paths, int * num_zero_paths); double calc_cube_switch_prob(DdManager * mgr, DdNode * bdd, ace_cube_t * cube, Vec_Ptr_t * inputs, int phase); double calc_switch_prob_recur(DdManager * mgr, DdNode * bdd_next, DdNode * bdd, ace_cube_t * cube, Vec_Ptr_t * inputs, double P1, int phase); 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; VTR_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: VTR_ASSERT (info->static_prob >= 0.0 && info->static_prob <= 1.0); VTR_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: VTR_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: VTR_ASSERT(info->static_prob >= 0 && info->static_prob <= 1.0); VTR_ASSERT(info->switch_prob >= 0 && info->switch_prob <= 1.0); break; case ACE_NEW: case ACE_OLD: default: VTR_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. */ //VTR_ASSERT(0); i = Cudd_Regular(bdd)->index; pi = (Abc_Obj_t*) Vec_PtrEntry((Vec_Ptr_t*) inputs, i); current_prob = (double*) 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); VTR_ASSERT(then_prob + EPSILON >= 0 && then_prob - EPSILON <= 1); else_prob = calc_cube_switch_prob_recur(mgr, bdd_if0, cube, inputs, visited, phase); VTR_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); VTR_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); VTR_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_t, switch_prob_e; double prob; DdNode * bdd_if1, *bdd_if0; ace_cube_t * cube0, *cube1; Ace_Obj_Info_t * info; VTR_ASSERT(inputs != NULL); VTR_ASSERT(Vec_PtrSize(inputs) > 0); VTR_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; VTR_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; VTR_ASSERT(prob + EPSILON >= 0. && prob - EPSILON <= 1.); return (prob * P1); } /* Get literal index for this bdd node. */ i = Cudd_Regular(bdd)->index; pi = (Abc_Obj_t*) Vec_PtrEntry((Vec_Ptr_t*) 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); VTR_ASSERT(switch_prob_t + EPSILON >= 0. && switch_prob_t - EPSILON <= 1.); VTR_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; VTR_ASSERT(d > 0); d = (int) d * 0.4; if (d < 1) { d = 1; } if (Vec_PtrSize(fanins) < 1) { return 0.5; } bdd = (DdNode*) obj->pData; n0 = n1 = 0; ace_bdd_count_paths(mgr, bdd, &n1, &n0); Vec_PtrForEachEntry(Abc_Obj_t*, fanins, fanin, i) //#define Vec_PtrForEachEntry( vVec, pEntry, i ) for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) //for ( i = 0; (i < Vec_PtrSize(fanins)) && (((fanin) = Vec_PtrEntry(fanins, i)), 1); 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); VTR_ASSERT( fanin_info->prob0to1 + EPSILON >= 0. && fanin_info->prob0to1 - EPSILON <= 1.0); VTR_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; }