static void btor_delete_btor_parser (BtorBTORParser * parser) { BtorNode *e; int i; for (i = 0; i < BTOR_COUNT_STACK (parser->exps); i++) if ((e = parser->exps.start[i])) btor_release_exp (parser->btor, parser->exps.start[i]); BTOR_RELEASE_STACK (parser->mem, parser->exps); BTOR_RELEASE_STACK (parser->mem, parser->info); BTOR_RELEASE_STACK (parser->mem, parser->inputs); BTOR_RELEASE_STACK (parser->mem, parser->outputs); BTOR_RELEASE_STACK (parser->mem, parser->regs); BTOR_RELEASE_STACK (parser->mem, parser->nexts); BTOR_RELEASE_STACK (parser->mem, parser->op); BTOR_RELEASE_STACK (parser->mem, parser->constant); BTOR_RELEASE_STACK (parser->mem, parser->symbol); BTOR_DELETEN (parser->mem, parser->parsers, SIZE_PARSERS); BTOR_DELETEN (parser->mem, parser->ops, SIZE_PARSERS); btor_freestr (parser->mem, parser->error); BTOR_DELETE (parser->mem, parser); }
void boolector_enable_model_gen (Btor * btor) { BTOR_ABORT_ARG_NULL_BOOLECTOR (btor); BTOR_ABORT_BOOLECTOR (BTOR_COUNT_STACK (btor->id_table) > 1, "enabling model generation must be done before creating expressions"); btor_enable_model_gen (btor); }
static BtorNode * parse_consth (BtorBTORParser * parser, int len) { char * tmp, * extended; BtorNode *res; int ch, clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF && ch != ';') { if (!isxdigit (ch)) { (void) btor_perr_btor (parser, "expected hexidecimal digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); } btor_savech_btor (parser, ch); clen = BTOR_COUNT_STACK (parser->constant); BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); tmp = btor_hex_to_const_n (parser->mem, parser->constant.start, clen); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "hexadecimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_freestr (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
static void mark_boolean (BtorSMTDumpContext * sdc, BtorNodePtrStack * exps) { int i, j, not_bool; BtorNode *cur; /* collect boolean terms */ for (i = 0; i < BTOR_COUNT_STACK (*exps); i++) { cur = BTOR_PEEK_STACK (*exps, i); /* these nodes are boolean by definition */ if (BTOR_IS_BV_EQ_NODE (cur) || BTOR_IS_FUN_EQ_NODE (cur) || BTOR_IS_ULT_NODE (cur) || cur == BTOR_REAL_ADDR_NODE (sdc->btor->true_exp)) { btor_insert_in_ptr_hash_table (sdc->boolean, cur); continue; } else if (BTOR_IS_APPLY_NODE (cur)) { /* boolean function */ if ((BTOR_IS_LAMBDA_NODE (cur->e[0]) && is_boolean (sdc, btor_lambda_get_body (cur->e[0]))) || (BTOR_IS_FUN_COND_NODE (cur->e[0]) && is_boolean (sdc, cur->e[1])) || (BTOR_IS_UF_NODE (cur->e[0]) && btor_is_bool_sort (&sdc->btor->sorts_unique_table, btor_get_codomain_fun_sort ( &sdc->btor->sorts_unique_table, cur->e[0]->sort_id)))) btor_insert_in_ptr_hash_table (sdc->boolean, cur); continue; } else if ((BTOR_IS_AND_NODE (cur) || BTOR_IS_BV_COND_NODE (cur)) && btor_get_exp_width (sdc->btor, cur) == 1) { not_bool = 0; for (j = 0; j < cur->arity; j++) { if (!is_boolean (sdc, cur->e[j])) { not_bool = 1; break; } } if (not_bool) continue; btor_insert_in_ptr_hash_table (sdc->boolean, cur); } } }
void boolector_set_rewrite_level (Btor * btor, int rewrite_level) { BTOR_ABORT_ARG_NULL_BOOLECTOR (btor); BTOR_ABORT_BOOLECTOR (rewrite_level < 0 || rewrite_level > 3, "'rewrite_level' has to be in [0,3]"); BTOR_ABORT_BOOLECTOR (BTOR_COUNT_STACK (btor->id_table) > 1, "setting rewrite level must be done before creating expressions"); btor_set_rewrite_level_btor (btor, rewrite_level); }
static BtorNode * parse_exp (BtorBTORParser * parser, int expected_len, int can_be_array) { int lit, idx, len_res; BtorNode *res; lit = 0; if (parse_non_zero_int (parser, &lit)) return 0; idx = abs (lit); assert (idx); if (idx >= BTOR_COUNT_STACK (parser->exps) || !(res = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "literal '%d' undefined", lit); return 0; } if (!can_be_array && btor_is_array_exp (parser->btor, res)) { (void) btor_perr_btor (parser, "literal '%d' refers to an unexpected array expression", lit); return 0; } if (expected_len) { len_res = btor_get_exp_len (parser->btor, res); if (expected_len != len_res) { (void) btor_perr_btor (parser, "literal '%d' has length '%d' but expected '%d'", lit, len_res, expected_len); return 0; } } if (lit < 0) res = btor_not_exp (parser->btor, res); else res = btor_copy_exp (parser->btor, res); return res; }
char * btor_const_to_decimal (BtorMemMgr * mem, const char *c) { char *res, *q, *tmp, *rem, ch; BtorCharStack stack; const char *p; int len; BTOR_INIT_STACK (stack); assert (mem != NULL); assert (c != NULL); assert (is_valid_const (c)); res = btor_copy_const (mem, c); while (*res) { tmp = btor_udiv_unbounded_const (mem, res, "1010", &rem); /* / 10 */ assert ((int) strlen (rem) <= 4); ch = 0; for (p = strip_zeroes (rem); *p; p++) { ch <<= 1; if (*p == '1') ch++; } assert (ch < 10); ch += '0'; BTOR_PUSH_STACK (mem, stack, ch); btor_delete_const (mem, rem); btor_delete_const (mem, res); res = tmp; } btor_delete_const (mem, res); if (BTOR_EMPTY_STACK (stack)) BTOR_PUSH_STACK (mem, stack, '0'); len = BTOR_COUNT_STACK (stack); BTOR_NEWN (mem, res, len + 1); q = res; p = stack.top; while (p > stack.start) *q++ = *--p; assert (res + len == q); *q = 0; assert (len == (int) strlen (res)); BTOR_RELEASE_STACK (mem, stack); return res; }
static BtorNode * parse_next (BtorBTORParser * parser, int len) { int idx; BtorNode * current, * next; Info info; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx)) return 0; if (idx >= BTOR_COUNT_STACK (parser->exps) || !(current = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "invalid next index %d", idx); return 0; } info = parser->info.start[idx]; if (!info.var) { (void) btor_perr_btor (parser, "next index %d is not a variable", idx); return 0; } if (info.next) { (void) btor_perr_btor (parser, "next index %d already used", idx); return 0; } if (parse_space (parser)) return 0; assert (!btor_is_array_exp (parser->btor, current)); if (!(next = parse_exp (parser, len, 0))) return 0; BTOR_PUSH_STACK (parser->mem, parser->regs, current); BTOR_PUSH_STACK (parser->mem, parser->nexts, next); parser->info.start[idx].next = 1; return next; }
static BtorNode * parse_const (BtorBTORParser * parser, int len) { BtorNode *res; int ch, clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF && ch != ';') { if (ch != '0' && ch != '1') { (void) btor_perr_btor (parser, "expected '0' or '1'"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); } btor_savech_btor (parser, ch); clen = BTOR_COUNT_STACK (parser->constant); BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); if (clen != len) { (void) btor_perr_btor (parser, "binary constant '%s' exceeds bit width %d", parser->constant.start, len); return 0; } res = btor_const_exp (parser->btor, parser->constant.start); return res; }
static int btor_nextch_btor (BtorBTORParser * parser) { int ch; if (parser->saved) { ch = parser->saved_char; parser->saved = 0; } else if (parser->prefix && parser->nprefix < BTOR_COUNT_STACK (*parser->prefix)) { ch = parser->prefix->start[parser->nprefix++]; } else ch = getc (parser->file); if (ch == '\n') parser->lineno++; return ch; }
static void dump_fun_smt2 (BtorSMTDumpContext * sdc, BtorNode * fun) { assert (fun); assert (sdc); assert (BTOR_IS_REGULAR_NODE (fun)); assert (BTOR_IS_LAMBDA_NODE (fun)); assert (!fun->parameterized); assert (!btor_find_in_ptr_hash_table (sdc->dumped, fun)); int i, refs; BtorNode *cur, *param, *fun_body, *p; BtorMemMgr *mm = sdc->btor->mm; BtorNodePtrStack visit, shared; BtorNodeIterator it, iit; BtorPtrHashTable *mark; BtorPtrHashBucket *b; mark = btor_new_ptr_hash_table (mm, (BtorHashPtr) btor_hash_exp_by_id, (BtorCmpPtr) btor_compare_exp_by_id); BTOR_INIT_STACK (visit); BTOR_INIT_STACK (shared); #if 0 extract_store (sdc, fun, &index, &value, &array); if (index) { assert (value); assert (array); btor_insert_in_ptr_hash_table (sdc->stores, fun); return; } #endif /* collect shared parameterized expressions in function body */ fun_body = btor_lambda_get_body (fun); BTOR_PUSH_STACK (mm, visit, fun_body); while (!BTOR_EMPTY_STACK (visit)) { cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit)); if (btor_find_in_ptr_hash_table (mark, cur) || btor_find_in_ptr_hash_table (sdc->dumped, cur) || BTOR_IS_LAMBDA_NODE (cur)) continue; b = btor_find_in_ptr_hash_table (sdc->dump, cur); assert (b); refs = b->data.asInt; /* args and params are handled differently */ /* collect shared parameterized expressions in function body. * arguments, parameters, and constants are excluded. */ if (!BTOR_IS_ARGS_NODE (cur) && !BTOR_IS_PARAM_NODE (cur) /* constants are always printed */ && !BTOR_IS_BV_CONST_NODE (cur) && cur->parameterized && refs > 1) BTOR_PUSH_STACK (mm, shared, cur); btor_insert_in_ptr_hash_table (mark, cur); for (i = 0; i < cur->arity; i++) BTOR_PUSH_STACK (mm, visit, cur->e[i]); } /* dump function signature */ fputs ("(define-fun ", sdc->file); dump_smt_id (sdc, fun); fputs (" (", sdc->file); btor_init_lambda_iterator (&it, fun); while (btor_has_next_lambda_iterator (&it)) { cur = btor_next_lambda_iterator (&it); param = cur->e[0]; if (!btor_find_in_ptr_hash_table (mark, cur)) btor_insert_in_ptr_hash_table (mark, cur); if (!btor_find_in_ptr_hash_table (mark, param)) btor_insert_in_ptr_hash_table (mark, param); btor_insert_in_ptr_hash_table (sdc->dumped, cur); btor_insert_in_ptr_hash_table (sdc->dumped, param); if (fun != cur) fputc (' ', sdc->file); fputc ('(', sdc->file); dump_smt_id (sdc, param); fputc (' ', sdc->file); btor_dump_sort_smt_node (param, sdc->file); fputc (')', sdc->file); } fputs (") ", sdc->file); // TODO (ma): again wait for aina merge for dump_sort_smt if (is_boolean (sdc, fun_body)) fputs ("Bool", sdc->file); else btor_dump_sort_smt_node (fun_body, sdc->file); fputc (' ', sdc->file); assert (sdc->open_lets == 0); /* dump expressions that are shared in 'fun' */ if (shared.start) qsort (shared.start, BTOR_COUNT_STACK (shared), sizeof (BtorNode *), cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (shared); i++) { cur = BTOR_PEEK_STACK (shared, i); assert (BTOR_IS_REGULAR_NODE (cur)); assert (cur->parameterized); dump_let_smt (sdc, cur); fputc (' ', sdc->file); } recursively_dump_exp_smt (sdc, fun_body, !is_boolean (sdc, fun_body), 0); /* close lets */ for (i = 0; i < sdc->open_lets; i++) fputc (')', sdc->file); sdc->open_lets = 0; /* close define-fun */ fputs (")\n", sdc->file); /* due to lambda hashing it is possible that a lambda in 'fun' is shared in * different functions. hence, we have to check if all lambda parents of * the resp. lambda have already been dumped as otherwise all expressions * below have to be removed from 'sdc->dumped' as they will be dumped * again in a different function definition. */ btor_init_lambda_iterator (&it, fun); while (btor_has_next_lambda_iterator (&it)) { cur = btor_next_lambda_iterator (&it); btor_init_parent_iterator (&iit, cur); while (btor_has_next_parent_iterator (&iit)) { p = btor_next_parent_iterator (&iit); /* find lambda parent that needs to be dumped but has not yet been * dumped */ if (btor_find_in_ptr_hash_table (sdc->dump, p) && !btor_find_in_ptr_hash_table (sdc->dumped, p) && BTOR_IS_LAMBDA_NODE (p)) { BTOR_PUSH_STACK (mm, visit, cur); while (!BTOR_EMPTY_STACK (visit)) { cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit)); assert (BTOR_IS_REGULAR_NODE (cur)); if (!cur->parameterized && (!btor_find_in_ptr_hash_table (mark, cur) || !btor_find_in_ptr_hash_table (sdc->dumped, cur))) continue; if (btor_find_in_ptr_hash_table (sdc->dumped, cur)) btor_remove_from_ptr_hash_table (sdc->dumped, cur, 0, 0); for (i = 0; i < cur->arity; i++) BTOR_PUSH_STACK (mm, visit, cur->e[i]); } break; } } } BTOR_RELEASE_STACK (mm, shared); BTOR_RELEASE_STACK (mm, visit); btor_delete_ptr_hash_table (mark); }
static void recursively_dump_exp_smt (BtorSMTDumpContext * sdc, BtorNode * exp, int expect_bv, unsigned depth_limit) { assert (sdc); assert (exp); assert (btor_find_in_ptr_hash_table (sdc->dump, BTOR_REAL_ADDR_NODE (exp))); unsigned depth; int pad, i, is_bool, add_space, zero_extend, expect_bool; BtorBitVector *bitsbv; char *bits; const char *op, *fmt; BtorNode *arg, *real_exp; BtorArgsIterator it; BtorNodePtrStack dump, args; BtorIntStack expect_bv_stack, expect_bool_stack, depth_stack; BtorIntStack add_space_stack, zero_extend_stack; BtorPtrHashTable *visited; BtorMemMgr *mm; mm = sdc->btor->mm; visited = btor_new_ptr_hash_table (mm, 0, 0); BTOR_INIT_STACK (args); BTOR_INIT_STACK (dump); BTOR_INIT_STACK (expect_bv_stack); BTOR_INIT_STACK (expect_bool_stack); BTOR_INIT_STACK (add_space_stack); BTOR_INIT_STACK (zero_extend_stack); BTOR_INIT_STACK (depth_stack); PUSH_DUMP_NODE (exp, expect_bv, 0, 0, 0, 0); while (!BTOR_EMPTY_STACK (dump)) { assert (!BTOR_EMPTY_STACK (expect_bv_stack)); assert (!BTOR_EMPTY_STACK (expect_bool_stack)); assert (!BTOR_EMPTY_STACK (add_space_stack)); assert (!BTOR_EMPTY_STACK (zero_extend_stack)); assert (!BTOR_EMPTY_STACK (depth_stack)); depth = BTOR_POP_STACK (depth_stack); exp = BTOR_POP_STACK (dump); expect_bv = BTOR_POP_STACK (expect_bv_stack); expect_bool = BTOR_POP_STACK (expect_bool_stack); add_space = BTOR_POP_STACK (add_space_stack); zero_extend = BTOR_POP_STACK (zero_extend_stack); real_exp = BTOR_REAL_ADDR_NODE (exp); is_bool = is_boolean (sdc, real_exp); assert (!expect_bv || !expect_bool); assert (!expect_bool || !expect_bv); /* open s-expression */ if (!btor_find_in_ptr_hash_table (visited, real_exp)) { if (add_space) fputc (' ', sdc->file); /* wrap node with zero_extend */ if (zero_extend) { fmt = " ((_ zero_extend %d) "; fprintf (sdc->file, fmt, zero_extend); } /* always print constants */ if (BTOR_IS_BV_CONST_NODE (real_exp)) { if (exp == sdc->btor->true_exp && !expect_bv) fputs ("true", sdc->file); else if (exp == BTOR_INVERT_NODE (sdc->btor->true_exp) && !expect_bv) fputs ("false", sdc->file); else if (BTOR_IS_INVERTED_NODE (exp)) { bitsbv = btor_not_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); bits = btor_bv_to_char_bv (sdc->btor->mm, bitsbv); dump_const_value_aux_smt (sdc, bits); btor_free_bv (sdc->btor->mm, bitsbv); btor_freestr (sdc->btor->mm, bits); } else { bits = btor_bv_to_char_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); dump_const_value_aux_smt (sdc, bits); btor_freestr (sdc->btor->mm, bits); } /* close zero extend */ if (zero_extend) fputc (')', sdc->file); continue; } /* wrap non-bool node and make it bool */ if (expect_bool && !is_bool) { fputs ("(= ", sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); } /* wrap node with bvnot/not */ if (BTOR_IS_INVERTED_NODE (exp)) fputs (expect_bv || !is_bool ? "(bvnot " : "(not ", sdc->file); /* wrap bool node and make it a bit vector expression */ if (is_bool && expect_bv) fputs ("(ite ", sdc->file); if (btor_find_in_ptr_hash_table (sdc->dumped, real_exp) || BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp)) { #ifndef NDEBUG BtorPtrHashBucket *b; b = btor_find_in_ptr_hash_table (sdc->dump, real_exp); assert (b); /* functions and variables are declared separately */ assert (BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp) || BTOR_IS_BV_VAR_NODE (real_exp) || BTOR_IS_PARAM_NODE (real_exp) || b->data.asInt > 1); #endif dump_smt_id (sdc, exp); goto CLOSE_WRAPPER; } if (depth_limit && depth >= depth_limit) { fprintf (sdc->file, "%s_%d", g_kind2smt[real_exp->kind], real_exp->id); goto CLOSE_WRAPPER; } PUSH_DUMP_NODE (exp, expect_bv, expect_bool, 0, zero_extend, depth); btor_insert_in_ptr_hash_table (visited, real_exp); op = ""; switch (real_exp->kind) { case BTOR_SLL_NODE: case BTOR_SRL_NODE: assert (!is_bool); op = real_exp->kind == BTOR_SRL_NODE ? "bvlshr" : "bvshl"; assert (btor_get_exp_width (sdc->btor, real_exp) > 1); pad = btor_get_exp_width (sdc->btor, real_exp) - btor_get_exp_width (sdc->btor, real_exp->e[1]); PUSH_DUMP_NODE (real_exp->e[1], 1, 0, 1, pad, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 1, 0, depth + 1); break; case BTOR_BCOND_NODE: op = "ite"; PUSH_DUMP_NODE (real_exp->e[2], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[1], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 0, 1, 1, 0, depth + 1); break; case BTOR_APPLY_NODE: /* we need the arguments in reversed order */ btor_init_args_iterator (&it, real_exp->e[1]); while (btor_has_next_args_iterator (&it)) { arg = btor_next_args_iterator (&it); BTOR_PUSH_STACK (mm, args, arg); } while (!BTOR_EMPTY_STACK (args)) { arg = BTOR_POP_STACK (args); // TODO (ma): what about bool arguments/indices PUSH_DUMP_NODE (arg, 1, 0, 1, 0, depth + 1); } PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 0, 0, depth + 1); break; #if 0 case BTOR_LAMBDA_NODE: extract_store (sdc, exp, &index, &value, &array); assert (index); assert (value); assert (array); fputs ("(store ", sdc->file); DUMP_EXP_SMT (array); fputc (' ', sdc->file); DUMP_EXP_SMT (index); fputc (' ', sdc->file); DUMP_EXP_SMT (value); fputc (')', sdc->file); break; #endif default: expect_bv = 1; switch (real_exp->kind) { case BTOR_FEQ_NODE: case BTOR_BEQ_NODE: op = "="; expect_bv = 1; break; case BTOR_ULT_NODE: op = "bvult"; expect_bv = 1; break; case BTOR_SLICE_NODE: assert (!is_bool); op = "(_ extract "; break; case BTOR_AND_NODE: op = is_bool ? "and" : "bvand"; expect_bv = !is_bool; break; case BTOR_ADD_NODE: assert (!is_bool); op = "bvadd"; break; case BTOR_MUL_NODE: assert (!is_bool); op = "bvmul"; break; case BTOR_UDIV_NODE: assert (!is_bool); op = "bvudiv"; break; case BTOR_UREM_NODE: assert (!is_bool); op = "bvurem"; break; case BTOR_CONCAT_NODE: assert (!is_bool); op = "concat"; break; default: assert (0); op = "unknown"; } if (BTOR_IS_AND_NODE (real_exp) && is_bool) { assert (BTOR_EMPTY_STACK (args)); get_children (sdc, exp, &args); for (i = 0; i < BTOR_COUNT_STACK (args); i++) { arg = BTOR_PEEK_STACK (args, i); PUSH_DUMP_NODE (arg, expect_bv, 0, 1, 0, depth + 1); } BTOR_RESET_STACK (args); } else for (i = real_exp->arity - 1; i >= 0; i--) PUSH_DUMP_NODE (real_exp->e[i], expect_bv, 0, 1, 0, depth + 1); } /* open s-expression */ assert (op); fprintf (sdc->file, "(%s", op); if (BTOR_IS_SLICE_NODE (real_exp)) { fmt = "%d %d)"; fprintf (sdc->file, fmt, btor_slice_get_upper (real_exp), btor_slice_get_lower (real_exp)); } } /* close s-expression */ else { if (!btor_find_in_ptr_hash_table (sdc->dumped, real_exp)) btor_insert_in_ptr_hash_table (sdc->dumped, real_exp); /* close s-expression */ if (real_exp->arity > 0) fputc (')', sdc->file); CLOSE_WRAPPER: /* close wrappers */ /* wrap boolean expressions in bit vector expression */ if (is_bool && expect_bv && !BTOR_IS_BV_CONST_NODE (real_exp)) { fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "0"); fputc (')', sdc->file); } /* close bvnot for non-constants */ if (BTOR_IS_INVERTED_NODE (exp) && !BTOR_IS_BV_CONST_NODE (real_exp)) fputc (')', sdc->file); /* close bool wrapper */ if (expect_bool && !is_boolean (sdc, real_exp)) fputc (')', sdc->file); /* close zero extend wrapper */ if (zero_extend) fputc (')', sdc->file); } } assert (BTOR_EMPTY_STACK (expect_bv_stack)); BTOR_RELEASE_STACK (mm, args); BTOR_RELEASE_STACK (mm, dump); BTOR_RELEASE_STACK (mm, expect_bv_stack); BTOR_RELEASE_STACK (mm, expect_bool_stack); BTOR_RELEASE_STACK (mm, add_space_stack); BTOR_RELEASE_STACK (mm, zero_extend_stack); BTOR_RELEASE_STACK (mm, depth_stack); btor_delete_ptr_hash_table (visited); }
void btor_dump_smt2_node (Btor * btor, FILE * file, BtorNode * exp, unsigned depth) { assert (btor); assert (depth); int i; BtorNode *cur, *real_exp; BtorSMTDumpContext *sdc; BtorNodePtrStack visit, all; BtorArgsIterator ait; BtorPtrHashBucket *b; real_exp = BTOR_REAL_ADDR_NODE (exp); BTOR_INIT_STACK (all); BTOR_INIT_STACK (visit); sdc = new_smt_dump_context (btor, file); if (!exp) { fprintf (file, "null\n"); goto CLEANUP; } else if (BTOR_IS_ARGS_NODE (real_exp) || BTOR_IS_PARAM_NODE (real_exp)) { fprintf (file, "%s_%d\n", g_kind2smt[real_exp->kind], real_exp->id); goto CLEANUP; } else if (BTOR_IS_BV_VAR_NODE (exp) || BTOR_IS_UF_NODE (exp)) { dump_declare_fun_smt (sdc, exp); goto CLEANUP; } BTOR_PUSH_STACK (btor->mm, visit, exp); while (!BTOR_EMPTY_STACK (visit)) { cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit)); if (btor_find_in_ptr_hash_table (sdc->dump, cur)) continue; if (BTOR_IS_BV_VAR_NODE (cur) || BTOR_IS_UF_NODE (cur) || (!BTOR_IS_LAMBDA_NODE (real_exp) && BTOR_IS_PARAM_NODE (cur))) btor_insert_in_ptr_hash_table (sdc->dumped, cur); btor_insert_in_ptr_hash_table (sdc->dump, cur); BTOR_PUSH_STACK (btor->mm, all, cur); for (i = 0; i < cur->arity; i++) BTOR_PUSH_STACK (btor->mm, visit, cur->e[i]); } /* compute reference counts of expressions (required for determining shared * expressions)*/ if (all.start) qsort (all.start, BTOR_COUNT_STACK (all), sizeof (BtorNode *), cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (all); i++) { cur = BTOR_PEEK_STACK (all, i); b = btor_find_in_ptr_hash_table (sdc->dump, cur); assert (b); assert (b->data.asInt == 0); /* cache result for later reuse */ b->data.asInt = get_references (sdc, cur); /* update references for expressions under argument nodes */ if (BTOR_IS_ARGS_NODE (cur) && b->data.asInt > 0) { btor_init_args_iterator (&ait, cur); while (btor_has_next_args_iterator (&ait)) { cur = BTOR_REAL_ADDR_NODE (btor_next_args_iterator (&ait)); assert (btor_find_in_ptr_hash_table (sdc->dump, cur)); btor_find_in_ptr_hash_table (sdc->dump, cur)->data.asInt += b->data.asInt; } } } mark_boolean (sdc, &all); if (BTOR_IS_LAMBDA_NODE (BTOR_REAL_ADDR_NODE (exp))) dump_fun_smt2 (sdc, exp); else { recursively_dump_exp_smt (sdc, exp, 0, depth); fprintf (file, "\n"); } CLEANUP: delete_smt_dump_context (sdc); BTOR_RELEASE_STACK (btor->mm, all); BTOR_RELEASE_STACK (btor->mm, visit); }
static void dump_smt (BtorSMTDumpContext * sdc) { assert (sdc); int i, j; BtorNode *e, *cur; BtorMemMgr *mm; BtorNodePtrStack visit, all, vars, shared, ufs; BtorPtrHashBucket *b; BtorHashTableIterator it; BtorArgsIterator ait; mm = sdc->btor->mm; BTOR_INIT_STACK (visit); BTOR_INIT_STACK (shared); BTOR_INIT_STACK (all); BTOR_INIT_STACK (vars); BTOR_INIT_STACK (ufs); btor_init_node_hash_table_iterator (&it, sdc->roots); while (btor_has_next_node_hash_table_iterator (&it)) { cur = btor_next_node_hash_table_iterator (&it); BTOR_PUSH_STACK (mm, visit, BTOR_REAL_ADDR_NODE (cur)); } /* collect constants, variables, array variables and functions */ while (!BTOR_EMPTY_STACK (visit)) { cur = BTOR_POP_STACK (visit); assert (BTOR_IS_REGULAR_NODE (cur)); assert (!btor_find_in_ptr_hash_table (sdc->dumped, cur)); if (btor_find_in_ptr_hash_table (sdc->dump, cur)) continue; btor_insert_in_ptr_hash_table (sdc->dump, cur)->data.asInt = 0; BTOR_PUSH_STACK (mm, all, cur); if (BTOR_IS_BV_VAR_NODE (cur)) BTOR_PUSH_STACK (mm, vars, cur); else if (BTOR_IS_UF_NODE (cur)) BTOR_PUSH_STACK (mm, ufs, cur); else if (BTOR_IS_LAMBDA_NODE (cur) && !cur->parameterized && !has_lambda_parents_only (cur)) BTOR_PUSH_STACK (mm, shared, cur); for (j = 0; j < cur->arity; j++) BTOR_PUSH_STACK (mm, visit, BTOR_REAL_ADDR_NODE (cur->e[j])); } /* compute reference counts of expressions (required for determining shared * expressions)*/ if (all.start) qsort (all.start, BTOR_COUNT_STACK (all), sizeof e, cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (all); i++) { cur = BTOR_PEEK_STACK (all, i); b = btor_find_in_ptr_hash_table (sdc->dump, cur); assert (b); assert (b->data.asInt == 0); /* cache result for later reuse */ b->data.asInt = get_references (sdc, cur); /* update references for expressions under argument nodes */ if (BTOR_IS_ARGS_NODE (cur) && b->data.asInt > 0) { btor_init_args_iterator (&ait, cur); while (btor_has_next_args_iterator (&ait)) { e = BTOR_REAL_ADDR_NODE (btor_next_args_iterator (&ait)); assert (btor_find_in_ptr_hash_table (sdc->dump, e)); btor_find_in_ptr_hash_table (sdc->dump, e)->data.asInt += b->data.asInt; } } } /* collect globally shared expressions */ for (i = 0; i < BTOR_COUNT_STACK (all); i++) { cur = BTOR_PEEK_STACK (all, i); b = btor_find_in_ptr_hash_table (sdc->dump, cur); assert (b); if (b->data.asInt <= 1 /* parameterized expressions are only shared within a function */ || cur->parameterized || BTOR_IS_PARAM_NODE (cur) /* constants are always printed */ || BTOR_IS_BV_CONST_NODE (cur) /* for variables and functions the resp. symbols are always printed */ || BTOR_IS_BV_VAR_NODE (cur) || BTOR_IS_LAMBDA_NODE (cur) || BTOR_IS_UF_NODE (cur) /* argument nodes are never printed */ || BTOR_IS_ARGS_NODE (cur)) continue; BTOR_PUSH_STACK (mm, shared, cur); } /* collect boolean terms */ mark_boolean (sdc, &all); /* begin dump */ if (BTOR_EMPTY_STACK (ufs)) set_logic_smt (sdc, "QF_BV"); else set_logic_smt (sdc, "QF_UFBV"); /* dump inputs */ if (vars.start) qsort (vars.start, BTOR_COUNT_STACK (vars), sizeof e, cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (vars); i++) { cur = BTOR_PEEK_STACK (vars, i); dump_declare_fun_smt (sdc, cur); } if (ufs.start) qsort (ufs.start, BTOR_COUNT_STACK (ufs), sizeof e, cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (ufs); i++) { cur = BTOR_PEEK_STACK (ufs, i); dump_declare_fun_smt (sdc, cur); } /* dump shared expressions and functions */ if (shared.start) qsort (shared.start, BTOR_COUNT_STACK (shared), sizeof e, cmp_node_id); for (i = 0; i < BTOR_COUNT_STACK (shared); i++) { cur = BTOR_PEEK_STACK (shared, i); assert (BTOR_IS_REGULAR_NODE (cur)); if (btor_find_in_ptr_hash_table (sdc->dumped, cur)) continue; assert (!cur->parameterized); if (BTOR_IS_LAMBDA_NODE (cur)) dump_fun_smt2 (sdc, cur); else dump_fun_let_smt2 (sdc, cur); } /* dump assertions/build root */ btor_init_node_hash_table_iterator (&it, sdc->roots); while (btor_has_next_node_hash_table_iterator (&it)) { cur = btor_next_node_hash_table_iterator (&it); dump_assert_smt2 (sdc, cur); } assert (sdc->open_lets == 0); #ifndef NDEBUG btor_init_node_hash_table_iterator (&it, sdc->dump); while (btor_has_next_node_hash_table_iterator (&it)) { cur = btor_next_node_hash_table_iterator (&it); /* constants and function applications are always dumped (hence, not in * mark) */ if (BTOR_IS_BV_CONST_NODE (cur) || BTOR_IS_APPLY_NODE (cur) /* argument nodes are never dumped and not in mark */ || BTOR_IS_ARGS_NODE (cur)) continue; assert (btor_find_in_ptr_hash_table (sdc->dumped, cur)); } #endif BTOR_RELEASE_STACK (mm, shared); BTOR_RELEASE_STACK (mm, visit); BTOR_RELEASE_STACK (mm, all); BTOR_RELEASE_STACK (mm, vars); BTOR_RELEASE_STACK (mm, ufs); fputs ("(check-sat)\n", sdc->file); fputs ("(exit)\n", sdc->file); fflush (sdc->file); }
static unsigned extract_lambdas (Btor * btor, BtorPtrHashTable * map_value_index, BtorPtrHashTable * map_lambda_base) { assert (btor); assert (map_value_index); assert (map_lambda_base); bool is_top_eq; BtorBitVector *inc; unsigned i_range, i_index, i_value, i_inc; BtorNode *subst, *base, *tmp, *array, *value, *lower, *upper; BtorNode *src_array, *src_addr, *dst_addr; BtorHashTableIterator it, iit; BtorPtrHashTable *t, *index_value_map; BtorPtrHashBucket *b; BtorNodePtrStack ranges, indices, values, indices_itoi, indices_itoip1; BtorNodePtrStack indices_cpy, indices_rem, *stack; BtorBitVectorPtrStack increments; BtorMemMgr *mm; /* statistics */ unsigned num_total = 0, num_writes = 0; unsigned num_set = 0, num_set_inc = 0, num_set_itoi = 0, num_set_itoip1 = 0; unsigned num_cpy = 0, size_set = 0, size_set_inc = 0, size_set_itoi = 0; unsigned size_set_itoip1 = 0, size_cpy = 0; mm = btor->mm; BTOR_INIT_STACK (ranges); BTOR_INIT_STACK (indices); BTOR_INIT_STACK (increments); BTOR_INIT_STACK (values); BTOR_INIT_STACK (indices_itoi); BTOR_INIT_STACK (indices_itoip1); BTOR_INIT_STACK (indices_cpy); BTOR_INIT_STACK (indices_rem); btor_init_node_hash_table_iterator (&it, map_value_index); while (btor_has_next_node_hash_table_iterator (&it)) { t = it.bucket->data.asPtr; array = btor_next_node_hash_table_iterator (&it); assert (t); /* find memset patterns, the remaining unused indices are pushed onto * stack 'indices' */ btor_init_node_hash_table_iterator (&iit, t); while (btor_has_next_node_hash_table_iterator (&iit)) { stack = iit.bucket->data.asPtr; value = btor_next_node_hash_table_iterator (&iit); assert (stack); find_ranges (btor, stack, &ranges, &increments, &indices, &num_set, &num_set_inc, &size_set, &size_set_inc); BTOR_RELEASE_STACK (mm, *stack); BTOR_DELETE (mm, stack); BTOR_PUSH_STACK (mm, ranges, 0); BTOR_PUSH_STACK (mm, indices, 0); BTOR_PUSH_STACK (mm, values, value); assert (BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values) > 0 || BTOR_COUNT_STACK (indices) - BTOR_COUNT_STACK (values) > 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) % 2 == 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) / 2 == BTOR_COUNT_STACK (increments)); } /* choose base array for patterns/writes: * 1) write chains: base array of the write chains * 2) top eqs: a new UF symbol */ if ((b = btor_find_in_ptr_hash_table (map_lambda_base, array))) { assert (BTOR_IS_LAMBDA_NODE (array)); b = btor_find_in_ptr_hash_table (map_lambda_base, array); assert (b); subst = btor_copy_exp (btor, b->data.asPtr); is_top_eq = false; } else { assert (BTOR_IS_UF_ARRAY_NODE (array)); subst = btor_array_exp (btor, btor_get_fun_exp_width (btor, array), btor_get_index_exp_width (btor, array), 0); is_top_eq = true; } index_value_map = btor_new_ptr_hash_table (mm, 0, 0); base = subst; i_range = i_index = i_inc = 0; for (i_value = 0; i_value < BTOR_COUNT_STACK (values); i_value++) { value = BTOR_PEEK_STACK (values, i_value); /* create memset regions */ for (; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2) { lower = BTOR_PEEK_STACK (ranges, i_range); /* next value */ if (!lower) { i_range++; break; } upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_memset (btor, lower, upper, value, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); i_inc++; } /* find patterns that are dependent on the current index */ for (; i_index < BTOR_COUNT_STACK (indices); i_index++) { lower = BTOR_PEEK_STACK (indices, i_index); /* next value */ if (!lower) { i_index++; break; } assert (!btor_find_in_ptr_hash_table (index_value_map, lower)); /* save index value pairs for later */ btor_insert_in_ptr_hash_table (index_value_map, lower)->data.asPtr = value; /* pattern 1: index -> index */ if (is_itoi_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoi, lower); /* pattern 2: index -> index + 1 */ else if (is_itoip1_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoip1, lower); /* pattern 3: memcopy pattern */ else if (is_cpy_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_cpy, lower); else /* no pattern found */ BTOR_PUSH_STACK (mm, indices_rem, lower); } } /* pattern: index -> index */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoi, &ranges, &increments, &indices_rem, &num_set_itoi, 0, &size_set_itoi, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoi (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: index -> index + 1 */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoip1, &ranges, &increments, &indices_rem, &num_set_itoip1, 0, &size_set_itoip1, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoip1 (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: memcopy */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_cpy, &ranges, &increments, &indices_rem, &num_cpy, 0, &size_cpy, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (base == subst); assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); b = btor_find_in_ptr_hash_table (index_value_map, lower); value = b->data.asPtr; extract_cpy_src_dst_info (lower, value, &src_array, &src_addr, &dst_addr, 0); /* 'subst' == destination array */ tmp = create_pattern_cpy (btor, lower, upper, src_array, subst, src_addr, dst_addr, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } num_total = num_set + num_set_inc + num_set_itoi + num_set_itoip1 + num_cpy; /* we can skip creating writes if we did not find any pattern in a write * chain, and thus can leave the write chain as-is. * for the top equality case we always have to create writes since we * convert top level equalities to writes. */ if (is_top_eq || num_total > 0) { /* no pattern found for indices in 'indices_rem'. create writes */ for (i_index = 0; i_index < BTOR_COUNT_STACK (indices_rem); i_index++) { lower = BTOR_PEEK_STACK (indices_rem, i_index); b = btor_find_in_ptr_hash_table (index_value_map, lower); assert (b); value = b->data.asPtr; tmp = btor_write_exp (btor, subst, lower, value); btor_release_exp (btor, subst); subst = tmp; num_writes++; } } assert ((is_top_eq || num_total > 0) || base == subst); if (base != subst) btor_insert_substitution (btor, array, subst, 0); btor_release_exp (btor, subst); btor_delete_ptr_hash_table (index_value_map); btor_delete_ptr_hash_table (t); BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (indices); BTOR_RESET_STACK (values); BTOR_RESET_STACK (increments); BTOR_RESET_STACK (indices_itoi); BTOR_RESET_STACK (indices_itoip1); BTOR_RESET_STACK (indices_cpy); BTOR_RESET_STACK (indices_rem); } BTOR_RELEASE_STACK (mm, ranges); BTOR_RELEASE_STACK (mm, indices); BTOR_RELEASE_STACK (mm, values); BTOR_RELEASE_STACK (mm, increments); BTOR_RELEASE_STACK (mm, indices_itoi); BTOR_RELEASE_STACK (mm, indices_itoip1); BTOR_RELEASE_STACK (mm, indices_cpy); BTOR_RELEASE_STACK (mm, indices_rem); BTOR_MSG (btor->msg, 1, "set: %u (%u), " "set_inc: %u (%u), " "set_itoi: %u (%u), " "set_itoip1: %u (%u), " "cpy: %u (%u)", num_set, size_set, num_set_inc, size_set_inc, num_set_itoi, size_set_itoi, num_set_itoip1, size_set_itoip1, num_cpy, size_cpy); return num_total; }
static BtorNode * parse_constd (BtorBTORParser * parser, int len) { char ch, *tmp, * extended; BtorNode *res; int clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); ch = btor_nextch_btor (parser); if (!isdigit (ch)) { (void) btor_perr_btor (parser, "expected digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); if (ch == '0') { ch = btor_nextch_btor (parser); if (isdigit (ch)) { (void) btor_perr_btor (parser, "digit after '0'"); return 0; } tmp = btor_strdup (parser->mem, ""); } else { while (isdigit (ch = btor_nextch_btor (parser))) BTOR_PUSH_STACK (parser->mem, parser->constant, ch); clen = BTOR_COUNT_STACK (parser->constant); tmp = btor_decimal_to_const_n (parser->mem, parser->constant.start, clen); } BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); btor_savech_btor (parser, ch); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "decimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_delete_const (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
void find_ranges (Btor * btor, BtorNodePtrStack * stack, BtorNodePtrStack * ranges, BtorBitVectorPtrStack * increments, BtorNodePtrStack * indices, unsigned * num_pat, unsigned * num_pat_inc, unsigned * size_pat, unsigned * size_pat_inc) { assert (stack); assert (ranges); assert (increments); assert (indices); assert (num_pat); assert (size_pat); #ifndef NDEBUG unsigned num_indices = 0; int i; #endif bool in_range; BtorBitVector *b0, *b1, *inc, *prev_inc; unsigned cnt, lower, upper; unsigned num_pattern = 0, num_pattern_inc = 0, size_pattern = 0; unsigned size_pattern_inc = 0; BtorNode *n0, *n1, *n0_base_addr, *n1_base_addr, *n0_offset, *n1_offset; BtorMemMgr *mm; BtorNodePtrStack index_stack; mm = btor->mm; index_stack = *stack; cnt = BTOR_COUNT_STACK (index_stack); if (cnt == 0) return; if (cnt == 1) BTOR_PUSH_STACK (mm, *indices, BTOR_PEEK_STACK (index_stack, 0)); else { assert (cnt > 1); #ifndef NDEBUG /* sanity check: 'index_stack' contains either absolute or relative * addresses */ for (i = 1; i < BTOR_COUNT_STACK (index_stack); i++) { n0 = BTOR_REAL_ADDR_NODE (BTOR_PEEK_STACK (index_stack, i - 1)); n1 = BTOR_REAL_ADDR_NODE (BTOR_PEEK_STACK (index_stack, i)); assert (n0->kind == n1->kind); assert (BTOR_IS_ADD_NODE (n0) || BTOR_IS_BV_CONST_NODE (n0)); if (BTOR_IS_ADD_NODE (n0)) { extract_base_addr_offset (n0, &n0_base_addr, &n0_offset); extract_base_addr_offset (n1, &n1_base_addr, &n1_offset); assert (n0_base_addr == n1_base_addr); assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n0_offset))); assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n1_offset))); } } #endif qsort (index_stack.start, cnt, sizeof (BtorNode *), cmp_abs_rel_indices); inc = prev_inc = 0; lower = upper = 0; while (upper < cnt) { in_range = false; inc = 0; if (upper + 1 < cnt) { n0 = BTOR_PEEK_STACK (index_stack, upper); n1 = BTOR_PEEK_STACK (index_stack, upper + 1); if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n0))) { assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n1))); b0 = BTOR_CONST_GET_BITS (n0); b1 = BTOR_CONST_GET_BITS (n1); } else { assert (!BTOR_IS_INVERTED_NODE (n0)); assert (!BTOR_IS_INVERTED_NODE (n1)); assert (BTOR_IS_ADD_NODE (n0)); assert (BTOR_IS_ADD_NODE (n1)); extract_base_addr_offset (n0, &n0_base_addr, &n0_offset); extract_base_addr_offset (n1, &n1_base_addr, &n1_offset); assert (n0_base_addr == n1_base_addr); b0 = BTOR_CONST_GET_BITS (n0_offset); b1 = BTOR_CONST_GET_BITS (n1_offset); } assert (b0); assert (b1); inc = btor_sub_bv (mm, b1, b0); if (!prev_inc) prev_inc = btor_copy_bv (mm, inc); /* increment upper bound of range */ in_range = btor_compare_bv (inc, prev_inc) == 0; if (in_range) upper += 1; } if (!in_range) { /* push index */ if (upper == lower) { BTOR_PUSH_STACK (mm, *indices, BTOR_PEEK_STACK (index_stack, lower)); #ifndef NDEBUG num_indices++; #endif goto NEW_RANGE; } /* range is too small, push separate indices */ else if (upper - lower <= 1 /* range with an offset greater than 1 */ && btor_is_power_of_two_bv (prev_inc) != 0) { /* last iteration step: if range contains all indices * up to the last one, we can push all indices */ if (upper == cnt - 1) upper += 1; /* push all indices from lower until upper - 1 */ for (; lower < upper; lower++) { BTOR_PUSH_STACK (mm, *indices, BTOR_PEEK_STACK (index_stack, lower)); #ifndef NDEBUG num_indices++; #endif } /* lower is now that last index in the range, from * which we try to find a new range */ upper += 1; } /* found range */ else { assert (upper - lower > 0); BTOR_PUSH_STACK (mm, *increments, prev_inc); BTOR_PUSH_STACK (mm, *ranges, BTOR_PEEK_STACK (index_stack, lower)); BTOR_PUSH_STACK (mm, *ranges, BTOR_PEEK_STACK (index_stack, upper)); #ifndef NDEBUG num_indices += upper - lower + 1; #endif if (btor_is_one_bv (prev_inc)) { size_pattern += upper - lower + 1; num_pattern++; } else { size_pattern_inc += upper - lower + 1; num_pattern_inc++; } /* 'prev_inc' will be released later */ prev_inc = 0; NEW_RANGE: /* reset range */ upper += 1; lower = upper; if (inc) btor_free_bv (mm, inc); inc = 0; } } if (prev_inc) btor_free_bv (mm, prev_inc); prev_inc = inc; } if (inc) btor_free_bv (mm, inc); assert (num_indices == cnt); } /* return statistics */ if (num_pat) { *num_pat += num_pattern; /* if no separate statistic variable is given for the 'inc' pattern, * we just add the number to the normal one */ if (!num_pat_inc) *num_pat += num_pattern_inc; } if (num_pat_inc) *num_pat_inc += num_pattern_inc; if (size_pat) { *size_pat += size_pattern; /* if no separate statistic variable is given for the 'inc' pattern, * we just add the size to the normal one */ if (!size_pat_inc) *size_pat += size_pattern_inc; } if (size_pat_inc) *size_pat_inc += size_pattern_inc; }
static BtorNode * parse_anext (BtorBTORParser * parser, int len) { int idx, current_idx_len, idx_len; BtorNode * current, * next; Info info; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx_len)) return 0; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx)) return 0; if (idx >= BTOR_COUNT_STACK (parser->exps) || !(current = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "invalid next index %d", idx); return 0; } info = parser->info.start[idx]; if (!info.array) { (void) btor_perr_btor (parser, "next index %d is not an array", idx); return 0; } if (info.next) { (void) btor_perr_btor (parser, "next index %d already used", idx); return 0; } if (parse_space (parser)) return 0; assert (btor_is_array_exp (parser->btor, current)); if (!(next = parse_array_exp (parser, len))) return 0; current_idx_len = btor_get_index_exp_len (parser->btor, current); if (idx_len != current_idx_len) { btor_release_exp (parser->btor, next); (void) btor_perr_btor (parser, "arrays with different index width %d and %d", current_idx_len, idx_len); return 0; } BTOR_PUSH_STACK (parser->mem, parser->regs, current); BTOR_PUSH_STACK (parser->mem, parser->nexts, next); parser->info.start[idx].next = 1; return next; }
int main (int argc, char ** argv) { int i, j, verbosity, close_input, close_output, binary, merge; const char * input_name, * output_name; FILE * input_file, * output_file, * file; BtorAIG * aig, * tmp, * merged, ** p; BtorPtrHashTable * back_annotation; const char * parse_error; BtorPtrHashBucket *b; BtorParseResult model; BtorAIGVecMgr * avmgr; BtorAIGPtrStack regs; BtorAIGPtrStack nexts; BtorAIGPtrStack aigs; BtorParser * parser; BtorAIGMgr * amgr; BtorMemMgr * mem; BtorAIGVec * av; Btor * btor; verbosity = 0; close_input = 0; close_output = 0; binary = 0; merge = 0; input_name = "<stdin>"; output_name = "<stdout>"; input_file = stdin; output_file = stdout; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-h")) { printf ("usage: synthebor [-h][-v][-m][<input>[<output>]]\n"); exit (0); } else if (!strcmp (argv[i], "-v")) verbosity++; else if (!strcmp (argv[i], "-m")) merge = 1; else if (argv[i][0] == '-') die (1, "invalid command line option '%s'", argv[i]); else if (close_output) die (1, "too many files"); else if (close_input) { if (!strcmp (argv[i], input_name)) die (1, "input and output are the same"); if (!(file = fopen (argv[i], "w"))) die (1, "can not write '%s'", argv[i]); output_file = file; output_name = argv[i]; close_output = 1; } else if (!(file = fopen (argv[i], "r"))) die (1, "can not read '%s'", argv[i]); else { input_file = file; input_name = argv[i]; close_input = 1; } } btor = btor_new_btor (); btor_set_verbosity_btor (btor, verbosity); btor_set_rewrite_level_btor (btor, 1); parser = btor_btor_parser_api ()->init (btor, verbosity); parse_error = btor_btor_parser_api()->parse (parser, input_file, input_name, &model); if (parse_error) die (0, parse_error); if (!model.noutputs) die (1, "no roots in '%s'", input_name); if (model.nregs && merge) die (1, "can not merge registers"); mem = btor->mm; avmgr = btor->avmgr; amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); back_annotation = btor_new_ptr_hash_table (mem, 0, 0); BTOR_INIT_STACK (regs); BTOR_INIT_STACK (nexts); for (i = 0; i < model.nregs; i++) { if (btor_is_array_exp (btor, model.regs[i])) die (1, "can not synthesize memories (yet)"); av = btor_exp_to_aigvec (btor, model.regs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, regs, aig); } btor_release_delete_aigvec (avmgr, av); av = btor_exp_to_aigvec (btor, model.nexts[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, nexts, aig); } btor_release_delete_aigvec (avmgr, av); } BTOR_INIT_STACK (aigs); merged = BTOR_AIG_TRUE; for (i = 0; i < model.noutputs; i++) { av = btor_exp_to_aigvec (btor, model.outputs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = av->aigs[j]; if (merge) { tmp = btor_and_aig (amgr, merged, aig); btor_release_aig (amgr, merged); merged = tmp; } else { aig = btor_copy_aig (amgr, aig); BTOR_PUSH_STACK (mem, aigs, aig); } } btor_release_delete_aigvec (avmgr, av); } if (merge) BTOR_PUSH_STACK (mem, aigs, merged); #ifdef BTOR_HAVE_ISATTY if (close_output || !isatty (1)) binary = 1; #endif assert (BTOR_COUNT_STACK (regs) == BTOR_COUNT_STACK (nexts)); btor_dump_aiger (amgr, binary, output_file, BTOR_COUNT_STACK (aigs), aigs.start, BTOR_COUNT_STACK (regs), regs.start, nexts.start, back_annotation); for (p = aigs.start; p < aigs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, aigs); for (p = regs.start; p < regs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, regs); for (p = nexts.start; p < nexts.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, nexts); for (b = back_annotation->first; b; b = b->next) btor_freestr (mem, b->data.asStr); btor_delete_ptr_hash_table (back_annotation); btor_btor_parser_api()->reset (parser); btor_delete_btor (btor); if (close_input) fclose (input_file); if (close_output) fclose (output_file); return 0; }
static const char * btor_parse_btor_parser (BtorBTORParser * parser, BtorCharStack * prefix, FILE * file, const char *name, BtorParseResult * res) { BtorOpParser op_parser; int ch, len; BtorNode *e; assert (name); assert (file); if (parser->verbosity > 0) btor_msg_btor ("parsing %s", name); parser->nprefix = 0; parser->prefix = prefix; parser->file = file; parser->name = name; parser->lineno = 1; parser->saved = 0; BTOR_CLR (res); NEXT: assert (!parser->error); ch = btor_nextch_btor (parser); if (isspace (ch)) /* also skip empty lines */ goto NEXT; if (ch == EOF) { DONE: if (res) { remove_regs_from_vars (parser); if (parser->found_arrays) res->logic = BTOR_LOGIC_QF_AUFBV; else res->logic = BTOR_LOGIC_QF_BV; res->status = BTOR_PARSE_SAT_STATUS_UNKNOWN; res->ninputs = BTOR_COUNT_STACK (parser->inputs); res->inputs = parser->inputs.start; res->noutputs = BTOR_COUNT_STACK (parser->outputs); res->outputs = parser->outputs.start; res->nregs = BTOR_COUNT_STACK (parser->regs); res->regs = parser->regs.start; res->nexts = parser->nexts.start; if (parser->verbosity > 0) { btor_msg_btor ("parsed %d inputs", res->ninputs); btor_msg_btor ("parsed %d registers", res->nregs); btor_msg_btor ("parsed %d outputs", res->noutputs); } } return 0; } if (ch == ';') /* skip comments */ { COMMENTS: while ((ch = btor_nextch_btor (parser)) != '\n') if (ch == EOF) goto DONE; goto NEXT; } if (!isdigit (ch)) return btor_perr_btor (parser, "expected ';' or digit"); btor_savech_btor (parser, ch); if (parse_positive_int (parser, &parser->idx)) return parser->error; while (BTOR_COUNT_STACK (parser->exps) <= parser->idx) { Info info; memset (&info, 0, sizeof info); BTOR_PUSH_STACK (parser->mem, parser->info, info); BTOR_PUSH_STACK (parser->mem, parser->exps, 0); } if (parser->exps.start[parser->idx]) return btor_perr_btor (parser, "'%d' defined twice", parser->idx); if (parse_space (parser)) return parser->error; assert (BTOR_EMPTY_STACK (parser->op)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF) BTOR_PUSH_STACK (parser->mem, parser->op, ch); BTOR_PUSH_STACK (parser->mem, parser->op, 0); BTOR_RESET_STACK (parser->op); btor_savech_btor (parser, ch); if (parse_space (parser)) return parser->error; if (parse_positive_int (parser, &len)) return parser->error; if (!(op_parser = find_parser (parser, parser->op.start))) return btor_perr_btor (parser, "invalid operator '%s'", parser->op.start); if (!(e = op_parser (parser, len))) { assert (parser->error); return parser->error; } assert (btor_get_exp_len (parser->btor, e) == len); parser->exps.start[parser->idx] = e; SKIP: ch = btor_nextch_btor (parser); if (ch == ' ' || ch == '\t') goto SKIP; if (ch == ';') goto COMMENTS; /* ... and force new line */ if (ch != '\n') return btor_perr_btor (parser, "expected new line"); goto NEXT; }