mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Added "yosys-smtbmc --unroll"
This commit is contained in:
		
							parent
							
								
									ceff7ecd91
								
							
						
					
					
						commit
						6770d6e0f8
					
				
					 1 changed files with 130 additions and 11 deletions
				
			
		| 
						 | 
					@ -18,6 +18,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sys, subprocess, re
 | 
					import sys, subprocess, re
 | 
				
			||||||
 | 
					from copy import deepcopy
 | 
				
			||||||
from select import select
 | 
					from select import select
 | 
				
			||||||
from time import time
 | 
					from time import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,18 +47,20 @@ class SmtModInfo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SmtIo:
 | 
					class SmtIo:
 | 
				
			||||||
    def __init__(self, solver=None, debug_print=None, debug_file=None, timeinfo=None, opts=None):
 | 
					    def __init__(self, solver=None, debug_print=None, debug_file=None, timeinfo=None, unroll=None, opts=None):
 | 
				
			||||||
        if opts is not None:
 | 
					        if opts is not None:
 | 
				
			||||||
            self.solver = opts.solver
 | 
					            self.solver = opts.solver
 | 
				
			||||||
            self.debug_print = opts.debug_print
 | 
					            self.debug_print = opts.debug_print
 | 
				
			||||||
            self.debug_file = opts.debug_file
 | 
					            self.debug_file = opts.debug_file
 | 
				
			||||||
            self.timeinfo = opts.timeinfo
 | 
					            self.timeinfo = opts.timeinfo
 | 
				
			||||||
 | 
					            self.unroll = opts.unroll
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.solver = "z3"
 | 
					            self.solver = "z3"
 | 
				
			||||||
            self.debug_print = False
 | 
					            self.debug_print = False
 | 
				
			||||||
            self.debug_file = None
 | 
					            self.debug_file = None
 | 
				
			||||||
            self.timeinfo = True
 | 
					            self.timeinfo = True
 | 
				
			||||||
 | 
					            self.unroll = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if solver is not None:
 | 
					        if solver is not None:
 | 
				
			||||||
            self.solver = solver
 | 
					            self.solver = solver
 | 
				
			||||||
