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 mod
= SbyModule(name
=instance_name
, type=module_name
)
108 cells
= design_json
["modules"][module_name
]["cells"]
109 for cell_name
, cell
in cells
.items():
110 sub_hierarchy
=f
"{hierarchy}/{instance_name}" if hierarchy
else instance_name
111 if cell
["type"][0] != '$' or cell
["type"].startswith("$paramod"):
112 mod
.submodules
[cell_name
] = make_mod_hier(cell_name
, cell
["type"], hierarchy
=sub_hierarchy
)
113 if cell
["type"] in ["$assume", "$assert", "$cover", "$live"]:
115 location
= cell
["attributes"]["src"]
118 p
= SbyProperty(name
=cell_name
, type=SbyProperty
.Type
.from_cell(cell
["type"]), location
=location
, hierarchy
=sub_hierarchy
)
119 mod
.properties
.append(p
)
122 for module_name
in design_json
["modules"]:
123 attrs
= design_json
["modules"][module_name
]["attributes"]
124 if "top" in attrs
and int(attrs
["top"]) == 1:
125 hierarchy
= make_mod_hier(module_name
, module_name
)
128 raise ValueError("Cannot find top module")
132 if len(sys
.argv
) != 2:
133 print(f
"""Usage: {sys.argv[0]} design.json""")
134 with
open(sys
.argv
[1]) as f
:
135 d
= design_hierarchy(f
)
136 print("Design Hierarchy:", d
)
137 for p
in d
.get_property_list():
138 print("Property:", p
)
140 if __name__
== '__main__':