2 # SymbiYosys (sby) -- Front-end for Yosys-based formal verification flows
4 # Copyright (C) 2022 N. Engelhardt <nak@yosyshq.com>
6 # Permission to use, copy, modify, and/or distribute this software for any
7 # purpose with or without fee is hereby granted, provided that the above
8 # copyright notice and this permission notice appear in all copies.
10 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 from enum
import Enum
, auto
21 from dataclasses
import dataclass
, field
35 def from_cell(c
, name
):
44 raise ValueError("Unknown property type: " + name
)
50 status
: str = field(default
="UNKNOWN")
51 tracefile
: str = field(default
="")
54 return f
"SbyProperty<{self.type} {self.name} at {self.location}: status={self.status}, tracefile=\"{self.tracefile}\">"
60 submodules
: dict = field(default_factory
=dict)
61 properties
: list = field(default_factory
=list)
64 return f
"SbyModule<{self.name} : {self.type}, submodules={self.submodules}, properties={self.properties}>"
67 for prop
in self
.properties
:
69 for submod
in self
.submodules
.values():
70 yield from submod
.__iter
__()
72 def get_property_list(self
):
73 return [p
for p
in self
if p
.type != p
.Type
.ASSUME
]
75 def find_property(self
, hierarchy
, location
):
76 # FIXME: use that RE that works with escaped paths from https://stackoverflow.com/questions/46207665/regex-pattern-to-split-verilog-path-in-different-instances-using-python
77 path
= hierarchy
.split('.')
80 raise ValueError(f
"{self.name} is not the first module in hierarchical path {hierarchy}.")
85 mod_hier
= mod_hier
.submodules
[mod
]
87 raise KeyError(f
"Could not find {hierarchy} in design hierarchy!")
89 prop
= next(p
for p
in mod_hier
.properties
if location
in p
.location
)
91 raise KeyError(f
"Could not find assert at {location} in properties list!")
94 def find_property_by_cellname(self
, cell_name
, trans_dict
=dict()):
95 # backends may need to mangle names irreversibly, so allow applying
96 # the same transformation here
98 if cell_name
== prop
.name
.translate(str.maketrans(trans_dict
)):
100 raise KeyError(f
"No such property: {cell_name}")
102 def design_hierarchy(filename
):
103 design_json
= json
.load(filename
)
104 def make_mod_hier(instance_name
, module_name
, hierarchy
=""):
105 # print(instance_name,":", module_name)
106 sub_hierarchy
=f
"{hierarchy}/{instance_name}" if hierarchy
else instance_name
107 mod
= SbyModule(name
=instance_name
, type=module_name
)
109 for m
in design_json
["modules"]:
110 if m
["name"] == module_name
:
111 cell_sorts
= m
["cell_sorts"]
114 raise ValueError(f
"Cannot find module {module_name}")
116 for sort
in cell_sorts
:
117 if sort
["type"] in ["$assume", "$assert", "$cover", "$live"]:
118 for cell
in sort
["cells"]:
120 location
= cell
["attributes"]["src"]
123 p
= SbyProperty(name
=cell
["name"], type=SbyProperty
.Type
.from_cell(sort
["type"]), location
=location
, hierarchy
=sub_hierarchy
)
124 mod
.properties
.append(p
)
125 if sort
["type"][0] != '$' or sort
["type"].startswith("$paramod"):
126 for cell
in sort
["cells"]:
127 mod
.submodules
[cell
["name"]] = make_mod_hier(cell
["name"], sort
["type"], hierarchy
=sub_hierarchy
)
130 for m
in design_json
["modules"]:
131 attrs
= m
["attributes"]
132 if "top" in attrs
and int(attrs
["top"]) == 1:
133 hierarchy
= make_mod_hier(m
["name"], m
["name"])
136 raise ValueError("Cannot find top module")
140 if len(sys
.argv
) != 2:
141 print(f
"""Usage: {sys.argv[0]} design.json""")
142 with
open(sys
.argv
[1]) as f
:
143 d
= design_hierarchy(f
)
144 print("Design Hierarchy:", d
)
145 for p
in d
.get_property_list():
146 print("Property:", p
)
148 if __name__
== '__main__':