#include "vtr_assert.h" #include "ace.h" #include "sim.h" #include "bdd/cudd/cudd.h" #include "bdd/cudd/cuddInt.h" void get_pi_values(Abc_Ntk_t * ntk, Vec_Ptr_t * nodes, int cycle); int * getFaninValues(Abc_Obj_t * obj_ptr); ace_status_t getFaninStatus(Abc_Obj_t * obj_ptr); void evaluate_circuit(Abc_Ntk_t * ntk, Vec_Ptr_t * node_vec, int cycle); void update_FFs(Abc_Ntk_t * ntk); void get_pi_values(Abc_Ntk_t * ntk, Vec_Ptr_t * /*nodes*/, int cycle) { Abc_Obj_t * obj; Ace_Obj_Info_t * info; int i; double prob0to1, prob1to0, rand_num; //Vec_PtrForEachEntry(Abc_Obj_t *, nodes, obj, i) Abc_NtkForEachObj(ntk, obj, i) { info = Ace_ObjInfo(obj); if (Abc_ObjType(obj) == ABC_OBJ_PI) { if (info->values) { if (info->status == ACE_UNDEF) { info->status = ACE_NEW; if (info->values[cycle] == 1) { info->value = 1; info->num_toggles = 1; info->num_ones = 1; } else { info->value = 0; info->num_toggles = 0; info->num_ones = 0; } } else { switch (info->value) { case 0: if (info->values[cycle] == 1) { info->value = 1; info->status = ACE_NEW; info->num_toggles++; info->num_ones++; } else { info->status = ACE_OLD; } break; case 1: if (info->values[cycle] == 0) { info->value = 0; info->status = ACE_NEW; info->num_toggles++; } else { info->num_ones++; info->status = ACE_OLD; } break; default: printf("Bad Value\n"); VTR_ASSERT(0); break; } } } else { prob0to1 = ACE_P0TO1(info->static_prob, info->switch_prob); prob1to0 = ACE_P1TO0(info->static_prob, info->switch_prob); //We don't need a cryptographically secure random number //generator so suppress warning in coverity // //coverity[dont_call] rand_num = (double) rand() / (double) RAND_MAX; if (info->status == ACE_UNDEF) { info->status = ACE_NEW; if (rand_num < prob0to1) { info->value = 1; info->num_toggles = 1; info->num_ones = 1; } else { info->value = 0; info->num_toggles = 0; info->num_ones = 0; } } else { switch (info->value) { case 0: if (rand_num < prob0to1) { info->value = 1; info->status = ACE_NEW; info->num_toggles++; info->num_ones++; } else { info->status = ACE_OLD; } break; case 1: if (rand_num < prob1to0) { info->value = 0; info->status = ACE_NEW; info->num_toggles++; } else { info->num_ones++; info->status = ACE_OLD; } break; default: printf("Bad value\n"); VTR_ASSERT(FALSE); break; } } } } } } int * getFaninValues(Abc_Obj_t * obj_ptr) { Abc_Obj_t * fanin; int i; Ace_Obj_Info_t * info; int * faninValues; Abc_ObjForEachFanin(obj_ptr, fanin, i) { info = Ace_ObjInfo(fanin); if (info->status == ACE_UNDEF) { printf("Fan-in is undefined\n"); VTR_ASSERT(FALSE); } else if (info->status == ACE_NEW) { break; } } if (i >= Abc_ObjFaninNum(obj_ptr)) { // inputs haven't changed return NULL; } faninValues = (int*) malloc(Abc_ObjFaninNum(obj_ptr) * sizeof(int)); Abc_ObjForEachFanin(obj_ptr, fanin, i) { info = Ace_ObjInfo(fanin); faninValues[i] = info->value; } return faninValues; } ace_status_t getFaninStatus(Abc_Obj_t * obj_ptr) { Abc_Obj_t * fanin; int i; Ace_Obj_Info_t * info; Abc_ObjForEachFanin(obj_ptr, fanin, i) { info = Ace_ObjInfo(fanin); if (info->status == ACE_UNDEF) { return ACE_UNDEF; } } Abc_ObjForEachFanin(obj_ptr, fanin, i) { info = Ace_ObjInfo(fanin); if (info->status == ACE_NEW || info->status == ACE_SIM) { return ACE_NEW; } } return ACE_OLD; } void evaluate_circuit(Abc_Ntk_t * ntk, Vec_Ptr_t * node_vec, int /*cycle*/) { Abc_Obj_t * obj; Ace_Obj_Info_t * info; int i; int value = -1; int * faninValues; ace_status_t status; DdNode * dd_node; Vec_PtrForEachEntry(Abc_Obj_t*, node_vec, obj, i) { info = Ace_ObjInfo(obj); switch (Abc_ObjType(obj)) { case ABC_OBJ_PI: case ABC_OBJ_BO: break; case ABC_OBJ_PO: case ABC_OBJ_BI: case ABC_OBJ_LATCH: case ABC_OBJ_NODE: status = getFaninStatus(obj); switch (status) { case ACE_UNDEF: info->status = ACE_UNDEF; break; case ACE_OLD: info->status = ACE_OLD; info->num_ones += info->value; break; case ACE_NEW: if (Abc_ObjIsNode(obj)) { faninValues = getFaninValues(obj); VTR_ASSERT(faninValues); dd_node = Cudd_Eval((DdManager*) ntk->pManFunc, (DdNode*) obj->pData, faninValues); VTR_ASSERT(Cudd_IsConstant(dd_node)); if (dd_node == Cudd_ReadOne((DdManager*) ntk->pManFunc)) { value = 1; } else if (dd_node == Cudd_ReadLogicZero((DdManager*) ntk->pManFunc)) { value = 0; } else { VTR_ASSERT(0); } free(faninValues); } else { Ace_Obj_Info_t * fanin_info = Ace_ObjInfo( Abc_ObjFanin0(obj)); value = fanin_info->value; } if (info->value != value || info->status == ACE_UNDEF) { info->value = value; if (info->status != ACE_UNDEF) { /* Don't count the first value as a toggle */ info->num_toggles++; } info->status = ACE_NEW; } else { info->status = ACE_OLD; } info->num_ones += info->value; break; default: VTR_ASSERT(0); break; } break; default: VTR_ASSERT(0); break; } } } void update_FFs(Abc_Ntk_t * ntk) { Abc_Obj_t * obj; int i; Ace_Obj_Info_t * bi_fanin_info; Ace_Obj_Info_t * bi_info; Ace_Obj_Info_t * latch_info; Ace_Obj_Info_t * bo_info; Abc_NtkForEachLatch(ntk, obj, i) { bi_fanin_info = Ace_ObjInfo(Abc_ObjFanin0(Abc_ObjFanin0(obj))); bi_info = Ace_ObjInfo(Abc_ObjFanin0(obj)); bo_info = Ace_ObjInfo(Abc_ObjFanout0(obj)); latch_info = Ace_ObjInfo(obj); // Value bi_info->value = bi_fanin_info->value; latch_info->value = bi_fanin_info->value; bo_info->value = bi_fanin_info->value; // Status bi_info->status = bi_fanin_info->status; latch_info->status = bi_fanin_info->status; bo_info->status = bi_fanin_info->status; // Ones bi_info->num_ones = bi_fanin_info->num_ones; latch_info->num_ones = bi_fanin_info->num_ones; bo_info->num_ones = bi_fanin_info->num_ones; // Toggles bi_info->num_toggles = bi_fanin_info->num_toggles; latch_info->num_toggles = bi_fanin_info->num_toggles; bo_info->num_toggles = bi_fanin_info->num_toggles; } } void ace_sim_activities(Abc_Ntk_t * ntk, Vec_Ptr_t * nodes, int max_cycles, double threshold) { Abc_Obj_t * obj; Ace_Obj_Info_t * info; int i; VTR_ASSERT(max_cycles > 0); VTR_ASSERT(threshold > 0.0); // srand((unsigned) time(NULL)); //Vec_PtrForEachEntry(Abc_Obj_t *, nodes, obj, i) Abc_NtkForEachObj(ntk, obj, i) { info = Ace_ObjInfo(obj); info->value = 0; if (Abc_ObjType(obj) == ABC_OBJ_BO) { info->status = ACE_NEW; } else { info->status = ACE_UNDEF; } info->num_ones = 0; info->num_toggles = 0; } Vec_Ptr_t * logic_nodes = Abc_NtkDfs(ntk, TRUE); for (i = 0; i < max_cycles; i++) { get_pi_values(ntk, nodes, i); evaluate_circuit(ntk, logic_nodes, i); update_FFs(ntk); } //Vec_PtrForEachEntry(Abc_Obj_t *, nodes, obj, i) Abc_NtkForEachObj(ntk, obj, i) { info = Ace_ObjInfo(obj); info->static_prob = info->num_ones / (double) max_cycles; VTR_ASSERT(info->static_prob >= 0.0 && info->static_prob <= 1.0); info->switch_prob = info->num_toggles / (double) max_cycles; VTR_ASSERT(info->switch_prob >= 0.0 && info->switch_prob <= 1.0); VTR_ASSERT(info->switch_prob - EPSILON <= 2.0 * (1.0 - info->static_prob)); VTR_ASSERT(info->switch_prob - EPSILON <= 2.0 * (info->static_prob)); info->status = ACE_SIM; } Vec_PtrFree(logic_nodes); }