mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Yosys-smtbmc: Support for hierarchical VCD dumping
This commit is contained in:
		
							parent
							
								
									0153ad85d9
								
							
						
					
					
						commit
						c71785d65e
					
				
					 2 changed files with 59 additions and 23 deletions
				
			
		|  | @ -98,7 +98,7 @@ smt.setup("QF_AUFBV") | ||||||
| with open(args[0], "r") as f: | with open(args[0], "r") as f: | ||||||
|     for line in f: |     for line in f: | ||||||
|         smt.write(line) |         smt.write(line) | ||||||
|         smt.getinfo(line) |         smt.info(line) | ||||||
| 
 | 
 | ||||||
| if topmod is None: | if topmod is None: | ||||||
|     topmod = smt.topmod |     topmod = smt.topmod | ||||||
|  | @ -106,18 +106,19 @@ if topmod is None: | ||||||
| assert topmod is not None | assert topmod is not None | ||||||
| assert topmod in smt.modinfo | assert topmod in smt.modinfo | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def write_vcd_model(steps): | def write_vcd_model(steps): | ||||||
|     print("%s Writing model to VCD file." % smt.timestamp()) |     print("%s Writing model to VCD file." % smt.timestamp()) | ||||||
| 
 | 
 | ||||||
|     vcd = mkvcd(open(vcdfile, "w")) |     vcd = mkvcd(open(vcdfile, "w")) | ||||||
|     for netname in sorted(smt.modinfo[topmod].wsize.keys()): |     for netpath in sorted(smt.hiernets(topmod)): | ||||||
|         width = len(smt.get_net_bin(topmod, netname, "s0")) |         width = len(smt.get_net_bin(topmod, netpath, "s0")) | ||||||
|         vcd.add_net(netname, width) |         vcd.add_net([topmod] + netpath, width) | ||||||
| 
 | 
 | ||||||
|     for i in range(steps): |     for i in range(steps): | ||||||
|         vcd.set_time(i) |         vcd.set_time(i) | ||||||
|         for netname in smt.modinfo[topmod].wsize.keys(): |         for netpath in sorted(smt.hiernets(topmod)): | ||||||
|             vcd.set_net(netname, smt.get_net_bin(topmod, netname, "s%d" % i)) |             vcd.set_net([topmod] + netpath, smt.get_net_bin(topmod, netpath, "s%d" % i)) | ||||||
| 
 | 
 | ||||||
|     vcd.set_time(steps) |     vcd.set_time(steps) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ class smtio: | ||||||
|         self.p.stdin.write(bytes(stmt + "\n", "ascii")) |         self.p.stdin.write(bytes(stmt + "\n", "ascii")) | ||||||
|         self.p.stdin.flush() |         self.p.stdin.flush() | ||||||
| 
 | 
 | ||||||
|     def getinfo(self, stmt): |     def info(self, stmt): | ||||||
|         if not stmt.startswith("; yosys-smt2-"): |         if not stmt.startswith("; yosys-smt2-"): | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|  | @ -129,6 +129,17 @@ class smtio: | ||||||
|             self.modinfo[self.curmod].wires.add(fields[2]) |             self.modinfo[self.curmod].wires.add(fields[2]) | ||||||
|             self.modinfo[self.curmod].wsize[fields[2]] = int(fields[3]) |             self.modinfo[self.curmod].wsize[fields[2]] = int(fields[3]) | ||||||
| 
 | 
 | ||||||
|  |     def hiernets(self, top): | ||||||
|  |         def hiernets_worker(nets, mod, cursor): | ||||||
|  |             for netname in sorted(self.modinfo[mod].wsize.keys()): | ||||||
|  |                 nets.append(cursor + [netname]) | ||||||
|  |             for cellname, celltype in sorted(self.modinfo[mod].cells.items()): | ||||||
|  |                 hiernets_worker(nets, celltype, cursor + [cellname]) | ||||||
|  | 
 | ||||||
|  |         nets = list() | ||||||
|  |         hiernets_worker(nets, top, []) | ||||||
|  |         return nets | ||||||
|  | 
 | ||||||
|     def read(self): |     def read(self): | ||||||
|         stmt = [] |         stmt = [] | ||||||
|         count_brackets = 0 |         count_brackets = 0 | ||||||
|  | @ -282,19 +293,32 @@ class smtio: | ||||||
|         self.write("(get-value (%s))" % (expr)) |         self.write("(get-value (%s))" % (expr)) | ||||||
|         return self.parse(self.read())[0][1] |         return self.parse(self.read())[0][1] | ||||||
| 
 | 
 | ||||||
|     def get_net(self, mod_name, net_name, state_name): |     def get_net(self, mod_name, net_path, state_name): | ||||||
|         return self.get("(|%s_n %s| %s)" % (mod_name, net_name, state_name)) |         def mkexpr(mod, base, path): | ||||||
|  |             if len(path) == 1: | ||||||
|  |                 assert mod in self.modinfo | ||||||
|  |                 assert path[0] in self.modinfo[mod].wsize | ||||||
|  |                 return "(|%s_n %s| %s)" % (mod, path[0], base) | ||||||
| 
 | 
 | ||||||
