442 lines
9.8 KiB
C
442 lines
9.8 KiB
C
|
#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) {
|
||
|
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);
|
||
|
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:
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/*inline*/
|
||
|
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;
|
||
|
char clk_name[ACE_CHAR_BUFFER_SIZE];
|
||
|
int error = 0;
|
||
|
Abc_Frame_t * pAbc;
|
||
|
Abc_Ntk_t * ntk;
|
||
|
Abc_Obj_t * obj;
|
||
|
|
||
|
srand(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);
|
||
|
|
||
|
// Check # of clocks
|
||
|
#if 0
|
||
|
int num_clks;
|
||
|
blif_clock_info(blif_file_name, &num_clks, clk_name);
|
||
|
if (num_clks > 1)
|
||
|
{
|
||
|
printf("Multiple clocks detected in blif file. This is not supported.\n");
|
||
|
exit(0);
|
||
|
}
|
||
|
else if (num_clks == 1)
|
||
|
{
|
||
|
printf("Clock Detected: %s\n", clk_name);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// 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);
|
||
|
}
|
||
|
|
||
|
//Abc_NtkToSop(ntk, 0);
|
||
|
Abc_Ntk_t * new_ntk;
|
||
|
new_ntk = Abc_NtkToNetlist(ntk);
|
||
|
|
||
|
if (!error) {
|
||
|
ace_io_print_activity(ntk, OUT_ACT);
|
||
|
}
|
||
|
|
||
|
Io_WriteHie(ntk, blif_file_name, new_blif_file_name);
|
||
|
|
||
|
printf("Done\n");
|
||
|
fflush(0);
|
||
|
return 0;
|
||
|
}
|