| 
						 | 
					@ -71,6 +74,9 @@ class SmtIo:
 | 
				
			||||||
        if timeinfo is not None:
 | 
					        if timeinfo is not None:
 | 
				
			||||||
            self.timeinfo = timeinfo
 | 
					            self.timeinfo = timeinfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if unroll is not None:
 | 
				
			||||||
 | 
					            self.unroll = unroll
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.solver == "yices":
 | 
					        if self.solver == "yices":
 | 
				
			||||||
            popen_vargs = ['yices-smt2', '--incremental']
 | 
					            popen_vargs = ['yices-smt2', '--incremental']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,8 +90,17 @@ class SmtIo:
 | 
				
			||||||
            popen_vargs = ['mathsat']
 | 
					            popen_vargs = ['mathsat']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.solver == "boolector":
 | 
					        if self.solver == "boolector":
 | 
				
			||||||
            self.declared_sorts = list()
 | 
					            popen_vargs = ['boolector', '--smt2', '-i', '-m']
 | 
				
			||||||
            popen_vargs = ['boolector', '--smt2', '-i']
 | 
					            self.unroll = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.unroll:
 | 
				
			||||||
 | 
					            self.unroll_idcnt = 0
 | 
				
			||||||
 | 
					            self.unroll_buffer = ""
 | 
				
			||||||
 | 
					            self.unroll_sorts = set()
 | 
				
			||||||
 | 
					            self.unroll_objs = set()
 | 
				
			||||||
 | 
					            self.unroll_decls = dict()
 | 
				
			||||||
 | 
					            self.unroll_cache = dict()
 | 
				
			||||||
 | 
					            self.unroll_stack = list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.p = subprocess.Popen(popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 | 
					        self.p = subprocess.Popen(popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 | 
				
			||||||
        self.start_time = time()
 | 
					        self.start_time = time()
 | 
				
			||||||
| 
						 | 
					@ -105,15 +120,108 @@ class SmtIo:
 | 
				
			||||||
        secs = int(time() - self.start_time)
 | 
					        secs = int(time() - self.start_time)
 | 
				
			||||||
        return "## %6d %3d:%02d:%02d " % (secs, secs // (60*60), (secs // 60) % 60, secs % 60)
 | 
					        return "## %6d %3d:%02d:%02d " % (secs, secs // (60*60), (secs // 60) % 60, secs % 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def write(self, stmt):
 | 
					    def replace_in_stmt(self, stmt, pat, repl):
 | 
				
			||||||
 | 
					        if stmt == pat:
 | 
				
			||||||
 | 
					            return repl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if isinstance(stmt, list):
 | 
				
			||||||
 | 
					            return [self.replace_in_stmt(s, pat, repl) for s in stmt]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return stmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def unroll_stmt(self, stmt):
 | 
				
			||||||
 | 
					        if not isinstance(stmt, list):
 | 
				
			||||||
 | 
					            return stmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stmt = [self.unroll_stmt(s) for s in stmt]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(stmt) >= 2 and not isinstance(stmt[0], list) and stmt[0] in self.unroll_decls:
 | 
				
			||||||
 | 
					            assert stmt[1] in self.unroll_objs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            key = tuple(stmt)
 | 
				
			||||||
 | 
					            if key not in self.unroll_cache:
 | 
				
			||||||
 | 
					                decl = deepcopy(self.unroll_decls[key[0]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.unroll_cache[key] = "|UNROLL#%d|" % self.unroll_idcnt
 | 
				
			||||||
 | 
					                decl[1] = self.unroll_cache[key]
 | 
				
			||||||
 | 
					                self.unroll_idcnt += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if decl[0] == "declare-fun":
 | 
				
			||||||
 | 
					                    if isinstance(decl[3], list) or decl[3] not in self.unroll_sorts:
 | 
				
			||||||
 | 
					                        self.unroll_objs.add(decl[1])
 | 
				
			||||||
 | 
					                        decl[2] = list()
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        self.unroll_objs.add(decl[1])
 | 
				
			||||||
 | 
					                        decl = list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                elif decl[0] == "define-fun":
 | 
				
			||||||
 | 
					                    arg_index = 1
 | 
				
			||||||
 | 
					                    for arg_name, arg_sort in decl[2]:
 | 
				
			||||||
 | 
					                        decl[4] = self.replace_in_stmt(decl[4], arg_name, key[arg_index])
 | 
				
			||||||
 | 
					                        arg_index += 1
 | 
				
			||||||
 | 
					                    decl[2] = list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if len(decl) > 0:
 | 
				
			||||||
 | 
					                    decl = self.unroll_stmt(decl)
 | 
				
			||||||
 | 
					                    self.write(self.unparse(decl), unroll=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return self.unroll_cache[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return stmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def write(self, stmt, unroll=True):
 | 
				
			||||||
        stmt = stmt.strip()
 | 
					        stmt = stmt.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.solver == "boolector":
 | 
					        if unroll and self.unroll:
 | 
				
			||||||
            if stmt.startswith("(declare-sort"):
 | 
					            if stmt.startswith(";"):
 | 
				
			||||||
                self.declared_sorts.append(stmt.split()[1])
 | 
					 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
            for n in self.declared_sorts:
 | 
					
 | 
				
			||||||
                stmt = stmt.replace(n, "(_ BitVec 16)")
 | 
					            stmt = re.sub(r" ;.*", "", stmt)
 | 
				
			||||||
 | 
					            stmt = self.unroll_buffer + stmt
 | 
				
			||||||
 | 
					            self.unroll_buffer = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            s = re.sub(r"\|[^|]*\|", "", stmt)
 | 
				
			||||||
 | 
					            if s.count("(") != s.count(")"):
 | 
				
			||||||
 | 
					                self.unroll_buffer = stmt + " "
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            s = self.parse(stmt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.debug_print:
 | 
				
			||||||
 | 
					                print("-> %s" % s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if len(s) == 3 and s[0] == "declare-sort" and s[2] == "0":
 | 
				
			||||||
 | 
					                self.unroll_sorts.add(s[1])
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elif len(s) == 4 and s[0] == "declare-fun" and s[2] == [] and s[3] in self.unroll_sorts:
 | 
				
			||||||
 | 
					                self.unroll_objs.add(s[1])
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elif len(s) >= 4 and s[0] == "declare-fun":
 | 
				
			||||||
 | 
					                for arg_sort in s[2]:
 | 
				
			||||||
 | 
					                    if arg_sort in self.unroll_sorts:
 | 
				
			||||||
 | 
					                        self.unroll_decls[s[1]] = s
 | 
				
			||||||
 | 
					                        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elif len(s) >= 4 and s[0] == "define-fun":
 | 
				
			||||||
 | 
					                for arg_name, arg_sort in s[2]:
 | 
				
			||||||
 | 
					                    if arg_sort in self.unroll_sorts:
 | 
				
			||||||
 | 
					                        self.unroll_decls[s[1]] = s
 | 
				
			||||||
 | 
					                        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            stmt = self.unparse(self.unroll_stmt(s))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if stmt == "(push 1)":
 | 
				
			||||||
 | 
					                self.unroll_stack.append((
 | 
				
			||||||
 | 
					                    deepcopy(self.unroll_sorts),
 | 
				
			||||||
 | 
					                    deepcopy(self.unroll_objs),
 | 
				
			||||||
 | 
					                    deepcopy(self.unroll_decls),
 | 
				
			||||||
 | 
					                    deepcopy(self.unroll_cache),
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if stmt == "(pop 1)":
 | 
				
			||||||
 | 
					                self.unroll_sorts, self.unroll_objs, self.unroll_decls, self.unroll_cache = self.unroll_stack.pop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.debug_print:
 | 
					        if self.debug_print:
 | 
				
			||||||
            print("> %s" % stmt)
 | 
					            print("> %s" % stmt)
 | 
				
			||||||
| 
						 | 
					@ -297,6 +405,11 @@ class SmtIo:
 | 
				
			||||||
            return expr, cursor
 | 
					            return expr, cursor
 | 
				
			||||||
        return worker(stmt)[0]
 | 
					        return worker(stmt)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def unparse(self, stmt):
 | 
				
			||||||
 | 
					        if isinstance(stmt, list):
 | 
				
			||||||
 | 
					            return "(" + " ".join([self.unparse(s) for s in stmt]) + ")"
 | 
				
			||||||
 | 
					        return stmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def bv2hex(self, v):
 | 
					    def bv2hex(self, v):
 | 
				
			||||||
        h = ""
 | 
					        h = ""
 | 
				
			||||||
        v = self.bv2bin(v)
 | 
					        v = self.bv2bin(v)
 | 
				
			||||||
| 
						 | 
					@ -416,10 +529,11 @@ class SmtIo:
 | 
				
			||||||
class SmtOpts:
 | 
					class SmtOpts:
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self.shortopts = "s:v"
 | 
					        self.shortopts = "s:v"
 | 
				
			||||||
        self.longopts = ["no-progress", "dump-smt2="]
 | 
					        self.longopts = ["unroll", "no-progress", "dump-smt2="]
 | 
				
			||||||
        self.solver = "z3"
 | 
					        self.solver = "z3"
 | 
				
			||||||
        self.debug_print = False
 | 
					        self.debug_print = False
 | 
				
			||||||
        self.debug_file = None
 | 
					        self.debug_file = None
 | 
				
			||||||
 | 
					        self.unroll = True
 | 
				
			||||||
        self.timeinfo = True
 | 
					        self.timeinfo = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle(self, o, a):
 | 
					    def handle(self, o, a):
 | 
				
			||||||
| 
						 | 
					@ -427,6 +541,8 @@ class SmtOpts:
 | 
				
			||||||
            self.solver = a
 | 
					            self.solver = a
 | 
				
			||||||
        elif o == "-v":
 | 
					        elif o == "-v":
 | 
				
			||||||
            self.debug_print = True
 | 
					            self.debug_print = True
 | 
				
			||||||
 | 
					        elif o == "--unroll":
 | 
				
			||||||
 | 
					            self.unroll = True
 | 
				
			||||||
        elif o == "--no-progress":
 | 
					        elif o == "--no-progress":
 | 
				
			||||||
            self.timeinfo = True
 | 
					            self.timeinfo = True
 | 
				
			||||||
        elif o == "--dump-smt2":
 | 
					        elif o == "--dump-smt2":
 | 
				
			||||||
| 
						 | 
					@ -444,8 +560,11 @@ class SmtOpts:
 | 
				
			||||||
    -v
 | 
					    -v
 | 
				
			||||||
        enable debug output
 | 
					        enable debug output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --unroll
 | 
				
			||||||
 | 
					        unroll uninterpreted functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    --no-progress
 | 
					    --no-progress
 | 
				
			||||||
        disable running timer display during solving
 | 
					        disable timer display during solving
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    --dump-smt2 <filename>
 | 
					    --dump-smt2 <filename>
 | 
				
			||||||
        write smt2 statements to file
 | 
					        write smt2 statements to file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue