#include <stdio.h> | |
#include "ace.h" | |
#include "io_ace.h" | |
#include "blif.h" | |
#include "cycle.h" | |
#include "sim.h" | |
#include "bdd.h" | |
#include "depth.h" | |
#include "cube.h" | |
// ABC Headers | |
#include "abc.h" | |
#include "main.h" | |
#include "io.h" | |
//#include "vecInt.h" | |
st_table * ace_info_hash_table; | |
void print_status(Abc_Ntk_t * ntk) { | |
int i; | |
Abc_Obj_t * obj; | |
Abc_NtkForEachNode(ntk, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
switch (info->status) { | |
case ACE_UNDEF: | |
printf("%d: UNDEFINED\n", i); | |
break; | |
case ACE_DEF: | |
printf("%d: DEFINED\n", i); | |
break; | |
case ACE_SIM: | |
printf("%d: SIM\n", i); | |
break; | |
case ACE_NEW: | |
printf("%d: NEW\n", i); | |
break; | |
case ACE_OLD: | |
printf("%d: OLD\n", i); | |
break; | |
} | |
} | |
} | |
void alloc_and_init_activity_info(Abc_Ntk_t * ntk) { | |
Vec_Ptr_t * node_vec; | |
Abc_Obj_t * obj_ptr; | |
int i; | |
node_vec = Abc_NtkDfsSeq(ntk); | |
Vec_PtrForEachEntry(node_vec, obj_ptr, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj_ptr); | |
info->values = NULL; | |
info->status = ACE_UNDEF; | |
info->num_toggles = 0; | |
info->num_ones = 0; | |
} | |
Vec_PtrFree(node_vec); | |
} | |
void ace_update_latch_probs(Abc_Ntk_t * ntk) { | |
Abc_Obj_t * obj_ptr; | |
Abc_Obj_t * fanin_ptr; | |
Abc_Obj_t * fanout_ptr; | |
Ace_Obj_Info_t * fanin_info; | |
Ace_Obj_Info_t * fanout_info; | |
int i; | |
Abc_NtkForEachLatch(ntk, obj_ptr, i) | |
{ | |
fanin_ptr = Abc_ObjFanin0(obj_ptr); | |
fanout_ptr = Abc_ObjFanout0(obj_ptr); | |
fanin_info = Ace_ObjInfo(fanin_ptr); | |
fanout_info = Ace_ObjInfo(fanout_ptr); | |
fanout_info->static_prob = fanin_info->static_prob; | |
fanout_info->switch_prob = fanin_info->switch_prob; | |
fanout_info->status = fanin_info->status; | |
} | |
} | |
void print_node_bdd(Abc_Ntk_t * ntk) { | |
Abc_Obj_t * obj; | |
int i; | |
Abc_NtkForEachNode(ntk, obj, i) | |
{ | |
DdNode * node = obj->pData; | |
printf("Object: %d\n", obj->Id); | |
fflush(0); | |
//printf("Fanin: %d\n", Abc_ObjFaninNum(obj)); fflush(0); | |
while (1) { | |
if (node == Cudd_ReadOne(ntk->pManFunc)) { | |
//printf("one!\n"); | |
break; | |
} else if (node == Cudd_ReadLogicZero(ntk->pManFunc)) { | |
//printf("zero!\n"); | |
break; | |
} | |
printf("\tVar: %hd (%08x)\n", Cudd_Regular(node)->index, | |
(unsigned int) node); | |
fflush(0); | |
DdNode * first_node; | |
Cudd_FirstNode(ntk->pManFunc, node, &first_node); | |
node = Cudd_E(node); | |
} | |
} | |
} | |
void print_nodes(Vec_Ptr_t * nodes) { | |
Abc_Obj_t * obj; | |
int i; | |
printf("Printing Nodes\n"); | |
Vec_PtrForEachEntry(nodes, obj, i) | |
{ | |
printf("\t%d. %d-%d-%s\n", i, Abc_ObjId(obj), Abc_ObjType(obj), | |
Abc_ObjName(obj)); | |
} | |
fflush(0); | |
} | |
int ace_calc_activity(Abc_Ntk_t * ntk, int num_vectors, char * clk_name) { | |
int error = 0; | |
Vec_Ptr_t * nodes_all; | |
Vec_Ptr_t * nodes_logic; | |
Vec_Ptr_t * next_state_node_vec; | |
Vec_Ptr_t * latches_in_cycles_vec; | |
Abc_Obj_t * obj; | |
int i, j; | |
Ace_Obj_Info_t * info; | |
//Build BDD | |
Abc_NtkSopToBdd(ntk); | |
nodes_all = Abc_NtkDfsSeq(ntk); | |
nodes_logic = Abc_NtkDfs(ntk, TRUE); | |
//print_nodes(nodes_logic); | |
Vec_PtrForEachEntry(nodes_all, obj, i) | |
{ | |
info = Ace_ObjInfo(obj); | |
info->status = ACE_UNDEF; | |
} | |
Abc_NtkForEachPi(ntk, obj, i) | |
{ | |
info = Ace_ObjInfo(obj); | |
if (strcmp(Abc_ObjName(obj), clk_name) != 0) { | |
assert(info->static_prob >= 0 && info->static_prob <= 1.0); | |
assert(info->switch_prob >= 0 && info->switch_prob <= 1.0); | |
assert(info->switch_act >= 0 && info->switch_act <= 1.0); | |
assert(info->switch_prob <= 2.0 * (1.0 - info->static_prob)); | |
assert(info->switch_prob <= 2.0 * info->static_prob); | |
} | |
info->status = ACE_DEF; | |
} | |
latches_in_cycles_vec = latches_in_cycles(ntk); | |
printf("%d/%d latches are part of cycle(s)\n", latches_in_cycles_vec->nSize, | |
Abc_NtkLatchNum(ntk)); | |
fflush(0); | |
//if (latches_in_cycles_vec->nSize) | |
if (TRUE) { | |
//print_status(ntk); | |
printf("Stage 1: Simulating Probabilities...\n"); | |
fflush(0); | |
next_state_node_vec = Abc_NtkDfsSeq(ntk); | |
//print_nodes(next_state_node_vec); | |
ace_sim_activities(ntk, next_state_node_vec, num_vectors, 0.05); | |
//ace_sim_activities(ntk, nodes_logic, num_vectors, 0.05); | |
ace_update_latch_probs(ntk); | |
Vec_PtrFree(next_state_node_vec); | |
} | |
//print_status(ntk); | |
printf("Stage 2: Computing Probabilities...\n"); | |
fflush(0); | |
// Currently this stage does nothing | |
#if 0 | |
ace_bdd_get_literals (ntk, &leaves, &literals); | |
i = 0; | |
while(1) | |
{ | |
//printf("Calc Iteration = %d\n", i++); fflush(0); | |
if (ace_bdd_build_network_bdds(ntk, leaves, literals, ACE_MAX_BDD_SIZE, ACE_MIN_BDD_PROB) < 1) | |
{ | |
break; | |
} | |
ace_update_latch_static_probs(ntk); | |
ace_update_latch_switch_probs(ntk); | |
} | |
st_free_table(leaves); | |
Vec_PtrFree(literals); | |
#endif | |
/*------------- Computing Register Output Activities. ---------------------*/ | |
printf("Stage 3: Computing Register Output Activities...\n"); | |
fflush(0); | |
Abc_NtkForEachLatchOutput(ntk, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
info->switch_act = info->switch_prob; | |
assert(info->switch_act >= 0.0); | |
} | |
Abc_NtkForEachPi(ntk, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
assert(info->switch_act >= 0.0); | |
} | |
/*------------- Calculate switching activities. ---------------------*/ | |
printf("Stage 4: Computing Switching Activities...\n"); | |
fflush(0); | |
/* Do latches first, then logic after */ | |
Vec_PtrForEachEntry(nodes_all, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
switch (Abc_ObjType(obj)) { | |
case ABC_OBJ_PI: | |
if (strcmp(Abc_ObjName(obj), clk_name) == 0) { | |
info->switch_act = 2; | |
info->switch_prob = 1; | |
info->static_prob = 0.5; | |
} else { | |
info->switch_act = info->switch_prob; | |
} | |
break; | |
case ABC_OBJ_BO: | |
case ABC_OBJ_LATCH: | |
info->switch_act = info->switch_prob; | |
break; | |
default: | |
break; | |
} | |
} | |
Vec_PtrForEachEntry(nodes_logic, obj, i) | |
{ | |
Ace_Obj_Info_t * info = Ace_ObjInfo(obj); | |
//Ace_Obj_Info_t * fanin_info; | |
assert(Abc_ObjType(obj) == ABC_OBJ_NODE); | |
if (Abc_ObjFaninNum(obj) < 1) { | |
info->switch_act = 0.0; | |
continue; | |
} else { | |
Vec_Ptr_t * literals = Vec_PtrAlloc(0); | |
Abc_Obj_t * fanin; | |
assert(obj->Type == ABC_OBJ_NODE); | |
Abc_ObjForEachFanin(obj, fanin, j) | |
{ | |
Vec_PtrPush(literals, fanin); | |
} | |
info->switch_act = ace_bdd_calc_switch_act(ntk->pManFunc, obj, | |
literals); | |
Vec_PtrFree(literals); | |
} | |
assert(info->switch_act >= 0); | |
} | |
return error; | |
} | |
Ace_Obj_Info_t * Ace_ObjInfo(Abc_Obj_t * obj) { | |
Ace_Obj_Info_t * info; | |
if (st_lookup(ace_info_hash_table, (char *) obj, (char **) &info)) { | |
return info; | |
} | |
assert(0); | |
} | |
void prob_epsilon_fix(double * d) { | |
if (*d < 0) { | |
assert(*d > 0 - EPSILON); | |
*d = 0; | |
} else if (*d > 1) { | |
assert(*d < 1 + EPSILON); | |
*d = 1.; | |
} | |
} | |
int main(int argc, char * argv[]) { | |
FILE * BLIF = NULL; | |
FILE * IN_ACT = NULL; | |
FILE * OUT_ACT = stdout; | |
ace_pi_format_t pi_format = ACE_CODED; | |
double p, d; | |
int i; | |
int depth; | |
int error = 0; | |
Abc_Frame_t * pAbc; | |
Abc_Ntk_t * ntk; | |
Abc_Obj_t * obj; | |
int seed = 0; | |
p = ACE_PI_STATIC_PROB; | |
d = ACE_PI_SWITCH_PROB; | |
char blif_file_name[BLIF_FILE_NAME_LEN]; | |
char new_blif_file_name[BLIF_FILE_NAME_LEN]; | |
ace_io_parse_argv(argc, argv, &BLIF, &IN_ACT, &OUT_ACT, blif_file_name, | |
new_blif_file_name, &pi_format, &p, &d, &seed); | |
srand(seed); | |
pAbc = Abc_FrameGetGlobalFrame(); | |
ntk = Io_Read(blif_file_name, IO_FILE_BLIF, 1); | |
printf("Objects in network: %d\n", Abc_NtkObjNum(ntk)); | |
printf("PIs in network: %d\n", Abc_NtkPiNum(ntk)); | |
printf("POs in network: %d\n", Abc_NtkPoNum(ntk)); | |
printf("Nodes in network: %d\n", Abc_NtkNodeNum(ntk)); | |
printf("Latches in network: %d\n", Abc_NtkLatchNum(ntk)); | |
if (!Abc_NtkIsAcyclic(ntk)) { | |
printf("Circuit has combinational loops\n"); | |
exit(0); | |
} | |
// Alloc Aux Info Array | |
// Full Allocation | |
Ace_Obj_Info_t * info = calloc(Abc_NtkObjNum(ntk), sizeof(Ace_Obj_Info_t)); | |
ace_info_hash_table = st_init_table(st_ptrcmp, st_ptrhash); | |
Abc_NtkForEachObj(ntk, obj, i) | |
{ | |
st_insert(ace_info_hash_table, (char *) obj, (char *) &info[i]); | |
//Ace_InfoPtrSet(obj, & info[i]); | |
} | |
/* DFS Allocation | |
Vec_Ptr_t * node_vec = Abc_NtkDfsSeq(ntk); | |
Ace_Obj_Info_t * info = malloc(node_vec->nSize * sizeof(Ace_Obj_Info_t)); | |
Vec_PtrForEachEntry(Abc_Obj_t *, node_vec, obj_ptr, i) | |
{ | |
Ace_InfoPtrSet(obj_ptr, & info[i]); | |
} | |
Vec_PtrFree(node_vec); | |
*/ | |
// Check Depth | |
depth = ace_calc_network_depth(ntk); | |
printf("Max Depth: %d\n", depth); | |
assert(depth > 0); | |
alloc_and_init_activity_info(ntk); | |
switch (pi_format) { | |
case ACE_CODED: | |
printf("Input activities will be assumed (%f, %f, %f)...\n", | |
ACE_PI_STATIC_PROB, ACE_PI_SWITCH_PROB, ACE_PI_SWITCH_ACT); | |
break; | |
case ACE_PD: | |
printf("Input activities will be (%f, %f, %f)...\n", p, d, d); | |
fflush(0); | |
break; | |
case ACE_ACT: | |
printf("Input activities will be read from an activity file...\n"); | |
break; | |
case ACE_VEC: | |
printf("Input activities will be read from a vector file...\n"); | |
break; | |
default: | |
printf("Error reading activities.\n"); | |
error = ACE_ERROR; | |
break; | |
} | |
/* | |
Abc_NtkForEachPi(ntk, obj_ptr, i) | |
{ | |
char * s; | |
s = Nm_ManFindNameById(ntk->pManName, obj_ptr->Id); | |
if (s != NULL) | |
{ | |
//printf("%s\n",s); | |
} | |
} | |
*/ | |
// Get clock info | |
char * clk_name = NULL; | |
if (!error) { | |
Abc_NtkForEachLatch(ntk, obj, i) | |
{ | |
Abc_LatchInfo_t * latch_info = obj->pData; | |
if (!clk_name) { | |
clk_name = latch_info->pClkName; | |
} | |
if (strcmp(clk_name, latch_info->pClkName) == 0) { | |
// Clock names match - do nothing | |
} else { | |
// Multiple clocks - error | |
printf( | |
"Multiple clocks detected in blif file. This is not supported.\n"); | |
error = ACE_ERROR; | |
break; | |
} | |
} | |
} | |
if (!error) { | |
if (clk_name == NULL) { | |
// No clocks | |
printf( | |
"No clocks detected in blif file. This is not supported.\n"); | |
error = ACE_ERROR; | |
} else { | |
printf("Clock detected: %s\n", clk_name); | |
} | |
} | |
// Read Activities | |
if (!error) { | |
error = ace_io_read_activity(ntk, IN_ACT, pi_format, p, d, clk_name); | |
} | |
if (!error) { | |
error = ace_calc_activity(ntk, ACE_NUM_VECTORS, clk_name); | |
} | |
//Abc_NtkToSop(ntk, 0); | |
Abc_Ntk_t * new_ntk; | |
new_ntk = Abc_NtkToNetlist(ntk); | |
if (!error) { | |
ace_io_print_activity(ntk, OUT_ACT); | |
} | |
if (!error) { | |
Io_WriteHie(ntk, blif_file_name, new_blif_file_name); | |
printf("Done\n"); | |
} | |
fflush(0); | |
return 0; | |
} |