Skip to content

Commit

Permalink
Merge pull request #193 from byuccl/next_release_v2
Browse files Browse the repository at this point in the history
SpyDrNet 1.12.0
  • Loading branch information
jacobdbrown4 authored Nov 9, 2022
2 parents e971f17 + 74a2a5c commit 9063e17
Show file tree
Hide file tree
Showing 31 changed files with 1,143 additions and 512 deletions.
12 changes: 12 additions & 0 deletions docs/source/reference/archive/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _archive:

===========
Archive
===========

The following is from older versions of the SpyDrNet documentation

.. toctree::
:maxdepth: 2

introduction
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Netlists flow through SpyDrNet in a three step process (see :numref:`fig:flow`).
.. _Pandoc: https://pandoc.org/

.. _fig:flow:
.. figure:: ../figures/flow.*
.. figure:: ../../figures/flow.*
:align: center
:alt: SpyDrNet Flow

Expand Down Expand Up @@ -82,7 +82,7 @@ At this point, SpyDrNet features and functionality are accessible via ``sdn.<fun
Digital designs for FPGAs are represented as netlists, a list of components and connections. Netlists come from various vendors in many different formats. SpyDrNet allows you to look at and alter a netlist in a language inspecific way. SpyDrNet parses a netlist into an intermediate represention (IR) that is designed to be easily traversed and effortlessly manipulated. SpyDrNet aims to provide the tools you need to accomplish the netlist analysis and transformation tasks you have in mind without having to reinvent the wheel. :numref:`fig:IR` shows a summary of the SpyDrNet intermediate representation (IR).

.. _fig:IR:
.. figure:: ../figures/IR.*
.. figure:: ../../figures/IR.*
:align: center
:alt: SpyDrNet Intermediate Representation

Expand Down
19 changes: 19 additions & 0 deletions docs/source/reference/built_in_architecture.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.. _built_in_architecture:

Built In FPGA Architectures
----------------------------

SpyDrNet has built in libraries for the following primitive libraries:

* Xilinx 7-Series
* F4PGA Xilinx 7-Series
* Lattice LIFCL

An optional parameter can be parsed to parse() which will tell the parser to load in the specified primitive library during parsing. This allows primitive information to be known (particularly port directions) even if though it may not be defined in the netlist (as a cell define module or a blackbox).

The supported types are found under **spydrnet.util.architecture**

When a built in architecture parameter is passed, the parser uses the PrimitiveLibraryReader class to load in the primitive library and populate the netlist definitions with information. See below.

.. currentmodule:: spydrnet.parsers.primitive_library_reader
.. autoclass:: PrimitiveLibraryReader
File renamed without changes.
12 changes: 12 additions & 0 deletions docs/source/reference/functions/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _functions:

Functions (Additional Information)
----------------------------------

Included are some SpyDrNet functions that are worth highlighting:

.. toctree::
:maxdepth: 2

uniquify
clone
File renamed without changes.
6 changes: 3 additions & 3 deletions docs/source/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Reference

