OpenFPGA/ace2/sim.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;
}
}