|     def get_net_bool(self, mod_name, net_name, state_name): |             assert mod in self.modinfo | ||||||
|         v = self.get_net(mod_name, net_name, state_name) |             assert path[0] in self.modinfo[mod].cells | ||||||
|  | 
 | ||||||
|  |             nextmod = self.modinfo[mod].cells[path[0]] | ||||||
|  |             nextbase = "(|%s_h %s| %s)" % (mod, path[0], base) | ||||||
|  |             return mkexpr(nextmod, nextbase, path[1:]) | ||||||
|  | 
 | ||||||
|  |         return self.get(mkexpr(mod_name, state_name, net_path)) | ||||||
|  | 
 | ||||||
|  |     def get_net_bool(self, mod_name, net_path, state_name): | ||||||
|  |         v = self.get_net(mod_name, net_path, state_name) | ||||||
|         assert v in ["true", "false"] |         assert v in ["true", "false"] | ||||||
|         return 1 if v == "true" else 0 |         return 1 if v == "true" else 0 | ||||||
| 
 | 
 | ||||||
|     def get_net_hex(self, mod_name, net_name, state_name): |     def get_net_hex(self, mod_name, net_path, state_name): | ||||||
|         return self.bv2hex(self.get_net(mod_name, net_name, state_name)) |         return self.bv2hex(self.get_net(mod_name, net_path, state_name)) | ||||||
| 
 | 
 | ||||||
|     def get_net_bin(self, mod_name, net_name, state_name): |     def get_net_bin(self, mod_name, net_path, state_name): | ||||||
|         return self.bv2bin(self.get_net(mod_name, net_name, state_name)) |         return self.bv2bin(self.get_net(mod_name, net_path, state_name)) | ||||||
| 
 | 
 | ||||||
|     def wait(self): |     def wait(self): | ||||||
|         self.p.wait() |         self.p.wait() | ||||||
|  | @ -344,24 +368,35 @@ class mkvcd: | ||||||
|         self.t = -1 |         self.t = -1 | ||||||
|         self.nets = dict() |         self.nets = dict() | ||||||
| 
 | 
 | ||||||
|     def add_net(self, name, width): |     def add_net(self, path, width): | ||||||
|  |         path = tuple(path) | ||||||
|         assert self.t == -1 |         assert self.t == -1 | ||||||
|         key = "n%d" % len(self.nets) |         key = "n%d" % len(self.nets) | ||||||
|         self.nets[name] = (key, width) |         self.nets[path] = (key, width) | ||||||
| 
 | 
 | ||||||
|     def set_net(self, name, bits): |     def set_net(self, path, bits): | ||||||
|         assert name in self.nets |         path = tuple(path) | ||||||
|         assert self.t >= 0 |         assert self.t >= 0 | ||||||
|         print("b%s %s" % (bits, self.nets[name][0]), file=self.f) |         assert path in self.nets | ||||||
|  |         print("b%s %s" % (bits, self.nets[path][0]), file=self.f) | ||||||
| 
 | 
 | ||||||
|     def set_time(self, t): |     def set_time(self, t): | ||||||
|         assert t >= self.t |         assert t >= self.t | ||||||
|         if t != self.t: |         if t != self.t: | ||||||
|             if self.t == -1: |             if self.t == -1: | ||||||
|                 print("$var event 1 ! smt_clock $end", file=self.f) |                 print("$var event 1 ! smt_clock $end", file=self.f) | ||||||
|                 for name in sorted(self.nets): |                 scope = [] | ||||||
|                     key, width = self.nets[name] |                 for path in sorted(self.nets): | ||||||
|                     print("$var wire %d %s %s $end" % (width, key, name), file=self.f) |                     while len(scope)+1 > len(path) or (len(scope) > 0 and scope[-1] != path[len(scope)-1]): | ||||||
|  |                         print("$upscope $end", file=self.f) | ||||||
|  |                         scope = scope[:-1] | ||||||
|  |                     while len(scope)+1 < len(path): | ||||||
|  |                         print("$scope module %s $end" % path[len(scope)], file=self.f) | ||||||
|  |                         scope.append(path[len(scope)-1]) | ||||||
|  |                     key, width = self.nets[path] | ||||||
|  |                     print("$var wire %d %s %s $end" % (width, key, path[-1]), file=self.f) | ||||||
|  |                 for i in range(len(scope)): | ||||||
|  |                     print("$upscope $end", file=self.f) | ||||||
|                 print("$enddefinitions $end", file=self.f) |                 print("$enddefinitions $end", file=self.f) | ||||||
|             self.t = t |             self.t = t | ||||||
|             assert self.t >= 0 |             assert self.t >= 0 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue