3 #include <boost/fusion/include/at_c.hpp>
4 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
5 #include <boost/spirit/home/x3.hpp>
442 class ContextABC final
465 char* Io_WriteVerilogGetName(
char* pName)
467 static char Buffer[500];
468 int i, Length = strlen(pName);
469 if (pName[0] <
'0' || pName[0] >
'9')
471 for (i = 0; i < Length; i++)
473 if (!((pName[i] >=
'a' && pName[i] <=
'z') || (pName[i] >=
'A' && pName[i] <=
'Z') || (pName[i] >=
'0' && pName[i] <=
'9') || pName[i] ==
'_'))
485 for (i = 0; i < Length; i++)
487 Buffer[i + 1] = pName[i];
489 Buffer[Length + 1] =
' ';
490 Buffer[Length + 2] = 0;
499 if (nCap > 0 && nCap < 8)
505 p->
pArray = p->
nCap ? (
void**)malloc(
sizeof(
void*) * p->
nCap) : NULL;
517 #define ABC_FREE(obj) ((obj) ? (free((char*)(obj)), (obj) = 0) : 0)
546 std::vector<std::string> get_output_variables(
const BooleanFunction&
function)
548 std::vector<std::string> outputs;
549 outputs.reserve(
function.size());
550 for (
auto bit = 0u; bit <
function.size(); bit++)
552 outputs.emplace_back(
"output_" + std::to_string(bit));
564 Result<BooleanFunction> slice_at(
const BooleanFunction&
function,
const u16 index)
574 return ERR(res.get_error());
588 Result<Abc_Ntk_t*> translate_to_abc(
const BooleanFunction&
function)
599 auto translate = [](
const auto& node,
auto&& operands,
const auto& input2abc,
auto network) -> Result<Abc_Obj_t*> {
601 if (node.get_arity() != operands.size())
603 return ERR(
"could not translate Boolean function to ABC notation: invalid number of parameters");
618 return OK(input2abc.at(node.variable));
630 return ERR(
"could not translate Boolean function to ABC notation: not implemented for given node type " + std::to_string(node.type));
638 std::map<std::string, Abc_Obj_t*> input2abc;
639 for (
auto variable :
function.get_variable_names())
644 input2abc[variable] = object;
647 const auto output_variables = get_output_variables(
function);
648 for (
auto i = 0u; i < output_variables.size(); i++)
650 auto status = slice_at(
function, i);
654 "could not translate Boolean function to ABC notation: unable to slice Boolean function'" +
function.to_string() +
"' at index " + std::to_string(i));
658 std::vector<Abc_Obj_t*> stack;
659 for (
const auto& node :
status.get().get_nodes())
661 std::vector<Abc_Obj_t*> operands;
662 std::move(stack.end() -
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(operands));
663 stack.erase(stack.end() -
static_cast<i64>(node.get_arity()), stack.end());
665 auto translation =
translate(node, std::move(operands), input2abc, network);
666 if (translation.is_ok())
668 stack.emplace_back(translation.get());
672 return ERR(translation.get_error());
677 if (stack.size() != 1)
679 return ERR(
"could not translate Boolean function to ABC notation: number of elements remaining on the stack is not 1");
695 return ERR(
"could not translate Boolean function to ABC notation: AbcNtkCheck() failed");
707 Result<std::monostate> simplify(
Abc_Ntk_t* network)
754 Result<std::string> translate_from_abc()
756 std::stringstream ss;
767 auto vLevels = Vec_VecAlloc(10);
768 for (
int i = 0; i < network->
vObjs->
nSize; i++)
785 return ERR(
"could not translate Boolean function from ABC notation: 'node->fPersist' is set within ABC context");
789 for (
int j = 0; (j < node->vFanins.nSize) && (((pFanin) = Abc_ObjFanin(node, j)), 1); j++)
795 const auto lhs = std::string(Io_WriteVerilogGetName(
Abc_ObjName((
Abc_Obj_t*)node->pNtk->vObjs->pArray[node->vFanouts.pArray[0]])));
803 auto stream = open_memstream(&rhs, &len);
808 ss <<
"assign " << lhs <<
" = " << rhs <<
";" << std::endl;
812 Vec_VecFree(vLevels);
824 Result<BooleanFunction> translate_from_verilog(
const std::string& verilog,
const BooleanFunction&
function)
833 auto parse_assignment = [](
const auto& assignment) -> Result<std::tuple<BooleanFunction, BooleanFunction>> {
834 Result<BooleanFunction> lhs =
ERR(
""), rhs =
ERR(
"");
836 namespace x3 = boost::spirit::x3;
849 const auto EndOfLineRule = x3::lit(
";") >> *x3::space;
850 const auto RHSRule = x3::lexeme[*x3::char_(
"a-zA-Z0-9_+*~|&!'()[]\\ ")][RHSAction];
851 const auto EqualSignRule = *x3::space >> x3::lit(
"=") >> *x3::space;
852 const auto LHSRule = x3::lexeme[*x3::char_(
"a-zA-Z0-9_")][LHSAction];
853 const auto AssignRule = *x3::space >> x3::lit(
"assign") >> *x3::space;
856 auto iter = assignment.begin();
857 const auto ok = x3::phrase_parse(iter,
862 AssignRule >> LHSRule >> EqualSignRule >> RHSRule >> EndOfLineRule,
868 if (!ok || (iter != assignment.end()))
870 return ERR(
"could not parse assignment from Verilog notation: '" + assignment +
"' (remaining '" + std::string(iter, assignment.end()) +
"')");
875 return ERR_APPEND(lhs.get_error(),
"cannot parse assignment from Verilog notation: unable to translate left side of assignment '" + assignment +
"' into a Boolean function");
879 return ERR_APPEND(rhs.get_error(),
"cannot parse assignment from Verilog notation: unable to translate right side of assignment '" + assignment +
"' into a Boolean function");
882 return OK({lhs.get(), rhs.get()});
885 std::map<BooleanFunction, BooleanFunction> assignments;
888 std::istringstream
data(verilog);
890 while (std::getline(data, line))
892 if (
auto assignment = parse_assignment(line); assignment.is_ok())
894 auto [lhs, rhs] = assignment.get();
895 assignments[lhs] = rhs;
900 const auto output_variables = get_output_variables(
function);
901 for (
const auto& output_variable : output_variables)
905 return ERR(
"could not parse assignment from Verilog notation: unable to simplify Boolean function'" +
function.to_string() +
"' as output variable is not defined in Verilog");
912 const auto inputs =
function.get_variable_names();
913 for (
const auto& output_variable : output_variables)
920 while ((assignments[output].get_variable_names() != inputs) && (counter++ < assignments.size()))
922 for (
const auto& tmp : assignments[output].get_variable_names())
924 if (inputs.find(tmp) != inputs.end())
929 if (simplified.is_error())
931 return ERR(simplified.get_error());
934 assignments[
output] = simplified.get();
940 for (
const auto& output_variable : output_variables)
942 for (
const auto& input : assignments[
BooleanFunction::Var(output_variable)].get_variable_names())
944 if (inputs.find(input) == inputs.end())
946 return ERR(
"could not parse assignment from Verilog notation: unable to replace output variable '" + output_variable +
"' as it contains temporary variable '" + input +
"'");
953 for (
auto i = 1u; i <
function.size(); i++)
959 state = concat.get();
983 static ContextABC context;
988 static const std::set<u16> valid_abc_node_types({
996 if (
function.get_variable_names().empty())
998 return OK(
function.clone());
1001 if (
auto nodes =
function.get_nodes(); std::any_of(
1002 nodes.begin(), nodes.end(), [](
auto node) { return (valid_abc_node_types.find(node.type) == valid_abc_node_types.end()) || (node.type = NodeType::Variable && node.size != 1); }))
1004 return OK(
function.clone());
1010 static std::mutex mutex;
1013 auto status = translate_to_abc(
function).map<std::monostate>([](
const auto& network) {
return simplify(network); });
1017 return ERR_APPEND(
status.get_error(),
"could not simplyfy Boolean function using ABC: unable to translate & simplify Boolean function '" +
function.to_string() +
"'");
1021 auto translated_function = translate_from_abc().map<
BooleanFunction>([&
function](
const auto& verilog) {
return translate_from_verilog(verilog,
function); });
1025 if (translated_function.is_ok())
1027 return translated_function;
1031 return OK(
function.clone());
static BooleanFunction Var(const std::string &name, u16 size=1)
static Result< BooleanFunction > Concat(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static BooleanFunction Index(u16 index, u16 size)
static Result< BooleanFunction > from_string(const std::string &expression)
static Result< BooleanFunction > Slice(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
#define ERR_APPEND(prev_error, message)
Result< BooleanFunction > translate(std::vector< Token > &&tokens, const std::string &expression)
BooleanFunction Or(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Not(const std::vector< BooleanFunction::Value > &p)
BooleanFunction Xor(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction And(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
Result< BooleanFunction > local_simplification(const BooleanFunction &function)
Result< BooleanFunction > abc_simplification(const BooleanFunction &function)
if(BUILD_TESTS) include_directories($
struct Abc_ManTime_t_ Abc_ManTime_t
void Hop_ObjPrintVerilog(FILE *, Hop_Obj_t *, Vec_Vec_t *, int, int)
char * Abc_ObjAssignName(Abc_Obj_t *, char *, char *)
Abc_Obj_t * Abc_AigConst1(Abc_Ntk_t *)
struct Mem_Fixed_t_ Mem_Fixed_t
void Abc_FrameReplaceCurrentNetwork(Abc_Frame_t *, Abc_Ntk_t *)
void Abc_NtkDelete(Abc_Ntk_t *)
struct Mem_Step_t_ Mem_Step_t
struct Abc_Cex_t_ Abc_Cex_t
Abc_ObjType_t
Copied from "src/base/abc/abc.h", see above for link to ABC's repository.
void(* Abc_Frame_Callback_BmcFrameDone_Func)(int, int, int)
struct Abc_Nam_t_ Abc_Nam_t
struct Dsd_Manager_t_ DdManager
struct Abc_Aig_t_ Abc_Aig_t
Abc_Ntk_t * Abc_NtkToNetlist(Abc_Ntk_t *)
Abc_NtkType_t
Copied from "src/base/abc/abc.h", see above for link to ABC's repository.
int Abc_AigCleanup(Abc_Aig_t *)
struct Gia_Man_t_ Gia_Man_t
struct Abc_Des_t_ Abc_Des_t
Hop_Obj_t * Hop_IthVar(Hop_Man_t *p, int i)
Abc_Obj_t * Abc_AigOr(Abc_Aig_t *, Abc_Obj_t *, Abc_Obj_t *)
Abc_Ntk_t * Abc_NtkAlloc(Abc_NtkType_t, Abc_NtkFunc_t, int)
Abc_Obj_t * Abc_AigXor(Abc_Aig_t *, Abc_Obj_t *, Abc_Obj_t *)
Hop_Type_t
Copied from "src/aig/hop/hop.h", see above for link to ABC's repository.
char * Abc_ObjName(Abc_Obj_t *)
Abc_Obj_t * Abc_NtkCreateObj(Abc_Ntk_t *, Abc_ObjType_t)
struct Nm_Man_t_ Nm_Man_t
int Abc_NtkCheck(Abc_Ntk_t *)
void Abc_ObjAddFanin(Abc_Obj_t *, Abc_Obj_t *)
struct Vec_Wec_t_ Vec_Wec_t
Abc_Frame_t * Abc_FrameGetGlobalFrame()
char * Extra_UtilStrsav(const char *)
Abc_NtkFunc_t
Copied from "src/base/abc/abc.h", see above for link to ABC's repository.
int Abc_NtkToAig(Abc_Ntk_t *)
void Abc_FrameClearVerifStatus(Abc_Frame_t *)
int Cmd_CommandExecute(Abc_Frame_t *, const char *)
struct st__table st__table
Abc_Obj_t * Abc_AigAnd(Abc_Aig_t *, Abc_Obj_t *, Abc_Obj_t *)
Vec_Ptr_t * vLTLProperties_global
Abc_Frame_Callback_BmcFrameDone_Func pFuncOnFrameDone
Vec_Ptr_t * vPlugInComBinPairs
Abc_Ntk_t * pNtkBestDelay
int nObjCounts[ABC_OBJ_NUMBER]
Vec_Ptr_t * vLtlProperties
static constexpr u16 Variable