-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #172 from byuccl/eblif
SpyDrNet 1.11.0
- Loading branch information
Showing
24 changed files
with
1,176 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.. _eblif_support: | ||
|
||
EBLIF Support | ||
-------------- | ||
|
||
SpyDrNet's EBLIF parser requires/follows conventions followed by Symbiflow. Only structural BLIF is supported, as well as a few extensions (EBLIF). See Symbiflow's File Format page (https://docs.verilogtorouting.org/en/latest/vpr/file_formats/#vpr-pack-file) for more details. It is important to point out that, along with Symbiflow's VPR, SpyDrNet expects designs in the EBLIF format to be flat. Hierarchy is not currently supported by either. | ||
|
||
In addition, it is important that .blackbox modules are included in the netlist to provide SpyDrNet with the information about primitives in the netlist (port directions, etc.). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.. _netlist_types: | ||
|
||
Netlist Types | ||
-------------- | ||
|
||
SpyDrNet supports three netlist types: EDIF, Verilog, and EBLIF. All types can be parsed into and composed out of SpyDrNet. However, crossing between types (parsing in one type and composing out another type) is not guaranteed to always work. Crossing types will likely be improved in a future version. | ||
|
||
Some functions take a netlist type in as a parameter. Netlist types can be imported from spydrnet.util.netlist_type |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
import os | ||
from re import sub | ||
from spydrnet.util.selection import Selection | ||
import spydrnet as sdn | ||
|
||
class EBLIFComposer: | ||
def __init__(self,write_blackbox, write_cname=True): | ||
self.netlist = None | ||
self.open_file = None | ||
self.write_blackbox = write_blackbox | ||
self.write_cname = write_cname | ||
self.blackboxes_to_compose = set() | ||
|
||
def run(self, ir, file_out): | ||
self.open_file = self.prepare_file(file_out) | ||
self._compose(ir) | ||
|
||
def prepare_file(self,out_file): | ||
if (os.path.exists(out_file)): | ||
f = open(out_file,"w") | ||
else: | ||
f = open(out_file,"x") | ||
return f | ||
|
||
def write_out(self,string): | ||
self.open_file.write(string) | ||
|
||
def clean_up(self): | ||
self.open_file.close() | ||
|
||
def _compose(self,ir): | ||
self.netlist = ir | ||
# print("Composing...") | ||
self.compose_comments() | ||
self.compose_top_model() | ||
self.clean_up() | ||
|
||
def compose_comments(self): | ||
for comment in self.netlist["EBLIF.comment"]: | ||
to_write = "# "+comment+"\n" | ||
self.write_out(to_write) | ||
self.write_out("# Generated by \'BYU spydrnet tool\'\n") | ||
self.write_out("\n") | ||
|
||
def compose_top_model(self): | ||
top_instance = self.netlist.top_instance | ||
to_write = ".model "+top_instance.reference.name+"\n" | ||
self.write_out(to_write) | ||
self.compose_top_level_ports() | ||
self.compose_top_level_clocks() | ||
self.compose_default_wires() | ||
self.compose_instances() | ||
self.compose_end() | ||
if (self.write_blackbox): | ||
self.compose_blackboxes() | ||
|
||
def compose_top_level_ports(self): | ||
to_write = ".inputs " | ||
for port in self.netlist.top_instance.get_ports(filter = lambda x: x.direction is sdn.Port.Direction.IN): | ||
if len(port.pins) > 1: | ||
for i in range(len(port.pins)): | ||
to_write+=port.name+"["+str(i)+"] " | ||
else: | ||
to_write+=port.name+" " | ||
to_write+="\n" | ||
self.write_out(to_write) | ||
|
||
to_write = ".outputs " | ||
for port in self.netlist.top_instance.get_ports(filter = lambda x: x.direction is sdn.Port.Direction.OUT): | ||
if len(port.pins) > 1: | ||
for i in range(len(port.pins)): | ||
to_write+=port.name+"["+str(i)+"] " | ||
else: | ||
to_write+=port.name+" " | ||
to_write+="\n" | ||
self.write_out(to_write) | ||
|
||
def compose_top_level_clocks(self): | ||
if "EBLIF.clock" in self.netlist.top_instance.data: | ||
to_write = ".clock " | ||
for clock in self.netlist.top_instance["EBLIF.clock"]: | ||
to_write+=clock+" " | ||
self.write_out(to_write+"\n") | ||
|
||
def compose_default_wires(self): | ||
default_wires = list() | ||
try: | ||
self.netlist["EBLIF.default_wires"] | ||
default_wires = self.netlist['EBLIF.default_wires'] | ||
except KeyError: | ||
None | ||
if "$false" in default_wires: | ||
self.write_out(".names $false\n") | ||
if "$true" in default_wires: | ||
self.write_out(".names $true\n1\n") | ||
if "$undef" in default_wires: | ||
self.write_out(".names $undef\n") | ||
self.write_out("\n") | ||
|
||
def compose_instances(self): | ||
categories = self.separate_by_type() | ||
if "EBLIF.subckt" in categories.keys(): | ||
self.compose_subcircuits(categories["EBLIF.subckt"]) | ||
if "EBLIF.gate" in categories.keys(): | ||
self.compose_subcircuits(categories["EBLIF.gate"],is_gate=True) | ||
if "EBLIF.other" in categories.keys(): | ||
self.compose_subcircuits(categories["EBLIF.other"]) | ||
if "EBLIF.names" in categories.keys(): | ||
self.compose_names(categories["EBLIF.names"]) | ||
if "EBLIF.latch" in categories.keys(): | ||
self.compose_latches(categories["EBLIF.latch"]) | ||
|
||
def separate_by_type(self): | ||
dict_by_types = dict() | ||
for instance in self.netlist.get_instances(): | ||
try: | ||
instance["EBLIF.type"] | ||
except KeyError: | ||
# print("Error, no type found") | ||
instance["EBLIF.type"] = "EBLIF.other" | ||
type = instance["EBLIF.type"] | ||
try: | ||
dict_by_types[type] | ||
except KeyError: | ||
dict_by_types[type] = list() | ||
dict_by_types[type].append(instance) | ||
return dict_by_types | ||
|
||
def compose_subcircuits(self,list_of_subcircuits,is_gate=False): | ||
for subckt in list_of_subcircuits: | ||
self.blackboxes_to_compose.add(subckt.reference.name) | ||
to_add = "" | ||
if is_gate: | ||
to_write = ".gate "+ subckt.reference.name+" " | ||
else: | ||
to_write = ".subckt "+ subckt.reference.name+" " | ||
amount_of_ports_to_write = 0 | ||
for port in subckt.get_ports(): | ||
for pin in port.pins: | ||
amount_of_ports_to_write+=1 | ||
for port in subckt.reference.get_ports(): | ||
inner_pin_list = port.pins | ||
for pin in subckt.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port is port): | ||
if (amount_of_ports_to_write > 5): | ||
to_write+=to_add+" \\ \n" | ||
to_add = "" | ||
if len(inner_pin_list) > 1: | ||
index = inner_pin_list.index(pin.inner_pin) | ||
to_add+=port.name+"["+str(index)+"]"+"=" | ||
else: | ||
to_add+=port.name+"=" | ||
if pin.wire: | ||
to_add+=self.find_connected_wire_info(pin) | ||
else: | ||
to_add+='unconn' | ||
to_add+=" " | ||
to_write+=to_add+'\n' | ||
self.write_out(to_write) | ||
self.find_and_write_additional_instance_info(subckt) | ||
|
||
def compose_names(self,list_of_names): | ||
for name_instance in list_of_names: | ||
to_write = ".names " | ||
in_pin_list = list(x for x in name_instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.direction is sdn.IN)) | ||
in_pin_list.reverse() | ||
for pin in in_pin_list: | ||
# for pin in name_instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.direction is sdn.IN): | ||
if pin.wire: | ||
to_write+=pin.wire.cable.name | ||
if len(pin.wire.cable.wires) > 1: # if a multi bit wire, add the index | ||
to_write+="["+str(pin.wire.cable.wires.index(pin.wire))+"]" | ||
else: | ||
to_write+="unconn" | ||
to_write+=" " | ||
for pin in name_instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.direction is sdn.OUT): | ||
if pin.wire: | ||
to_write+=pin.wire.cable.name | ||
if len(pin.wire.cable.wires) > 1: # if a multi bit wire, add the index | ||
to_write+="["+str(pin.wire.cable.wires.index(pin.wire))+"]" | ||
else: | ||
to_write+="unconn" | ||
to_write+=" " | ||
to_write+="\n" | ||
try: | ||
name_instance["EBLIF.output_covers"] | ||
for output_cover in name_instance["EBLIF.output_covers"]: | ||
to_write+=output_cover+"\n" | ||
except KeyError: | ||
None | ||
self.write_out(to_write) | ||
self.find_and_write_additional_instance_info(name_instance) | ||
|
||
def compose_latches(self,latch_list): | ||
for latch_instance in latch_list: | ||
to_write = ".latch " | ||
# port_list = list(x for x in latch_instance.get_ports()) | ||
for port_type in ['input', 'output', 'type', 'control', 'init-val']: # this is the specific order of ports | ||
# current_port = next(port for port in port_list if port.name == port_type) | ||
for pin in latch_instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.name == port_type): | ||
# connection_name = None | ||
if pin.wire: | ||
to_write+=pin.wire.cable.name | ||
if (len(pin.wire.cable.wires)>1): | ||
to_write+="["+str(pin.wire.index())+"]" | ||
to_write+=" " | ||
# connection_name=pin.wire.cable.name | ||
else: | ||
to_write+="unconn " | ||
# connection_name="unconn" | ||
to_write+='\n' | ||
self.write_out(to_write) | ||
self.find_and_write_additional_instance_info(latch_instance) | ||
|
||
def find_connected_wire_info(self,pin): | ||
string_to_return = "" | ||
cable = pin.wire.cable | ||
string_to_return+=cable.name | ||
if len(cable.wires) > 1: | ||
string_to_return+="["+str(pin.wire.index()) +"]" | ||
return string_to_return | ||
|
||
def find_and_write_additional_instance_info(self,instance): | ||
to_write = "" | ||
if self.write_cname: | ||
# if "EBLIF.cname" in instance.data: | ||
# to_write+=".cname "+instance["EBLIF.cname"]+'\n' | ||
# else: | ||
to_write+=".cname "+instance.name+'\n' | ||
if "EBLIF.attr" in instance.data: | ||
for key, value in instance.data["EBLIF.attr"].items(): | ||
to_write+=".attr "+key+" "+value+'\n' | ||
if "EBLIF.param" in instance.data: | ||
for key, value in instance.data["EBLIF.param"].items(): | ||
to_write+=".param "+key+" "+value+'\n' | ||
self.write_out(to_write) | ||
|
||
def compose_blackboxes(self): | ||
for definition in self.netlist.get_definitions(): | ||
if definition.name in self.blackboxes_to_compose: | ||
if "EBLIF.blackbox" in definition.data.keys(): | ||
to_write = "\n.model "+definition.name | ||
to_write+="\n.inputs" | ||
for port in definition.get_ports(filter=lambda x: x.direction is sdn.IN): | ||
to_write+=" "+port.name | ||
to_write+="\n.outputs" | ||
for port in definition.get_ports(filter=lambda x: x.direction is sdn.OUT): | ||
to_write+=" "+port.name | ||
self.write_out(to_write+"\n") | ||
self.write_out(".blackbox\n") | ||
self.compose_end() | ||
|
||
def compose_end(self): | ||
self.write_out(".end\n") |
Oops, something went wrong.