classes/index.rst
netlist_types
built_in_architecture
functions/index
element_data
clone
uniquify
NamespaceManager
verilog_support
eblif_support
Callback_Framework
extensions
introduction
archive/index
35 changes: 35 additions & 0 deletions examples/basic/built_in_libraries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
=====================================
Using Built-In Primitive Libraries
=====================================
A simple example to demonstrate using SpyDrNet's built in primitive libraries.
The b13 example netlist is targeted towards the Xilinx 7 Series family. However, because the primitives are defined in the netlist, we must first compose it out to a new netlist that does not define the primitives.
netlist_1 is parsed in without using the built in primitive library. The output shows that the port directions are undefined.
netlist_2 is parsed in using the XILINX_7SERIES primitive library. The output shows that the port directions are defined.
"""

import spydrnet as sdn
from spydrnet.util.netlist_type import VERILOG
from spydrnet.util.architecture import XILINX_7SERIES


netlist = sdn.load_example_netlist_by_name("b13", VERILOG)
netlist.compose("b13.v", write_blackbox = False)

print("Without using the primitive library:")
netlist_1 = sdn.parse("b13.v")
for definition in netlist_1.get_definitions():
if definition is not netlist_1.top_instance.reference:
for port in definition.get_ports():
print(port.name + " " + str(port.direction))

print("\nUsing the primitive library:")
netlist_2 = sdn.parse("b13.v", XILINX_7SERIES)
for definition in netlist_2.get_definitions():
if definition is not netlist_2.top_instance.reference:
for port in definition.get_ports():
print(port.name + " " + str(port.direction))
2 changes: 1 addition & 1 deletion examples/basic/plot_stat.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
for definition in library.definitions:
# Gets the name of the current definition and how many times its been used
print("\tDefinition name:", definition['EDIF.identifier'])
print("\t\t", "Defintion used", str(len(definition.references)), "times")
print("\t\t", "Definition used", str(len(definition.references)), "times")
# Gets the number of Ports in definition
print("\t\t", str(len(definition.ports)), "ports detected")
# Loop through each port for the current definition
Expand Down
9 changes: 6 additions & 3 deletions spydrnet/composers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os


def compose(netlist, filename, definition_list=[], write_blackbox=True, write_eblif_cname=True):
def compose(netlist, filename, voters=[], definition_list=[], write_blackbox=True, write_eblif_cname=True, defparam = False, reinsert_space=False):
"""To compose a file into a netlist format"""
extension = os.path.splitext(filename)[1]
extension_lower = extension.lower()
Expand All @@ -11,9 +11,12 @@ def compose(netlist, filename, definition_list=[], write_blackbox=True, write_eb
if netlist.name is None:
raise Exception("netlist.name undefined")
composer.run(netlist, filename)
elif extension_lower in [".v", ".vh"]:
elif extension_lower in [".v", ".vh", ".vm"]:
if reinsert_space:
from spydrnet.util.reinsert_space import reinserting_space
reinserting_space(netlist, voters)
from spydrnet.composers.verilog.composer import Composer
composer = Composer(definition_list, write_blackbox)
composer = Composer(definition_list, write_blackbox, defparam)
composer.run(netlist, file_out=filename)
elif extension_lower in [".eblif",".blif"]:
from spydrnet.composers.eblif.eblif_composer import EBLIFComposer
Expand Down
108 changes: 48 additions & 60 deletions spydrnet/composers/eblif/eblif_composer.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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):
def __init__(self, write_blackbox, write_cname=True):
self.netlist = None
self.current_model = None
self.open_file = None
self.write_blackbox = write_blackbox
self.write_cname = write_cname
self.models_written = []
self.blackboxes_to_compose = set()

def run(self, ir, file_out):
Expand All @@ -30,33 +31,42 @@ def clean_up(self):

def _compose(self,ir):
self.netlist = ir
# print("Composing...")
self.compose_comments()
self.compose_top_model()
self.compose_models()
self.clean_up()

def compose_comments(self):
for comment in self.netlist["EBLIF.comment"]:
to_write = "# "+comment+"\n"
self.write_out(to_write)
if "EBLIF.comment" in self.netlist.data:
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"
def compose_models(self):
self.compose_model(self.netlist.top_instance.reference)
for model in self.netlist.get_hinstances(recursive=True):
model = model.item.reference
if model not in self.models_written:
self.compose_model(model)
self.models_written.append(model)
if self.write_blackbox:
self.compose_blackboxes()

def compose_model(self, model):
if model.library.name == "hdi_primitives":
return
self.current_model = model
to_write = ".model " + model.name + "\n"
self.write_out(to_write)
self.compose_top_level_ports()
self.compose_top_level_clocks()
self.compose_default_wires()
self.compose_model_ports()
self.compose_model_clocks()
self.compose_instances()
self.compose_end()
if (self.write_blackbox):
self.compose_blackboxes()

def compose_top_level_ports(self):
def compose_model_ports(self):
to_write = ".inputs "
for port in self.netlist.top_instance.get_ports(filter = lambda x: x.direction is sdn.Port.Direction.IN):
for port in self.current_model.get_ports(filter = lambda x: x.direction in {sdn.IN, sdn.INOUT}):
if len(port.pins) > 1:
for i in range(len(port.pins)):
to_write+=port.name+"["+str(i)+"] "
Expand All @@ -66,7 +76,7 @@ def compose_top_level_ports(self):
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):
for port in self.current_model.get_ports(filter = lambda x: x.direction in {sdn.OUT, sdn.INOUT}):
if len(port.pins) > 1:
for i in range(len(port.pins)):
to_write+=port.name+"["+str(i)+"] "
Expand All @@ -75,28 +85,13 @@ def compose_top_level_ports(self):
to_write+="\n"
self.write_out(to_write)

def compose_top_level_clocks(self):
if "EBLIF.clock" in self.netlist.top_instance.data:
def compose_model_clocks(self):
if "EBLIF.clock" in self.current_model.data:
to_write = ".clock "
for clock in self.netlist.top_instance["EBLIF.clock"]:
for clock in self.current_model["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():
Expand All @@ -112,7 +107,7 @@ def compose_instances(self):

def separate_by_type(self):
dict_by_types = dict()
for instance in self.netlist.get_instances():
for instance in self.current_model.children:
try:
instance["EBLIF.type"]
except KeyError:
Expand All @@ -128,7 +123,8 @@ def separate_by_type(self):

def compose_subcircuits(self,list_of_subcircuits,is_gate=False):
for subckt in list_of_subcircuits:
self.blackboxes_to_compose.add(subckt.reference.name)
if (subckt.is_leaf()):
self.blackboxes_to_compose.add(subckt.reference)
to_add = ""
if is_gate:
to_write = ".gate "+ subckt.reference.name+" "
Expand Down Expand Up @@ -193,20 +189,15 @@ def compose_names(self,list_of_names):
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)
Expand All @@ -222,9 +213,6 @@ def find_connected_wire_info(self,pin):
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():
Expand All @@ -235,19 +223,19 @@ def find_and_write_additional_instance_info(self,instance):
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()
primitive_library = next(self.netlist.get_libraries("hdi_primitives"))
for definition in primitive_library.definitions:
if definition in self.blackboxes_to_compose:
to_write = ".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")
self.write_out(".end\n\n")
10 changes: 3 additions & 7 deletions spydrnet/composers/eblif/tests/test_eblif_composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,9 @@ def test_cables(self):
cables_2.sort()
self.assertEqual(cables_1,cables_2)
self.assertEqual(len(cables_1),len(cables_2))

def test_no_blackbox_netlist(self):
for definition in self.netlist_1.get_definitions(filter=lambda x: (x is not self.netlist_1.top_instance.reference
and "logic-gate_0" not in x.name)):
self.assertTrue("EBLIF.blackbox" in definition.data.keys(),definition.name+" is not a blackbox"+str(definition.data))
for definition in self.netlist_3.get_definitions(filter=lambda x: x is not self.netlist_3.top_instance.reference):
self.assertFalse("EBLIF.blackbox" in definition.data,definition.name+" is a blackbox"+str(definition.data))


# TODO add wires and connections tests

# test the composing of each individual part

Loading

0 comments on commit 9063e17

Please sign in to comment.