require CUDD
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
2da2064852
commit
e3a1fd792c
|
|
@ -28,7 +28,6 @@ project(STA VERSION 2.6.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
option(USE_CUDD "Use CUDD BDD package" ON)
|
|
||||||
option(CUDD_DIR "CUDD BDD package directory")
|
option(CUDD_DIR "CUDD BDD package directory")
|
||||||
option(USE_TCL_READLINE "Use TCL readliine package" ON)
|
option(USE_TCL_READLINE "Use TCL readliine package" ON)
|
||||||
option(USE_SANITIZE "Compile with santize address enabled")
|
option(USE_SANITIZE "Compile with santize address enabled")
|
||||||
|
|
@ -371,30 +370,25 @@ find_package(Eigen3 REQUIRED)
|
||||||
#
|
#
|
||||||
# Locate CUDD bdd package.
|
# Locate CUDD bdd package.
|
||||||
#
|
#
|
||||||
set(CUDD 0)
|
find_library(CUDD_LIB
|
||||||
if (USE_CUDD)
|
NAME cudd
|
||||||
find_library(CUDD_LIB
|
PATHS ${CUDD_DIR}
|
||||||
NAME cudd
|
PATH_SUFFIXES lib lib/cudd cudd/.libs
|
||||||
PATHS ${CUDD_DIR}
|
)
|
||||||
PATH_SUFFIXES lib lib/cudd cudd/.libs
|
if (CUDD_LIB)
|
||||||
)
|
message(STATUS "CUDD library: ${CUDD_LIB}")
|
||||||
if (CUDD_LIB)
|
get_filename_component(CUDD_LIB_DIR "${CUDD_LIB}" PATH)
|
||||||
message(STATUS "CUDD library: ${CUDD_LIB}")
|
get_filename_component(CUDD_LIB_PARENT1 "${CUDD_LIB_DIR}" PATH)
|
||||||
get_filename_component(CUDD_LIB_DIR "${CUDD_LIB}" PATH)
|
find_file(CUDD_HEADER cudd.h
|
||||||
get_filename_component(CUDD_LIB_PARENT1 "${CUDD_LIB_DIR}" PATH)
|
PATHS ${CUDD_LIB_PARENT1} ${CUDD_LIB_PARENT1}/include ${CUDD_LIB_PARENT1}/include/cudd)
|
||||||
find_file(CUDD_HEADER cudd.h
|
if (CUDD_HEADER)
|
||||||
PATHS ${CUDD_LIB_PARENT1} ${CUDD_LIB_PARENT1}/include ${CUDD_LIB_PARENT1}/include/cudd)
|
get_filename_component(CUDD_INCLUDE "${CUDD_HEADER}" PATH)
|
||||||
if (CUDD_HEADER)
|
message(STATUS "CUDD header: ${CUDD_HEADER}")
|
||||||
get_filename_component(CUDD_INCLUDE "${CUDD_HEADER}" PATH)
|
|
||||||
message(STATUS "CUDD header: ${CUDD_HEADER}")
|
|
||||||
# Referenced by StaConfig.hh.cmake
|
|
||||||
set(CUDD 1)
|
|
||||||
else()
|
|
||||||
message(STATUS "CUDD header: not found")
|
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
message(STATUS "CUDD library: not found")
|
message(STATUS "CUDD header: not found")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "CUDD library: not found")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${SSTA}" STREQUAL "")
|
if("${SSTA}" STREQUAL "")
|
||||||
|
|
@ -517,6 +511,7 @@ target_link_libraries(OpenSTA
|
||||||
Eigen3::Eigen
|
Eigen3::Eigen
|
||||||
${TCL_LIBRARY}
|
${TCL_LIBRARY}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${CUDD_LIB}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (TCL_READLINE_LIBRARY)
|
if (TCL_READLINE_LIBRARY)
|
||||||
|
|
@ -527,9 +522,7 @@ if (ZLIB_LIBRARIES)
|
||||||
target_link_libraries(OpenSTA ${ZLIB_LIBRARIES})
|
target_link_libraries(OpenSTA ${ZLIB_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CUDD_LIB)
|
target_link_libraries(OpenSTA )
|
||||||
target_link_libraries(OpenSTA ${CUDD_LIB})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_include_directories(OpenSTA
|
target_include_directories(OpenSTA
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|
|
||||||
|
|
@ -103,9 +103,9 @@ External library dependencies:
|
||||||
```
|
```
|
||||||
Ubuntu Macos license
|
Ubuntu Macos license
|
||||||
eigen 3.4.0 3.4.0 MPL2 required
|
eigen 3.4.0 3.4.0 MPL2 required
|
||||||
|
cudd 3.0.0 3.0.0 BSD required
|
||||||
tclreadline 2.3.8 2.3.8 BSD optional
|
tclreadline 2.3.8 2.3.8 BSD optional
|
||||||
zLib 1.2.5 1.2.8 zlib optional
|
zLib 1.2.5 1.2.8 zlib optional
|
||||||
cudd 3.0.0 3.0.0 BSD optional
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The [TCL readline library](https://tclreadline.sourceforge.net/tclreadline.html)
|
The [TCL readline library](https://tclreadline.sourceforge.net/tclreadline.html)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ Release 2.6.0 2024/07/??
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The version of c++ used by OpenSTA is now 17.
|
The version of c++ used by OpenSTA is now 17.
|
||||||
|
The Cudd BBD packager is now required.
|
||||||
|
|
||||||
The USE_CUDD and USE_TCL_READLINE options default to ON.
|
The USE_TCL_READLINE option defaults to ON.
|
||||||
|
|
||||||
Release 2.5.0 2024/01/17
|
Release 2.5.0 2024/01/17
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,10 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "cudd.h"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
|
|
||||||
#if CUDD
|
|
||||||
#include "cudd.h"
|
|
||||||
#else
|
|
||||||
struct DdNode;
|
|
||||||
struct DdManager;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef std::map<const LibertyPort*, DdNode*> BddPortVarMap;
|
typedef std::map<const LibertyPort*, DdNode*> BddPortVarMap;
|
||||||
|
|
|
||||||
108
power/Power.cc
108
power/Power.cc
|
|
@ -502,8 +502,6 @@ Power::clockGatePins(const Instance *inst,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if CUDD
|
|
||||||
|
|
||||||
PwrActivity
|
PwrActivity
|
||||||
Power::evalActivity(FuncExpr *expr,
|
Power::evalActivity(FuncExpr *expr,
|
||||||
const Instance *inst)
|
const Instance *inst)
|
||||||
|
|
@ -609,112 +607,6 @@ Power::evalBddActivity(DdNode *bdd,
|
||||||
return activity;
|
return activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
PwrActivity
|
|
||||||
Power::evalActivity(FuncExpr *expr,
|
|
||||||
const Instance *inst)
|
|
||||||
{
|
|
||||||
return evalActivity(expr, inst, nullptr, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eval activity thru expr.
|
|
||||||
// With cofactor_port eval the positive/negative cofactor of expr wrt cofactor_port.
|
|
||||||
PwrActivity
|
|
||||||
Power::evalActivity(FuncExpr *expr,
|
|
||||||
const Instance *inst,
|
|
||||||
const LibertyPort *cofactor_port,
|
|
||||||
bool cofactor_positive)
|
|
||||||
{
|
|
||||||
switch (expr->op()) {
|
|
||||||
case FuncExpr::op_port: {
|
|
||||||
LibertyPort *port = expr->port();
|
|
||||||
if (port == cofactor_port) {
|
|
||||||
if (cofactor_positive)
|
|
||||||
return PwrActivity(0.0, 1.0, PwrActivityOrigin::constant);
|
|
||||||
else
|
|
||||||
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
|
|
||||||
}
|
|
||||||
if (port->direction()->isInternal())
|
|
||||||
return findSeqActivity(inst, port);
|
|
||||||
else {
|
|
||||||
Pin *pin = findLinkPin(inst, port);
|
|
||||||
if (pin) {
|
|
||||||
PwrActivity activity = findActivity(pin);
|
|
||||||
activity.setOrigin(PwrActivityOrigin::propagated);
|
|
||||||
return activity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
|
|
||||||
}
|
|
||||||
case FuncExpr::op_not: {
|
|
||||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
return PwrActivity(activity1.activity(),
|
|
||||||
1.0 - activity1.duty(),
|
|
||||||
PwrActivityOrigin::propagated);
|
|
||||||
}
|
|
||||||
case FuncExpr::op_or: {
|
|
||||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
float p1 = 1.0 - activity1.duty();
|
|
||||||
float p2 = 1.0 - activity2.duty();
|
|
||||||
return PwrActivity(activity1.activity() * p2 + activity2.activity() * p1,
|
|
||||||
// d1 + d2 - d1 * d2
|
|
||||||
1.0 - p1 * p2,
|
|
||||||
PwrActivityOrigin::propagated);
|
|
||||||
}
|
|
||||||
case FuncExpr::op_and: {
|
|
||||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
float p1 = activity1.duty();
|
|
||||||
float p2 = activity2.duty();
|
|
||||||
return PwrActivity(activity1.activity() * p2 + activity2.activity() * p1,
|
|
||||||
p1 * p2,
|
|
||||||
PwrActivityOrigin::propagated);
|
|
||||||
}
|
|
||||||
case FuncExpr::op_xor: {
|
|
||||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
|
||||||
cofactor_port, cofactor_positive);
|
|
||||||
float d1 = activity1.duty();
|
|
||||||
float d2 = activity2.duty();
|
|
||||||
float p1 = d1 * (1.0 - d2);
|
|
||||||
float p2 = (1.0 - d1) * d2;
|
|
||||||
return PwrActivity(activity1.activity() + activity2.activity(),
|
|
||||||
p1 + p2,
|
|
||||||
PwrActivityOrigin::propagated);
|
|
||||||
}
|
|
||||||
case FuncExpr::op_one:
|
|
||||||
return PwrActivity(0.0, 1.0, PwrActivityOrigin::constant);
|
|
||||||
case FuncExpr::op_zero:
|
|
||||||
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
|
|
||||||
}
|
|
||||||
return PwrActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eval activity of difference(expr) wrt cofactor port.
|
|
||||||
float
|
|
||||||
Power::evalDiffDuty(FuncExpr *expr,
|
|
||||||
LibertyPort *cofactor_port,
|
|
||||||
const Instance *inst)
|
|
||||||
{
|
|
||||||
// Activity of positive/negative cofactors.
|
|
||||||
PwrActivity pos = evalActivity(expr, inst, cofactor_port, true);
|
|
||||||
PwrActivity neg = evalActivity(expr, inst, cofactor_port, false);
|
|
||||||
// difference = xor(pos, neg).
|
|
||||||
float p1 = pos.duty() * (1.0 - neg.duty());
|
|
||||||
float p2 = neg.duty() * (1.0 - pos.duty());
|
|
||||||
return p1 + p2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CUDD
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -16,30 +16,11 @@
|
||||||
|
|
||||||
#include "Bdd.hh"
|
#include "Bdd.hh"
|
||||||
|
|
||||||
|
#include "cudd.h"
|
||||||
#include "StaConfig.hh"
|
#include "StaConfig.hh"
|
||||||
#include "Report.hh"
|
#include "Report.hh"
|
||||||
#include "FuncExpr.hh"
|
#include "FuncExpr.hh"
|
||||||
|
|
||||||
#if CUDD
|
|
||||||
#include "cudd.h"
|
|
||||||
#else
|
|
||||||
#include <cstdint>
|
|
||||||
#define CUDD_UNIQUE_SLOTS 0
|
|
||||||
#define CUDD_CACHE_SLOTS 0
|
|
||||||
DdManager *Cudd_Init(int, int, int, int, int) { return nullptr; }
|
|
||||||
void Cudd_Quit(void *) {}
|
|
||||||
DdNode *Cudd_Not(void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_bddOr(void *, void *, void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_bddAnd(void *, void *, void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_bddXor(void *, void *, void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_ReadOne(void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_ReadLogicZero(void *) { return nullptr; }
|
|
||||||
DdNode *Cudd_bddNewVar(void *) { return nullptr; }
|
|
||||||
int Cudd_NodeReadIndex(void *) { return 0;}
|
|
||||||
void Cudd_Ref(void *) {}
|
|
||||||
void Cudd_RecursiveDeref(void *, void *) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
Bdd::Bdd(const StaState *sta) :
|
Bdd::Bdd(const StaState *sta) :
|
||||||
|
|
|
||||||
287
search/Sim.cc
287
search/Sim.cc
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
#include "Sim.hh"
|
#include "Sim.hh"
|
||||||
|
|
||||||
#include "StaConfig.hh" // CUDD
|
// https://davidkebo.com/cudd
|
||||||
|
#include "cudd.h"
|
||||||
|
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "Mutex.hh"
|
#include "Mutex.hh"
|
||||||
#include "Debug.hh"
|
#include "Debug.hh"
|
||||||
|
|
@ -32,14 +34,6 @@
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
|
|
||||||
#if CUDD
|
|
||||||
// https://davidkebo.com/cudd
|
|
||||||
#include "cudd.h"
|
|
||||||
#else
|
|
||||||
#define Cudd_Init(ignore1, ignore2, ignore3, ignore4, ignore5) nullptr
|
|
||||||
#define Cudd_Quit(ignore1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
static LogicValue
|
static LogicValue
|
||||||
|
|
@ -69,8 +63,6 @@ Sim::~Sim()
|
||||||
delete observer_;
|
delete observer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CUDD
|
|
||||||
|
|
||||||
TimingSense
|
TimingSense
|
||||||
Sim::functionSense(const FuncExpr *expr,
|
Sim::functionSense(const FuncExpr *expr,
|
||||||
const Pin *input_pin,
|
const Pin *input_pin,
|
||||||
|
|
@ -159,279 +151,6 @@ Sim::funcBddSim(const FuncExpr *expr,
|
||||||
return bdd;
|
return bdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
// No CUDD.
|
|
||||||
|
|
||||||
static LogicValue
|
|
||||||
logicOr(LogicValue value1,
|
|
||||||
LogicValue value2)
|
|
||||||
{
|
|
||||||
static LogicValue logic_or[5][5] =
|
|
||||||
{{LogicValue::zero, LogicValue::one, LogicValue::unknown, LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::one, LogicValue::one, LogicValue::one, LogicValue::one, LogicValue::one},
|
|
||||||
{LogicValue::unknown,LogicValue::one, LogicValue::unknown, LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::unknown,LogicValue::one, LogicValue::unknown, LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::unknown,LogicValue::one, LogicValue::unknown, LogicValue::unknown, LogicValue::unknown}};
|
|
||||||
return logic_or[int(value1)][int(value2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
static LogicValue
|
|
||||||
logicAnd(LogicValue value1,
|
|
||||||
LogicValue value2)
|
|
||||||
{
|
|
||||||
static LogicValue logic_and[5][5] =
|
|
||||||
{{LogicValue::zero,LogicValue::zero, LogicValue::zero, LogicValue::zero, LogicValue::zero},
|
|
||||||
{LogicValue::zero,LogicValue::one, LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::zero,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::zero,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::zero,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown}};
|
|
||||||
return logic_and[int(value1)][int(value2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
static LogicValue
|
|
||||||
logicXor(LogicValue value1,
|
|
||||||
LogicValue value2)
|
|
||||||
{
|
|
||||||
static LogicValue logic_xor[5][5]=
|
|
||||||
{{LogicValue::zero, LogicValue::one, LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::one, LogicValue::zero, LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::unknown,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::unknown,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown},
|
|
||||||
{LogicValue::unknown,LogicValue::unknown,LogicValue::unknown,LogicValue::unknown, LogicValue::unknown}};
|
|
||||||
return logic_xor[int(value1)][int(value2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
static TimingSense
|
|
||||||
senseNot(TimingSense sense)
|
|
||||||
{
|
|
||||||
static TimingSense sense_not[5] = {TimingSense::negative_unate,
|
|
||||||
TimingSense::positive_unate,
|
|
||||||
TimingSense::non_unate,
|
|
||||||
TimingSense::none,
|
|
||||||
TimingSense::unknown};
|
|
||||||
return sense_not[int(sense)];
|
|
||||||
}
|
|
||||||
|
|
||||||
static TimingSense
|
|
||||||
senseAndOr(TimingSense sense1,
|
|
||||||
TimingSense sense2)
|
|
||||||
{
|
|
||||||
static TimingSense sense_and_or[5][5] =
|
|
||||||
{{TimingSense::positive_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::positive_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::non_unate, TimingSense::negative_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::negative_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::non_unate, TimingSense::non_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::positive_unate, TimingSense::negative_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::none, TimingSense::unknown},
|
|
||||||
{TimingSense::unknown, TimingSense::unknown,
|
|
||||||
TimingSense::unknown, TimingSense::non_unate, TimingSense::unknown}};
|
|
||||||
return sense_and_or[int(sense1)][int(sense2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
static TimingSense
|
|
||||||
senseXor(TimingSense sense1,
|
|
||||||
TimingSense sense2)
|
|
||||||
{
|
|
||||||
static TimingSense xor_sense[5][5] =
|
|
||||||
{{TimingSense::non_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::non_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::non_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::non_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::non_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::non_unate, TimingSense::unknown},
|
|
||||||
{TimingSense::non_unate, TimingSense::non_unate,
|
|
||||||
TimingSense::non_unate, TimingSense::none, TimingSense::unknown},
|
|
||||||
{TimingSense::unknown, TimingSense::unknown,
|
|
||||||
TimingSense::unknown, TimingSense::unknown, TimingSense::unknown}};
|
|
||||||
return xor_sense[int(sense1)][int(sense2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
TimingSense
|
|
||||||
Sim::functionSense(const FuncExpr *expr,
|
|
||||||
const Pin *input_pin,
|
|
||||||
const Instance *inst)
|
|
||||||
{
|
|
||||||
TimingSense sense = TimingSense::none;
|
|
||||||
LogicValue value = LogicValue::unknown;
|
|
||||||
functionSense(expr, input_pin, inst, sense, value);
|
|
||||||
return sense;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Sim::functionSense(const FuncExpr *expr,
|
|
||||||
const Pin *input_pin,
|
|
||||||
const Instance *inst,
|
|
||||||
// return values
|
|
||||||
TimingSense &sense,
|
|
||||||
LogicValue &value) const
|
|
||||||
{
|
|
||||||
switch (expr->op()) {
|
|
||||||
case FuncExpr::op_port: {
|
|
||||||
Pin *pin = network_->findPin(inst, expr->port());
|
|
||||||
if (pin) {
|
|
||||||
if (pin == input_pin)
|
|
||||||
sense = TimingSense::positive_unate;
|
|
||||||
else
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = logicValue(pin);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::unknown;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_not: {
|
|
||||||
TimingSense sense1;
|
|
||||||
LogicValue value1;
|
|
||||||
functionSense(expr->left(), input_pin, inst, sense1, value1);
|
|
||||||
if (value1 == LogicValue::zero) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::one;
|
|
||||||
}
|
|
||||||
else if (value1 == LogicValue::one) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::zero;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sense = senseNot(sense1);
|
|
||||||
value = LogicValue::unknown;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_or: {
|
|
||||||
TimingSense sense1, sense2;
|
|
||||||
LogicValue value1, value2;
|
|
||||||
functionSense(expr->left(), input_pin, inst, sense1, value1);
|
|
||||||
functionSense(expr->right(), input_pin, inst, sense2, value2);
|
|
||||||
if (value1 == LogicValue::one || value2 == LogicValue::one) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::one;
|
|
||||||
}
|
|
||||||
else if (value1 == LogicValue::zero) {
|
|
||||||
sense = sense2;
|
|
||||||
value = value2;
|
|
||||||
}
|
|
||||||
else if (value2 == LogicValue::zero) {
|
|
||||||
sense = sense1;
|
|
||||||
value = value1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sense = senseAndOr(sense1, sense2);
|
|
||||||
value = LogicValue::unknown;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_and: {
|
|
||||||
TimingSense sense1, sense2;
|
|
||||||
LogicValue value1, value2;
|
|
||||||
functionSense(expr->left(), input_pin, inst, sense1, value1);
|
|
||||||
functionSense(expr->right(), input_pin, inst, sense2, value2);
|
|
||||||
if (value1 == LogicValue::zero || value2 == LogicValue::zero) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::zero;
|
|
||||||
}
|
|
||||||
else if (value1 == LogicValue::one) {
|
|
||||||
sense = sense2;
|
|
||||||
value = value2;
|
|
||||||
}
|
|
||||||
else if (value2 == LogicValue::one) {
|
|
||||||
sense = sense1;
|
|
||||||
value = value1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sense = senseAndOr(sense1, sense2);
|
|
||||||
value = LogicValue::unknown;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_xor: {
|
|
||||||
TimingSense sense1, sense2;
|
|
||||||
LogicValue value1, value2;
|
|
||||||
functionSense(expr->left(), input_pin, inst, sense1, value1);
|
|
||||||
functionSense(expr->right(), input_pin, inst, sense2, value2);
|
|
||||||
if ((value1 == LogicValue::zero && value2 == LogicValue::zero)
|
|
||||||
|| (value1 == LogicValue::one && value2 == LogicValue::one)) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::zero;
|
|
||||||
}
|
|
||||||
else if ((value1 == LogicValue::zero && value2 == LogicValue::one)
|
|
||||||
|| (value1 == LogicValue::one && value2 == LogicValue::zero)) {
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::one;
|
|
||||||
}
|
|
||||||
else if (value1 == LogicValue::zero) {
|
|
||||||
sense = sense2;
|
|
||||||
value = value2;
|
|
||||||
}
|
|
||||||
else if (value1 == LogicValue::one) {
|
|
||||||
sense = senseNot(sense2);
|
|
||||||
value = logicNot(value2);
|
|
||||||
}
|
|
||||||
else if (value2 == LogicValue::zero) {
|
|
||||||
sense = sense1;
|
|
||||||
value = value1;
|
|
||||||
}
|
|
||||||
else if (value2 == LogicValue::one) {
|
|
||||||
sense = senseNot(sense1);
|
|
||||||
value = logicNot(value1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sense = senseXor(sense1, sense2);
|
|
||||||
value = logicXor(value1, value2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_one:
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::one;
|
|
||||||
break;
|
|
||||||
case FuncExpr::op_zero:
|
|
||||||
sense = TimingSense::none;
|
|
||||||
value = LogicValue::zero;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogicValue
|
|
||||||
Sim::evalExpr(const FuncExpr *expr,
|
|
||||||
const Instance *inst)
|
|
||||||
{
|
|
||||||
switch (expr->op()) {
|
|
||||||
case FuncExpr::op_port: {
|
|
||||||
LibertyPort *port = expr->port();
|
|
||||||
if (port) {
|
|
||||||
Pin *pin = network_->findPin(inst, port->name());
|
|
||||||
if (pin)
|
|
||||||
return logicValue(pin);
|
|
||||||
}
|
|
||||||
// Internal ports don't have instance pins.
|
|
||||||
return LogicValue::unknown;
|
|
||||||
}
|
|
||||||
case FuncExpr::op_not:
|
|
||||||
return logicNot(evalExpr(expr->left(), inst));
|
|
||||||
case FuncExpr::op_or:
|
|
||||||
return logicOr(evalExpr(expr->left(),inst),
|
|
||||||
evalExpr(expr->right(),inst));
|
|
||||||
case FuncExpr::op_and:
|
|
||||||
return logicAnd(evalExpr(expr->left(),inst),
|
|
||||||
evalExpr(expr->right(),inst));
|
|
||||||
case FuncExpr::op_xor:
|
|
||||||
return logicXor(evalExpr(expr->left(),inst),
|
|
||||||
evalExpr(expr->right(),inst));
|
|
||||||
case FuncExpr::op_one:
|
|
||||||
return LogicValue::one;
|
|
||||||
case FuncExpr::op_zero:
|
|
||||||
return LogicValue::zero;
|
|
||||||
}
|
|
||||||
// Prevent warnings from lame compilers.
|
|
||||||
return LogicValue::zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CUDD
|
|
||||||
|
|
||||||
static LogicValue
|
static LogicValue
|
||||||
logicNot(LogicValue value)
|
logicNot(LogicValue value)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
#cmakedefine ZLIB_FOUND
|
#cmakedefine ZLIB_FOUND
|
||||||
|
|
||||||
#define CUDD ${CUDD}
|
|
||||||
|
|
||||||
#define SSTA ${SSTA}
|
#define SSTA ${SSTA}
|
||||||
|
|
||||||
#define TCL_READLINE ${TCL_READLINE}
|
#define TCL_READLINE ${TCL_READLINE}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue