327 lines
7.4 KiB
C
327 lines
7.4 KiB
C
|
#include "ace.h"
|
||
|
#include "sim.h"
|
||
|
|
||
|
#include "cudd.h"
|
||
|
|
||
|
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");
|
||
|
assert(0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
prob0to1 = ACE_P0TO1(info->static_prob, info->switch_prob);
|
||
|
prob1to0 = ACE_P1TO0(info->static_prob, info->switch_prob);
|
||
|
|
||
|
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");
|
||
|
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");
|
||
|
assert(FALSE);
|
||
|
} else if (info->status == ACE_NEW) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i >= Abc_ObjFaninNum(obj_ptr)) {
|
||
|
// inputs haven't changed
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
faninValues = 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;
|
||
|
int * faninValues;
|
||
|
ace_status_t status;
|
||
|
DdNode * dd_node;
|
||
|
|
||
|
Vec_PtrForEachEntry(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);
|
||
|
assert(faninValues);
|
||
|
dd_node = Cudd_Eval(ntk->pManFunc, obj->pData, faninValues);
|
||
|
assert(Cudd_IsConstant(dd_node));
|
||
|
if (dd_node == Cudd_ReadOne(ntk->pManFunc)) {
|
||
|
value = 1;
|
||
|
} else if (dd_node == Cudd_ReadLogicZero(ntk->pManFunc)) {
|
||
|
value = 0;
|
||
|
} else {
|
||
|
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:
|
||
|
assert(0);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
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;
|
||
|
|
||
|
assert(max_cycles > 0);
|
||
|
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;
|
||
|
assert(info->static_prob >= 0.0 && info->static_prob <= 1.0);
|
||
|
info->switch_prob = info->num_toggles / (double) max_cycles;
|
||
|
assert(info->switch_prob >= 0.0 && info->switch_prob <= 1.0);
|
||
|
|
||
|
assert(info->switch_prob - EPSILON <= 2.0 * (1.0 - info->static_prob));
|
||
|
assert(info->switch_prob - EPSILON <= 2.0 * (info->static_prob));
|
||
|
|
||
|
info->status = ACE_SIM;
|
||
|
}
|
||
|
}
|