Repository: byuccl/spydrnet (language: python)

Issue:
[Bugfix] constant net name 
`SpyDrNet` currently supports single-bit constant declaration. 
However during parsing it names `1'b1` and `1'b0` both as  `\\<constb> `
This PR fixes the that and creates distinct net  `\\<const1> ` and  `\\<const0> ` respectively.
Added unit test also


Discussion / hints:

Fix patch:
diff --git a/docs/source/reference/archive/index.rst b/docs/source/reference/archive/index.rst
new file mode 100644
index 00000000..1314e6fb
--- /dev/null
+++ b/docs/source/reference/archive/index.rst
@@ -0,0 +1,12 @@
+.. _archive:
+
+===========
+Archive
+===========
+
+The following is from older versions of the SpyDrNet documentation 
+
+.. toctree::
+   :maxdepth: 2
+
+   introduction
\ No newline at end of file
diff --git a/docs/source/reference/introduction.rst b/docs/source/reference/archive/introduction.rst
similarity index 99%
rename from docs/source/reference/introduction.rst
rename to docs/source/reference/archive/introduction.rst
index e2555a27..474fed25 100644
--- a/docs/source/reference/introduction.rst
+++ b/docs/source/reference/archive/introduction.rst
@@ -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
 
@@ -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
 
diff --git a/docs/source/reference/built_in_architecture.rst b/docs/source/reference/built_in_architecture.rst
new file mode 100644
index 00000000..b867a4c1
--- /dev/null
+++ b/docs/source/reference/built_in_architecture.rst
@@ -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 
\ No newline at end of file
diff --git a/docs/source/reference/clone.rst b/docs/source/reference/functions/clone.rst
similarity index 100%
rename from docs/source/reference/clone.rst
rename to docs/source/reference/functions/clone.rst
diff --git a/docs/source/reference/functions/index.rst b/docs/source/reference/functions/index.rst
new file mode 100644
index 00000000..ede6db95
--- /dev/null
+++ b/docs/source/reference/functions/index.rst
@@ -0,0 +1,12 @@
+.. _functions:
+
+Functions (Additional Information)
+----------------------------------
+
+Included are some SpyDrNet functions that are worth highlighting:
+
+.. toctree::
+   :maxdepth: 2
+
+   uniquify
+   clone
diff --git a/docs/source/reference/uniquify.rst b/docs/source/reference/functions/uniquify.rst
similarity index 100%
rename from docs/source/reference/uniquify.rst
rename to docs/source/reference/functions/uniquify.rst
diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst
index 5a3752dd..0f367b12 100644
--- a/docs/source/reference/index.rst
+++ b/docs/source/reference/index.rst
@@ -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
\ No newline at end of file
+   archive/index
\ No newline at end of file
diff --git a/examples/basic/built_in_libraries.py b/examples/basic/built_in_libraries.py
new file mode 100644
index 00000000..c2d4075c
--- /dev/null
+++ b/examples/basic/built_in_libraries.py
@@ -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))
diff --git a/examples/basic/plot_stat.py b/examples/basic/plot_stat.py
index 31124769..ecbd9cf2 100644
--- a/examples/basic/plot_stat.py
+++ b/examples/basic/plot_stat.py
@@ -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
diff --git a/spydrnet/composers/__init__.py b/spydrnet/composers/__init__.py
index 153f64c4..f1d5a0c3 100644
--- a/spydrnet/composers/__init__.py
+++ b/spydrnet/composers/__init__.py
@@ -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()
@@ -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
diff --git a/spydrnet/composers/eblif/eblif_composer.py b/spydrnet/composers/eblif/eblif_composer.py
index ad8bcac8..69056c04 100644
--- a/spydrnet/composers/eblif/eblif_composer.py
+++ b/spydrnet/composers/eblif/eblif_composer.py
@@ -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):
@@ -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)+"] "
@@ -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)+"] "
@@ -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():
@@ -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:
@@ -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+" "
@@ -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)
@@ -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():
@@ -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")
diff --git a/spydrnet/composers/verilog/composer.py b/spydrnet/composers/verilog/composer.py
index 879789a8..55406c6a 100644
--- a/spydrnet/composers/verilog/composer.py
+++ b/spydrnet/composers/verilog/composer.py
@@ -2,18 +2,20 @@
 from spydrnet.ir import Port
 from spydrnet.ir import Cable
 import spydrnet.parsers.verilog.verilog_tokens as vt
-
+import spydrnet as sdn
 
 class Composer:
 
-    def __init__(self, definition_list=None, write_blackbox=False):
+    def __init__(self, definition_list=None, write_blackbox=False, defparam = False, reverse=False):
         """ Write a verilog netlist from SDN netlist
 
         parameters
         ----------
 
-        definition_list - (list[str]) list of defintions to write
+        definition_list - (list[str]) list of definitions to write
         write_blackbox - (bool) Skips writing black boxes/verilog primitives
+        defparam - (bool) Compose parameters in *defparam* statements instead of using #()
+        reverse - (bool) Compose the netlist bottom to top
         """
         self.file = None
         self.direction_string_map = dict()
@@ -25,12 +27,15 @@ def __init__(self, definition_list=None, write_blackbox=False):
         self.indent_count = 4  # set the indentation level for various components
         self.write_blackbox = write_blackbox
         self.definition_list = definition_list
+        self.defparam = defparam
+        self.module_body_ports_written = []
+        self.reverse = reverse
 
 
     def run(self, ir, file_out="out.v"):
         self._open_file(file_out)
         self._compose(ir)
-
+        
     def _open_file(self, file_name):
         f = open(file_name, "w")
         self.file = f
@@ -39,7 +44,10 @@ def _compose(self, netlist):
         self._write_header(netlist)
         instance = netlist.top_instance
         if instance is not None:
-            self._write_from_top(instance)
+            if self.reverse:
+                self._write_from_bottom(instance)
+            else:
+                self._write_from_top(instance)
         for library in netlist.libraries:
             for definition in library.definitions:
                 if definition not in self.written:
@@ -65,6 +73,28 @@ def _write_from_top(self, instance):
                 "definition has no name set", definition)
             self._write_module(definition)
 
+    def _write_from_bottom(self, instance):
+        # ****this may need more work****
+        visited = []
+        to_write_list = deque()
+        to_write_stack = []
+        to_write_list.append(instance.reference)
+        to_write_stack.append(instance.reference)
+        while(len(to_write_list) != 0):
+            definition = to_write_list.popleft()
+            if definition in visited:
+                continue
+            visited.append(definition)
+            for c in definition.children:
+                if c.reference not in visited:
+                    to_write_list.append(c.reference)
+                    to_write_stack.append(c.reference)
+        # print(list(x.name for x in to_write_stack if len(x.children) > 0))
+        while(to_write_stack):
+            definition = to_write_stack.pop()
+            if definition not in self.written:
+                self.written.add(definition)
+                self._write_module(definition)
 
     ###########################################################################
     # Write verilog constructs
@@ -110,7 +140,7 @@ def _write_module(self, definition):
                 return
         if definition.library.name == "SDN_VERILOG_ASSIGNMENT":
             return  # don't write assignment definitions
-        if definition.library.name == "SDN.verilog_primitives":
+        if definition.library.name == "hdi_primitives":
             if not self.write_blackbox:
                 return
             self.file.write(vt.CELL_DEFINE)
@@ -119,7 +149,7 @@ def _write_module(self, definition):
         self._write_module_header(definition)
         self._write_module_body(definition)
         self.file.write(vt.END_MODULE)
-        if definition.library.name == "SDN.verilog_primitives":
+        if definition.library.name == "hdi_primitives":
             self.file.write(vt.NEW_LINE)
             self.file.write(vt.END_CELL_DEFINE)
 
@@ -142,7 +172,7 @@ def _write_module_header(self, definition):
     def _write_module_body(self, definition):
         '''write out the module body start with ports, then do assignments then instances'''
         self._write_module_body_ports(definition)
-        if definition.library.name != "SDN.verilog_primitives":
+        if definition.library.name != "hdi_primitives":
             self._write_module_body_cables(definition)
             self._write_assignments(definition)
             self._write_module_body_instances(definition)
@@ -158,15 +188,24 @@ def _write_module_body_instance(self, instance):
         self.file.write(self.indent_count * vt.SPACE)
         self._write_name(instance.reference)
         self.file.write(vt.SPACE)
-        if "VERILOG.Parameters" in instance:
-            self._write_instance_parameters(instance)
-            self.file.write(self.indent_count * vt.SPACE)
+        if not self.defparam:
+            if "VERILOG.Parameters" in instance:
+                self._write_instance_parameters(instance)
+                self.file.write(self.indent_count * vt.SPACE)
         self._write_name(instance)
         self.file.write(vt.NEW_LINE)
         self._write_instance_ports(instance)
         self.file.write(vt.NEW_LINE)
+        if self.defparam:
+            if "VERILOG.Parameters" in instance:
+                for key, value in instance["VERILOG.Parameters"].items():
+                    to_write = (self.indent_count * vt.SPACE) + vt.DEFPARAM + vt.SPACE
+                    to_write += instance.name + vt.DOT + key + vt.EQUAL
+                    to_write += value + vt.SEMI_COLON + vt.NEW_LINE
+                    self.file.write(to_write)
 
     def _write_module_body_ports(self, definition):
+        self.module_body_ports_written = []
         for p in definition.ports:
             self._write_module_body_port(p)
         self.file.write(vt.NEW_LINE)
@@ -176,6 +215,9 @@ def _write_module_body_port(self, port):
         if len(cables) == 0:
             cables.append(port) #adding the port will let composer to still print out disconnected ports
         for c in cables:
+            if c.name in self.module_body_ports_written:
+                continue
+            self.module_body_ports_written.append(c.name)
             self._write_star_constraints(port)
             self.file.write(self.indent_count * vt.SPACE)
             self.file.write(self.direction_string_map[port.direction])
@@ -186,7 +228,9 @@ def _write_module_body_port(self, port):
             self.file.write(vt.NEW_LINE)
 
     def _write_module_body_cables(self, definition):
-        for c in definition.cables:
+        cable_list = list(c for c in definition.cables)
+        cable_list.reverse()
+        for c in cable_list:
             self._write_module_body_cable(c)
         self.file.write(vt.NEW_LINE)
 
@@ -208,17 +252,47 @@ def _write_concatenation(self, wires):
         {wire_1, wire_2}'''
         self.file.write(vt.OPEN_BRACE)
         first = True
+        previous_cable = Cable()
+        first_index = 0
+        previous_index = 0
+        has_to_write = False
         for w in wires:
             if w is not None:
-                if not first:
-                    self.file.write(vt.COMMA)
-                    self.file.write(vt.SPACE)
                 index = self._index_of_wire_in_cable(w)
-                self._write_bundle_with_indicies(w.cable, index, None)
+                if w.cable.name == previous_cable.name:
+                    if index == (previous_index - 1):
+                        previous_index = index
+                    else:
+                        #write the previous and save new stuff
+                        if not first:
+                            self.file.write(vt.COMMA)
+                            self.file.write(vt.SPACE)
+                        self._write_bundle_with_indicies(previous_cable, previous_index, first_index)
+                        first = False
+                        previous_cable = w.cable
+                        first_index = index
+                        previous_index = index
+                else:
+                    if has_to_write:
+                        #write the previous and save new stuff
+                        if not first:
+                            self.file.write(vt.COMMA)
+                            self.file.write(vt.SPACE)
+                        self._write_bundle_with_indicies(previous_cable, previous_index, first_index)
+                        first = False
+                    previous_cable = w.cable
+                    first_index = index
+                    previous_index = index
+                has_to_write = True
             else:
-                break
+                None
+                # break
+        if has_to_write:
+            if not first:
+                self.file.write(vt.COMMA)
+                self.file.write(vt.SPACE)
+            self._write_bundle_with_indicies(previous_cable, previous_index, first_index)
 
-            first = False
         self.file.write(vt.CLOSE_BRACE)
 
     def _write_module_header_ports(self, definition):
@@ -234,6 +308,11 @@ def _write_module_header_ports(self, definition):
         self.file.write(vt.CLOSE_PARENTHESIS)
         self.file.write(vt.SEMI_COLON)
         self.file.write(vt.NEW_LINE)
+    
+    def pin_sort_func(self, p):
+        if isinstance(p, sdn.OuterPin):
+            return p.inner_pin.port.pins.index(p.inner_pin)
+        return p.port.pins.index(p)
 
     def _write_module_header_port(self, port):
         '''does not write the input output or width, 
@@ -242,8 +321,10 @@ def _write_module_header_port(self, port):
         aliased = self._is_pinset_concatenated(port.pins, port.name)
         if aliased:
             wires = []
-            for p in port.pins:
-                wires.append(p.wire)
+            pin_list = list(p for p in port.pins)
+            pin_list.sort(reverse=True, key=self.pin_sort_func)
+            for pin in pin_list:
+                wires.append(pin.wire)
             self.file.write(vt.DOT)
             self._write_name(port)
             self.file.write(vt.OPEN_PARENTHESIS)
@@ -358,13 +439,51 @@ def _write_instance_ports(self, instance):
             if not first:
                 self.file.write(vt.COMMA)
                 self.file.write(vt.NEW_LINE)
-            self._write_instance_port(instance, p)
+            if p.name:
+                self._write_instance_port(instance, p)
+            else:
+                self._write_implicitly_mapped_instance_port(instance, p)
             first = False
         self.file.write(vt.NEW_LINE)
         self.file.write(self.indent_count * vt.SPACE)
         self.file.write(vt.CLOSE_PARENTHESIS)
         self.file.write(vt.SEMI_COLON)
 
+    def _write_implicitly_mapped_instance_port(self, instance, port):
+        '''Ports that have no name must be implicitly mapped. E.g. inst(VCC_net) rather than inst(.p(VCC_net))'''
+        self.file.write(2*self.indent_count * vt.SPACE)
+        # self.file.write(vt.DOT)
+        # self._write_name(port)
+        # self.file.write(vt.OPEN_PARENTHESIS)
+        pins = []
+        for p in port.pins:
+            pins.append(instance.pins[p])
+        if pins[0].wire is not None:
+            name = pins[0].wire.cable.name
+        else:
+            name = None
+        concatenated = self._is_pinset_concatenated(pins, name)
+        wires = []
+        pin_list = list(p for p in port.pins)
+        pin_list.sort(reverse=True, key=self.pin_sort_func)
+        for pin in pin_list:
+            wires.append(pin.wire)
+        if concatenated:
+            self._write_concatenation(wires)
+        else:
+            if pins[0].wire is not None:
+                last = -1
+                wl = wires[last]
+                wr = wires[0]
+                while wl is None:  # get the last named non none wire.
+                    last = last - 1
+                    wl = wires[last]
+                il = self._index_of_wire_in_cable(wl)
+                ir = self._index_of_wire_in_cable(wr)
+                self._write_bundle_with_indicies(wl.cable, ir, il)
+
+        # self.file.write(vt.CLOSE_PARENTHESIS)
+
     def _write_instance_port(self, instance, port):
         self.file.write(2*self.indent_count * vt.SPACE)
         self.file.write(vt.DOT)
@@ -379,10 +498,15 @@ def _write_instance_port(self, instance, port):
             name = None
         concatenated = self._is_pinset_concatenated(pins, name)
         wires = []
+        sorted_wires = []
+        pin_list = list(p for p in pins)
+        pin_list.sort(reverse=True, key=self.pin_sort_func)
+        for pin in pin_list:
+            sorted_wires.append(pin.wire)
         for p in pins:
             wires.append(p.wire)
         if concatenated:
-            self._write_concatenation(wires)
+            self._write_concatenation(sorted_wires)
         else:
             if pins[0].wire is not None:
                 last = -1
@@ -455,6 +579,7 @@ def _write_brackets(self, bundle, low_index, high_index):
                 self._error_string("attempted to index bundle out of bounds at " + str(high_index), bundle)
             return
         elif (low_index == lower_bundle and high_index == upper_bundle) or (low_index == None and high_index == None):
+            self.file.write("[" + str(high_index) + ":" + str(low_index) + "]")
             return
         elif low_index == high_index or low_index is None or high_index is None:
             index = low_index
@@ -513,7 +638,20 @@ def _is_pinset_concatenated(self, pins, name):
             if next_name != name and not now_none:
                 aliased = True
                 break
-            
+
+        # if all the wires connected to the pins are from the same cable, don't count as aliased
+        # otherwise, return previous answer
+        # TODO maybe also check if all of the cable is used. So no skipped wires.
+        # name = None
+        # for p in pins:
+        #     if p.wire is None:
+        #         continue
+        #     if not name:
+        #         name = p.wire.cable.name
+        #         continue
+        #     if p.wire.cable.name is not name:
+        #         return aliased
+        # return False
         return aliased
 
     def _all_wires_and_cables_from_pinset(self, pins):
diff --git a/spydrnet/ir/outerpin.py b/spydrnet/ir/outerpin.py
index fd540434..d993b66a 100644
--- a/spydrnet/ir/outerpin.py
+++ b/spydrnet/ir/outerpin.py
@@ -93,3 +93,6 @@ def clone(self):
         c = self._clone(dict())
         c._clone_rip()
         return c
+
+    def index(self):
+        return self._inner_pin.port.pins.index(self._inner_pin)
\ No newline at end of file
diff --git a/spydrnet/parsers/__init__.py b/spydrnet/parsers/__init__.py
index 77f4c1ec..dae59ef5 100644
--- a/spydrnet/parsers/__init__.py
+++ b/spydrnet/parsers/__init__.py
@@ -8,7 +8,7 @@
 """
 
 
-def parse(filename):
+def parse(filename, architecture=None, remove_space=False):
     """
     The parse function is able to parse an EDIF (.edf) file, a Verilog file (.v), or an EBLIF file (.eblif).
 
@@ -51,15 +51,15 @@ def parse(filename):
                 filename = os.path.join(
                     tempdirname, basename_less_final_extension)
                 return _parse(filename)
-    return _parse(filename)
+    return _parse(filename, architecture, remove_space)
 
 
-def _parse(filename):
+def _parse(filename, architecture=None, remove_space=False):
     extension = get_lowercase_extension(filename)
     if extension in [".edf", ".edif", ".edn"]:
         from spydrnet.parsers.edif.parser import EdifParser
         parser = EdifParser.from_filename(filename)
-    elif extension in [".v", ".vh"]:
+    elif extension in [".v", ".vh", ".vm"]:
         from spydrnet.parsers.verilog.parser import VerilogParser
         parser = VerilogParser.from_filename(filename)
     elif extension in [".eblif",".blif"]:
@@ -68,6 +68,15 @@ def _parse(filename):
     else:
         raise RuntimeError("Extension {} not recognized.".format(extension))
     parser.parse()
+    
+    if remove_space:
+        from spydrnet.util.remove_space import removing_space
+        removing_space(parser.netlist)
+
+    if architecture:
+        read_primitive_library(architecture, parser.netlist)
+        if extension in [".eblif",".blif"]:
+            set_eblif_names(parser.netlist)
     return parser.netlist
 
 
@@ -75,3 +84,14 @@ def get_lowercase_extension(filename):
     extension = os.path.splitext(filename)[1]
     extension_lower = extension.lower()
     return extension_lower
+
+def read_primitive_library(architecture, netlist):
+    from spydrnet.parsers.primitive_library_reader import PrimitiveLibraryReader
+    reader = PrimitiveLibraryReader(architecture, netlist)
+    reader.run()
+
+def set_eblif_names(netlist):
+    from spydrnet.parsers.eblif.eblif_parser import EBLIFParser
+    eblif_parser = EBLIFParser()
+    eblif_parser.netlist = netlist
+    eblif_parser.set_subcircuit_names_by_convention()
\ No newline at end of file
diff --git a/spydrnet/parsers/eblif/eblif_parser.py b/spydrnet/parsers/eblif/eblif_parser.py
index ace56da9..1db1c7c4 100644
--- a/spydrnet/parsers/eblif/eblif_parser.py
+++ b/spydrnet/parsers/eblif/eblif_parser.py
@@ -1,12 +1,10 @@
 import spydrnet as sdn
-from spydrnet.parsers.eblif.eblif_tokens import *
+import spydrnet.parsers.eblif.eblif_tokens as et
 from spydrnet.parsers.eblif.eblif_tokenizer import Tokenizer
 from spydrnet.ir import Netlist
-from spydrnet.ir import Definition
 from spydrnet.ir import Instance
 from spydrnet.ir import Port
 from spydrnet.ir import InnerPin
-from spydrnet.ir.outerpin import OuterPin
 from spydrnet.ir import Wire
 from spydrnet.util.selection import Selection
 
@@ -14,9 +12,38 @@ class EBLIFParser:
     """
     Parse BLIF and EBLIF files into SpyDrNet
 
-    The first model is considered the netlist's top instance. Any model that follows is used as information for the definitions (aka primitive information)
-
     """
+
+    class BlackboxHolder:
+        '''this is an internal class that helps manage
+        modules that are instanced before they are declared'''
+
+        def __init__(self):
+            self.name_lookup = {}
+            self.defined = set()
+
+        def get_blackbox(self, name):
+            '''creates or returns the black box based on the name'''
+            if name in self.name_lookup:
+                return self.name_lookup[name]
+            else:
+                definition = sdn.Definition()
+                definition.name = name
+                self.name_lookup[name] = definition
+                return definition
+
+        def define(self, name):
+            '''adds the name to the defined set'''
+            self.defined.add(self.name_lookup[name])
+
+        def get_undefined_blackboxes(self):
+            '''return an iterable of all undefined blackboxes'''
+            undef = set()
+            for v in self.name_lookup.values():
+                if v not in self.defined:
+                    undef.add(v)
+            return undef
+
     #######################################################
     # setup functions
     #######################################################
@@ -36,19 +63,14 @@ def __init__(self):
         self.file_name = None
         self.tokenizer = None
         self.netlist = None
-        self.current_instance_info = dict()
-        # self.top_instance = None
+        self.current_instance_info = {}
         self.current_instance = None
-        # self.latest_definition = None
-        # self.information = dict()
-        self.definitions = dict()
-        self.cables = dict()
-        self.default_names = dict()
-        self.top_level_input_ports = dict()
-        self.top_level_output_ports = dict()       
-        self.comments = list() 
+        self.default_names = {}
+        self.comments = []
         self.current_model = None
-        # self.last_net = None
+        self.primitives = None
+        self.work = None
+        self.blackbox_holder = self.BlackboxHolder()
 
     def createTokenizer(self):
         self.tokenizer = Tokenizer(self.file_name)
@@ -60,284 +82,240 @@ def parse(self):
         self.createTokenizer()
         self.parse_eblif()
         return self.netlist
-    
+
     def parse_eblif(self):
-        while(self.tokenizer.has_next()):
+        netlist = Netlist()
+        self.netlist = netlist
+        self.work = self.netlist.create_library("work")
+        self.primitives = self.netlist.create_library("hdi_primitives")
+        while self.tokenizer.has_next():
             token = self.tokenizer.next()
-            if token == COMMENT:
+            if token == et.COMMENT:
                 self.parse_comment()
-            elif token == MODEL:
-                if self.netlist:
-                    self.parse_other_model()
-                else:
-                    self.parse_top_model()
+            elif token == et.MODEL:
+                self.parse_model()
             else:
                 None
         self.set_subcircuit_names_by_convention()
         self.insert_comments_into_netlist_data()
-
-    def parse_top_model(self):
-        netlist = Netlist()
-        name = self.tokenizer.next()
-        netlist.name = name
-        self.netlist = netlist
-        self.parse_top_instance()
-        self.parse_model_helper()
-
-    def parse_other_model(self):
-        name = self.tokenizer.next()
-        try:
-            self.definitions[name]
-        except KeyError:
-            # print("Error, no definition found")
-            self.definitions[name] = self.create_new_definition()
-        definition = self.definitions[name]
-        self.tokenizer.next()
-
-        while(self.tokenizer.peek() == INPUTS):
-            self.parse_other_model_input_ports(definition)
-        
-        while(self.tokenizer.peek() == OUTPUTS):
-            self.parse_other_model_output_ports(definition)
-
-        while (True):
-            self.tokenizer.next()
-            if (self.tokenizer.token == BLACKBOX):
-                definition["EBLIF.blackbox"] = True
-            elif self.tokenizer.token == END:
-                break   
-    
-    def parse_other_model_input_ports(self,definition):
-        self.expect(INPUTS)
-        self.tokenizer.next()
-        while (self.tokenizer.token is not NEW_LINE):
-            port_name, index = self.get_port_name_and_index(self.tokenizer.token)
-            index = int(index)
-            port = next(definition.get_ports(filter=lambda x: x.name == port_name))
-            port.direction = sdn.IN
-            self.tokenizer.next()
-    
-    def parse_other_model_output_ports(self,definition):
-        self.expect(OUTPUTS)
-        self.tokenizer.next()
-        while (self.tokenizer.token is not NEW_LINE):
-            port_name, index = self.get_port_name_and_index(self.tokenizer.token)
-            port = next(definition.get_ports(filter=lambda x: x.name == port_name))
-            port.direction = sdn.OUT
-            self.tokenizer.next()
-    
-    def parse_model_helper(self):
-         while(self.tokenizer.has_next()):
+        self.add_blackbox_definitions()
+
+    def parse_model(self):
+        model_name = self.tokenizer.next()
+        self.default_names = {}
+        self.parse_model_header(model_name)
+        self.parse_model_helper(model_name)
+
+    def parse_model_helper(self, model_name):
+        model = self.blackbox_holder.get_blackbox(model_name)
+        is_blackbox = False
+        while self.tokenizer.has_next():
             token = self.tokenizer.next()
-            if token == COMMENT:
+            if token == et.COMMENT:
                 self.parse_comment()
-            elif token == SUBCIRCUIT:
-                self.parse_sub_circuit()
-            elif token == GATE:
-                self.parse_sub_circuit(is_gate=True)
-            elif token == LATCH:
+            elif token == et.SUBCIRCUIT:
+                self.parse_subcircuit()
+            elif token == et.GATE:
+                self.parse_subcircuit(is_gate=True)
+            elif token == et.LATCH:
                 self.parse_latch()
-            elif token == NAMES:
+            elif token == et.NAMES:
                 self.parse_name()
-            elif token == CONN:
+            elif token == et.CONN:
                 self.parse_conn()
-            elif token == END:
+            elif token == et.BLACKBOX:
+                self.make_blackbox()
+                is_blackbox = True
+            elif token == et.END:
                 break
             else:
                 None
-    
-    def parse_top_instance(self):
-        # Libraries aren't in blif, so just create a single library
-        library = self.netlist.create_library(name="library_1")
-        top_instance_def = library.create_definition(name=self.netlist.name)
-        top_instance = Instance(name=top_instance_def.name)
-        top_instance.reference = top_instance_def
-        self.netlist.set_top_instance(top_instance)
-        self.current_model = top_instance
+        if is_blackbox:
+            self.primitives.add_definition(model)
+        else:
+            self.work.add_definition(model)
+
+    def parse_model_header(self, model_name):
+        model_def = self.blackbox_holder.get_blackbox(model_name)
+        self.blackbox_holder.define(model_name)
+        if not self.netlist.top_instance:
+            parent_instance = Instance(name=model_def.name)
+            parent_instance.reference = model_def
+            self.netlist.set_top_instance(parent_instance)
+            self.netlist.name = model_def.name
+        self.current_model = model_def
         self.tokenizer.next() # should be end of line so proceed to next line
-        self.parse_top_level_ports()
-    
-    def parse_top_level_ports(self):
-        while(self.tokenizer.peek() == INPUTS):
-            self.parse_top_level_inputs()
-        while(self.tokenizer.peek() == OUTPUTS):
-            self.parse_top_level_outputs()
-
-        while(self.tokenizer.peek() == CLOCK):
-            self.parse_top_level_clock()
-    
-    def parse_top_level_inputs(self):
-        self.expect(INPUTS)
+        self.parse_model_ports()
+
+    def parse_model_ports(self):
+        while self.tokenizer.peek() == et.INPUTS:
+            self.parse_input_ports()
+        while self.tokenizer.peek() == et.OUTPUTS:
+            self.parse_output_ports()
+        while self.tokenizer.peek() == et.CLOCK:
+            self.parse_clock()
+
+    def parse_input_ports(self):
+        self.expect(et.INPUTS)
         self.tokenizer.next()
-        while (self.tokenizer.token is not NEW_LINE):
+        while self.tokenizer.token is not et.NEW_LINE:
             port_name, index = self.get_port_name_and_index(self.tokenizer.token)
             index = int(index)
-            port = None
-            pin = None
-            if (port_name in self.top_level_input_ports.keys()):
-                port= self.top_level_input_ports[port_name]
-                pin = port.create_pin()
+            port = next(self.current_model.get_ports(port_name), None)
+            if not port:
+                port = self.create_model_port(sdn.Port.Direction.IN, port_name)
+                self.current_model.add_port(port)
             else:
-                port = self.create_top_level_port(sdn.Port.Direction.IN,port_name)
-                self.netlist.top_instance.reference.add_port(port)
-                self.top_level_input_ports[port_name] = port
-                pin = port.create_pin()
-            self.connect_pins_to_wires(pin,port_name,index)
+                port.direction=sdn.IN
+            while len(port.pins) < index+1:
+                port.create_pin()
+            pin = port.pins[index]
+            self.connect_pin_to_wire(pin,port_name,index)
             self.tokenizer.next()
-    
-    def parse_top_level_outputs(self):
-        self.expect(OUTPUTS)
+
+    def parse_output_ports(self):
+        self.expect(et.OUTPUTS)
         self.tokenizer.next()
-        while (self.tokenizer.token is not NEW_LINE):
+        while self.tokenizer.token is not et.NEW_LINE:
+            is_inout = False
             port_name, index = self.get_port_name_and_index(self.tokenizer.token)
             index = int(index)
-            port = None
-            pin = None
-            if (port_name in self.top_level_output_ports.keys()):
-                port= self.top_level_output_ports[port_name]
-                pin = port.create_pin()
+            port = next(self.current_model.get_ports(port_name), None)
+            if not port:
+                port = self.create_model_port(sdn.Port.Direction.OUT, port_name)
+                self.current_model.add_port(port)
+            if port.direction in {sdn.IN, sdn.INOUT}: # it's an input port and now an output, so it's inout
+                port.direction = sdn.INOUT
+                is_inout = True
             else:
-                port = self.create_top_level_port(sdn.Port.Direction.OUT,port_name)
-                self.netlist.top_instance.reference.add_port(port)
-                self.top_level_output_ports[port_name] = port
-                pin = port.create_pin()
-            self.connect_pins_to_wires(pin,port_name,index)
+                port.direction = sdn.OUT
+            while len(port.pins) < index+1:
+                port.create_pin()
+            pin = port.pins[index]
+            if not is_inout:
+                self.connect_pin_to_wire(pin,port_name,index)
             self.tokenizer.next()
-    
-    def parse_top_level_clock(self):
-        self.expect(CLOCK)
+
+    def create_model_port(self, port_direction, port_name):
+        port = Port(direction=port_direction)
+        port.name = port_name
+        return port
+
+    def parse_clock(self):
+        self.expect(et.CLOCK)
         self.tokenizer.next()
         try:
-            self.netlist.top_instance["EBLIF.clock"]
+            self.current_model["EBLIF.clock"]
         except KeyError:
-            self.netlist.top_instance["EBLIF.clock"] = list()
-        while (self.tokenizer.token is not NEW_LINE):
-            self.netlist.top_instance["EBLIF.clock"].append(self.tokenizer.token)
+            self.current_model["EBLIF.clock"] = []
+        while self.tokenizer.token is not et.NEW_LINE:
+            self.current_model["EBLIF.clock"].append(self.tokenizer.token)
             self.tokenizer.next()
 
-    def create_top_level_port(self,port_direction,port_name):
-        port = Port(direction=port_direction)
-        port.name = port_name
-        return port
-    
-    def connect_pins_to_wires(self, pin, cable_name, wire_index):
+    def connect_pin_to_wire(self, pin, cable_name, wire_index):
         # connect the port to a wire in a cable named after it
-        cable = None
-        if (cable_name in self.cables.keys()):
-            cable = self.cables[cable_name]
-        else:
-            cable = self.netlist.top_instance.reference.create_cable(name=cable_name)
-            self.cables[cable_name] = cable
-        try:
-            cable.wires[wire_index]
-        except IndexError:
-            while (len(cable.wires)-1 < wire_index): # add wires to cable until we get the right index
-                wire = Wire()
-                cable.add_wire(wire,wire_index)
-            # wire = Wire()
-            # cable.add_wire(wire,wire_index)
+        cable = next(self.current_model.get_cables(cable_name), None)
+        if not cable:
+            cable = self.current_model.create_cable(name=cable_name)
+        while (len(cable.wires)-1) < wire_index: # add wires to cable until we get the right index
+            wire = Wire()
+            cable.add_wire(wire,wire_index)
         wire = cable.wires[wire_index]
         wire.connect_pin(pin)
 
-    def parse_sub_circuit(self,is_gate=False):
-        # print(self.tokenizer.token)
+    def parse_subcircuit(self, is_gate=False):
         self.current_instance_info.clear()
         reference_model = self.tokenizer.next()
-        definition = None
-        if reference_model not in list(key for key in self.definitions.keys()):  # if the reference model is not found in the netlist, create it
-            definition = self.create_new_definition()
-            # Note: if a definition is created, instance information is automatically collected
-        else:
-            definition = self.definitions[reference_model]
-            self.collect_subcircuit_information()
-        instance = self.netlist.top_instance.reference.create_child(reference = definition)
+        self.check_hierarchy(reference_model)
+        definition = self.blackbox_holder.get_blackbox(reference_model)
+        self.tokenizer.next()
+        while self.tokenizer.token is not et.NEW_LINE:
+            self.parse_subcircuit_port(definition)
+            self.tokenizer.next()
+
+        instance = self.current_model.create_child(reference=definition)
         self.current_instance = instance
         if is_gate:
             instance["EBLIF.type"] = "EBLIF.gate"
         else:
             instance["EBLIF.type"] = "EBLIF.subckt"
+
         self.assign_instance_a_default_name(instance)
-        # print(self.current_instance_info)
         self.connect_instance_pins(instance)
-        self.check_for_and_add_more_instance_info()
+        self.parse_instance_info()
 
-    def create_new_definition(self):
-        definition = self.netlist.libraries[0].create_definition(name = self.tokenizer.token)
-        # print("GONNA MAKE DEFINITION: " + self.tokenizer.token)
-        self.tokenizer.next()
-        # print("now token is "+self.tokenizer.token)
-        while (self.tokenizer.token is not NEW_LINE):
-            self.parse_definition_port(definition)
-            self.tokenizer.next()
-        self.definitions[definition.name] = definition
-        return definition
-
-    def parse_definition_port(self,definition):
-        port = Port()
+    def parse_subcircuit_port(self, definition):
         token = self.tokenizer.token
         equal_index = token.find("=")
         port_name_and_index = token[:equal_index]
-        name,index = self.get_port_name_and_index(port_name_and_index)
-        if name in list(x.name for x in definition.ports):
-            # print(name + " is in "+ str(list(x.name for x in definition.ports)))
-            port = next(x for x in definition.ports if x.name == name)
+        name, index = self.get_port_name_and_index(port_name_and_index)
+        port = next(definition.get_ports(name), None)
+        if not port:
+            port = definition.create_port(name=name)
+        if index > (len(port.pins) - 1):
             pin = InnerPin()
             port.add_pin(pin,index)
-            # print("added a pin at index "+str(index))
-            self.current_instance_info[port_name_and_index] = token[equal_index+1:]
-        else:
-            new_port = Port()
-            new_port.name = name
-            pin = InnerPin()
-            new_port.add_pin(pin,index)
-            self.current_instance_info[port_name_and_index] = token[equal_index+1:]
-            definition.add_port(new_port)
-            # port.create_pin()
-        # return port
-
-    def collect_subcircuit_information(self):
-        self.tokenizer.next()
-        while (self.tokenizer.token is not NEW_LINE):
-            token = self.tokenizer.token
-            equal_index = token.find("=")
-            port_name =token[:equal_index]
-            self.current_instance_info[port_name] = token[equal_index+1:]
-            self.tokenizer.next()
+        self.current_instance_info[port_name_and_index] = token[equal_index+1:]
+
+    def check_hierarchy(self, child_definition_name):
+        if child_definition_name == self.netlist.top_instance.reference.name:
+            # print(self.current_definition.name + " is instancing the current top instance (" + name+ " which is a "+ self.netlist.top_instance.reference.name+")")
+            old_top_instance = self.netlist.top_instance
+            new_level = self.current_model
+            # we know the current top is not right. So now we can move it up a level.
+            # But double check to make sure nothing is instancing the potential new top.
+            # Move up levels until we reach a new top
+            if len(self.current_model.references) > 0:
+                current_level = list(x for x in self.current_model.references)[0]
+                while True:
+                    current_level = current_level.parent
+                    try:
+                        current_level.parent
+                    except AttributeError:
+                        new_level = current_level
+                        break
+
+            self.netlist.top_instance = sdn.Instance()
+            self.netlist.top_instance.name = new_level.name
+            self.netlist.top_instance.reference = new_level
+            self.netlist.name = new_level.name
+
+            # this instance should just go away. It was created to be the top instance but we don't want that
+            # it has no parent. And now with no reference, it should have no ties to the netlist.
+            old_top_instance.reference = None
 
     def connect_instance_pins(self,instance):
-        for key in self.current_instance_info.keys():
-            cable_info = self.current_instance_info[key]
-            cable_name,cable_index = self.get_port_name_and_index(cable_info) # get connected cable name and wire index
+        for key, cable_info in self.current_instance_info.items():
+            # cable_info = self.current_instance_info[key]
+            cable_name, cable_index = self.get_port_name_and_index(cable_info) # get connected cable name and wire index
             port_name, pin_index = self.get_port_name_and_index(key) # get own port name and pin index
-            if (cable_name == UNCONN):  # intentionally disconnected so put that into metadata
+            if cable_name == et.UNCONN:  # intentionally disconnected so put that into metadata
                 try:
-                    instance[UNCONN]
+                    instance[et.UNCONN]
                 except KeyError:
-                    instance[UNCONN] = list()
-                instance[UNCONN].append(port_name+"["+str(pin_index)+"]")
+                    instance[et.UNCONN] = []
+                instance[et.UNCONN].append(port_name+"["+str(pin_index)+"]")
                 continue
-            # print(port_name)
-            # print(list(x.inner_pin.port.name for x in instance.get_pins(selection=Selection.OUTSIDE)))
-            pin = next(instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.name == port_name and x.inner_pin is x.inner_pin.port.pins[pin_index]))
-            self.connect_pins_to_wires(pin,cable_name,cable_index)
+
+            port = next(instance.get_ports(port_name))
+            while len(port.pins) < (pin_index+1): # multibit port that isn't yet multibit
+                port.create_pin()
+            pin = next(instance.get_pins(selection=Selection.OUTSIDE, filter=lambda x: x.inner_pin.port.name == port_name and x.inner_pin is x.inner_pin.port.pins[pin_index]))
+            self.connect_pin_to_wire(pin, cable_name, cable_index)
 
     def parse_comment(self):
         token = self.tokenizer.next()
         comment = ""
-        while (token is not NEW_LINE):
+        while token is not et.NEW_LINE:
             comment+=token+" "
             token = self.tokenizer.next()
         self.comments.append(comment)
-    
+
     def insert_comments_into_netlist_data(self):
         self.netlist["EBLIF.comment"] = self.comments
 
-    def expect(self, token):
-        self.tokenizer.next()
-        self.tokenizer.expect(token)
-
     def get_port_name_and_index(self,string):
-        index_specified = (string[len(string)-1] == "]")
+        index_specified = (string[-1] == "]")
         if index_specified:
             open_bracket = string.rfind("[")
             if open_bracket == -1:
@@ -349,101 +327,99 @@ def get_port_name_and_index(self,string):
                 if ":" in index:
                     old_index = index
                     index = index[:index.find(':')]
-                    print("Index was: "+old_index+". To avoid an error, it was changed to "+index)
+                    print("EBLIFParser: Index was: " + old_index + ". To avoid an error, it was changed to " + index)
                 return name, int(index)
         else:
             return string, 0
 
-    def assign_instance_a_default_name(self,instance):
+    def assign_instance_a_default_name(self, instance):
         name = instance.reference.name
         index = 0
         if name in self.default_names.keys():
-            index = self.default_names[name]+1
+            index = self.default_names[name] + 1
             self.default_names[name]+=1
         else:
             index = 0
             self.default_names[name] = 0
-        name = name+"_instance_"+str(index)
+        name = name + "_instance_" + str(index)
         instance.name = name
-    
-    def check_for_and_add_more_instance_info(self):
-        while(True):
+
+    def parse_instance_info(self):
+        while True:
             peeked_token = self.tokenizer.peek()
-            if (peeked_token == PARAM):
+            if peeked_token == et.PARAM:
                 self.parse_param()
-            elif (peeked_token == CNAME):
+            elif peeked_token == et.CNAME:
                 self.parse_cname()
-            elif (peeked_token == ATTRIBUTE):
+            elif peeked_token == et.ATTRIBUTE:
                 self.parse_attribute()
             else:
-                if (peeked_token == NEW_LINE):
+                if peeked_token == et.NEW_LINE:
                     self.tokenizer.next()
                     continue
                 break
-        
+
     def parse_param(self):
-        self.expect(PARAM)
+        self.expect(et.PARAM)
         token = self.tokenizer.next()
         info = self.tokenizer.next()
-        try: 
+        try:
             self.current_instance["EBLIF.param"]
         except KeyError:
-            self.current_instance["EBLIF.param"] = dict()
+            self.current_instance["EBLIF.param"] = {}
         self.current_instance["EBLIF.param"][token] = info
-    
+
     def parse_cname(self):
-        self.expect(CNAME)
+        self.expect(et.CNAME)
         name = self.tokenizer.next()
         self.current_instance["EBLIF.cname"] = name
         self.current_instance.name = name
 
     def parse_attribute(self):
-        self.expect(ATTRIBUTE)
+        self.expect(et.ATTRIBUTE)
         key = self.tokenizer.next()
         value = self.tokenizer.next()
         try:
             self.current_instance["EBLIF.attr"]
         except KeyError:
-            self.current_instance["EBLIF.attr"] = dict()
+            self.current_instance["EBLIF.attr"] = {}
         self.current_instance["EBLIF.attr"][key] = value
 
     def parse_name(self):
         self.current_instance_info.clear()
         self.tokenizer.next()
-        # if self.look_for_true_false_undef():
-        #     return
-        port_nets = list()
-        while (self.tokenizer.token is not NEW_LINE):
+        port_nets = []
+        while self.tokenizer.token is not et.NEW_LINE:
             port_nets.append(self.tokenizer.token)
             self.tokenizer.next()
-        single_output_covers = list()
+        single_output_covers = []
         while (self.check_if_init_values(self.tokenizer.peek())): # make sure next token is init values
             single_output_cover=self.tokenizer.next()
-            single_output_cover+=" "+self.tokenizer.next()
-            self.tokenizer.next()
+            single_output_cover+=" "
+            possible_next = self.tokenizer.next()
+            if possible_next != et.NEW_LINE:
+                single_output_cover+=possible_next
+                self.tokenizer.next()
             single_output_covers.append(single_output_cover)
-    
-        # then make/get def called LUT_names_# where # is the # of ports-1
+
+        # then make/get def called logic-gate_# where # is the # of ports-1
         name = "logic-gate_"+str(len(port_nets)-1)
-        try:
-            self.definitions[name]
-        except KeyError:
-            definition = self.netlist.libraries[0].create_definition(name=name)
-            self.definitions[name] = definition
-            for i in range(len(port_nets)-1):
-                port = self.create_names_port("in_"+str(i),Port.Direction.IN)
+        definition = self.blackbox_holder.get_blackbox(name)
+        for i in range(len(port_nets)-1):
+            port_name = "in_" + str(i)
+            port = next(definition.get_ports(port_name), None)
+            if not port:
+                port = self.create_names_port("in_" + str(i), Port.Direction.IN)
                 definition.add_port(port)
-            definition.add_port(self.create_names_port("out",Port.Direction.OUT))
-        definition = self.definitions[name]
+        if not next(definition.get_ports("out"), None):
+            definition.add_port(self.create_names_port("out", Port.Direction.OUT))
 
         # then create an instance of it
-        instance = self.netlist.top_instance.reference.create_child()
-        instance.reference = definition
-        instance["EBLIF.output_covers"] = single_output_covers
-        # self.assign_instance_a_default_name(instance)
+        instance = self.current_model.create_child(reference=definition)
         self.current_instance = instance
+        instance["EBLIF.output_covers"] = single_output_covers
         instance["EBLIF.type"] = "EBLIF.names"
-     
+
         for port, net in zip(definition.get_ports(),port_nets):
             self.current_instance_info[port.name] = net
         if "unconn" in port_nets[len(port_nets)-1]:
@@ -452,7 +428,7 @@ def parse_name(self):
             instance.name = port_nets[len(port_nets)-1] # by convention, the name of the instance is the name of the driven net
 
         self.connect_instance_pins(instance)
-        self.check_for_and_add_more_instance_info()
+        self.parse_instance_info()
 
     def check_if_init_values(self,string):
         allowed = {'1','0','-'}
@@ -461,22 +437,7 @@ def check_if_init_values(self,string):
                 return False
         return True
 
-    def look_for_true_false_undef(self):
-        if self.tokenizer.token in [TRUE_WIRE,FALSE_WIRE,UNDEF_WIRE]:
-            try:
-                self.netlist["EBLIF.default_wires"]
-            except KeyError:
-                self.netlist["EBLIF.default_wires"] = list()
-            self.netlist["EBLIF.default_wires"].append(self.tokenizer.token)
-            if (self.tokenizer.token is TRUE_WIRE):
-                self.tokenizer.next()
-                self.tokenizer.next()
-            else:
-                self.tokenizer.next()
-            return True
-        return False
-
-    def create_names_port(self,name,direction):
+    def create_names_port(self, name, direction):
         port = Port(direction=direction)
         port.name = name
         port.create_pin()
@@ -486,33 +447,27 @@ def parse_latch(self):
         self.current_instance_info.clear()
         self.tokenizer.next() # first collect the information
         port_order = ["input","output","type","control","init-val"]
-        token_list = list()
-        port_info = dict()
-        while (self.tokenizer.token is not NEW_LINE):
+        token_list = []
+        port_info = {}
+        while self.tokenizer.token is not et.NEW_LINE:
             token_list.append(self.tokenizer.token)
             self.tokenizer.next()
         for order, token in zip(port_order,token_list):
             port_info[order] = token
 
         name = "generic-latch"
-        try:
-            self.definitions[name]
-        except KeyError:
-            definition = self.netlist.libraries[0].create_definition(name=name)
-            self.definitions[name] = definition
+        definition = self.blackbox_holder.get_blackbox(name)
+        if len(definition.ports) == 0:
             for order in port_info.keys() :
-                if order != "output":
-                    port = self.create_names_port(order,Port.Direction.IN)
+                if order == "output":
+                    port = self.create_names_port(order, Port.Direction.OUT)
                     definition.add_port(port)
                 else:
-                    port = self.create_names_port(order,Port.Direction.OUT)
+                    port = self.create_names_port(order, Port.Direction.IN)
                     definition.add_port(port)
-        definition = self.definitions[name]
 
         # create an instance of it
-        instance = self.netlist.top_instance.reference.create_child()
-        instance.reference = definition
-        # self.assign_instance_a_default_name(instance)
+        instance = self.current_model.create_child(reference=definition)
         instance.name = port_info["output"] # by convention, the latch name is the name of the net it drives
         self.current_instance = instance
         instance["EBLIF.type"] = "EBLIF.latch"
@@ -521,50 +476,38 @@ def parse_latch(self):
         for port, net in port_info.items():
             self.current_instance_info[port] = net
         self.connect_instance_pins(instance)
-        self.check_for_and_add_more_instance_info()
+        self.parse_instance_info()
 
     def parse_conn(self):
         cable_one_info = self.tokenizer.next()
         cable_two_info = self.tokenizer.next()
-        cable_one_name,cable_one_index = self.get_port_name_and_index(cable_one_info)
-        cable_two_name,cable_two_index = self.get_port_name_and_index(cable_two_info)
-        wire_one,wire_two = self.get_connected_wires(cable_one_name,cable_one_index,cable_two_name,cable_two_index)
-        self.merge_wires(wire_one,wire_two)
-
-    def get_connected_wires(self,cable_one_name,index_one,cable_two_name,index_two):
-        cable_one = None
-        cable_two = None
-        if (cable_one_name in self.cables.keys()):
-            cable_one = self.cables[cable_one_name]
-        else:
-            cable_one = self.netlist.top_instance.reference.create_cable(name=cable_one_name)
-            self.cables[cable_one_name] = cable_one
-        try:
-            cable_one.wires[index_one]
-        except IndexError:
-            wire = Wire()
-            cable_one.add_wire(wire,index_one)
+        cable_one_name, cable_one_index = self.get_port_name_and_index(cable_one_info)
+        cable_two_name, cable_two_index = self.get_port_name_and_index(cable_two_info)
+        wire_one, wire_two = self.get_connected_wires(cable_one_name, cable_one_index, cable_two_name, cable_two_index)
+        self.merge_wires(wire_one, wire_two)
+
+    def get_connected_wires(self, cable_one_name, index_one, cable_two_name, index_two):
+        cable_one = next(self.current_model.get_cables(cable_one_name), None)
+        if not cable_one:
+            cable_one = self.current_model.create_cable(name=cable_one_name)
+        while len(cable_one.wires) < (index_one + 1):
+            cable_one.create_wire()
         wire_one = cable_one.wires[index_one]
 
-        if (cable_two_name in self.cables.keys()):
-            cable_two = self.cables[cable_two_name]
-        else:
-            cable_two = self.netlist.top_instance.reference.create_cable(name=cable_two_name)
-            self.cables[cable_two_name] = cable_two
-        try:
-            cable_two.wires[index_two]
-        except IndexError:
-            wire = Wire()
-            cable_two.add_wire(wire,index_two)
+        cable_two = next(self.current_model.get_cables(cable_two_name), None)
+        if not cable_two:
+            cable_two = self.current_model.create_cable(name=cable_two_name)
+        while len(cable_two.wires) < (index_two + 1):
+            cable_two.create_wire()
         wire_two = cable_two.wires[index_two]
-        return wire_one,wire_two
+        return wire_one, wire_two
 
-    def merge_wires(self,wire_one,wire_two):
+    def merge_wires(self, wire_one, wire_two):
         # merge them into one new wire inside a new cable and throw both wires away
-        name_one = wire_one.cable.name+"_"+str(wire_one.index())
-        name_two = wire_two.cable.name+"_"+str(wire_two.index())
-        new_cable_name = name_one+"_"+name_two
-        new_cable = self.current_model.reference.create_cable(name=new_cable_name)
+        name_one = wire_one.cable.name + "_" + str(wire_one.index())
+        name_two = wire_two.cable.name + "_" + str(wire_two.index())
+        new_cable_name = name_one + "_" + name_two
+        new_cable = self.current_model.create_cable(name=new_cable_name)
         new_wire = new_cable.create_wire()
 
         wire_one_pins = wire_one.pins.copy()
@@ -580,13 +523,33 @@ def merge_wires(self,wire_one,wire_two):
         wire_two.cable.remove_wire(wire_two)
 
     def set_subcircuit_names_by_convention(self): # by convention, the instance names are defined by the net they drive
-        for instance in self.netlist.get_instances(): 
-            if instance["EBLIF.type"] in ["EBLIF.subckt","EBLIF.gate"]:
-                if "EBLIF.cname" not in instance.data:
-                    pin = next(instance.get_pins(selection=Selection.OUTSIDE,filter=lambda x: x.inner_pin.port.direction is sdn.OUT),None)
-                    if pin:
-                        if pin.wire:
-                            name = pin.wire.cable.name
-                            if len(pin.wire.cable.wires) > 1:
-                                name+="_"+str(pin.wire.cable.wires.index(pin.wire))
-                            instance.name = name
\ No newline at end of file
+        for instance in self.netlist.get_instances():
+            if instance["EBLIF.type"] not in ["EBLIF.subckt", "EBLIF.gate"]:
+                continue
+            if "EBLIF.cname" in instance.data:
+                continue
+            iterator = instance.get_pins(selection=Selection.OUTSIDE, filter=lambda x: x.inner_pin.port.direction is sdn.OUT)
+            while True:
+                pin = next(iterator, None)
+                if pin:
+                    if pin.wire:
+                        name = pin.wire.cable.name
+                        if len(pin.wire.cable.wires) > 1:
+                            name+="_"+str(pin.wire.cable.wires.index(pin.wire))
+                        instance.name = name
+                        break
+                else:
+                    break
+
+    def expect(self, token):
+        self.tokenizer.next()
+        self.tokenizer.expect(token)
+
+    def make_blackbox(self):
+        # self.current_model["EBLIF.blackbox"] = True
+        self.current_model.remove_cables_from(self.current_model.cables)
+
+    def add_blackbox_definitions(self):
+        for d in self.blackbox_holder.get_undefined_blackboxes():
+            # d["EBLIF.blackbox"] = True
+            self.primitives.add_definition(d)
diff --git a/spydrnet/parsers/primitive_library_reader.py b/spydrnet/parsers/primitive_library_reader.py
new file mode 100644
index 00000000..b7585414
--- /dev/null
+++ b/spydrnet/parsers/primitive_library_reader.py
@@ -0,0 +1,81 @@
+import spydrnet as sdn
+from spydrnet.ir import Library
+from spydrnet.parsers.verilog.parser import VerilogParser
+import spydrnet.parsers.verilog.verilog_tokens as vt
+
+MODULE = "module"
+END_MODULE = "endmodule"
+INPUT = "input"
+OUTPUT = "output"
+PARAMETER = "parameter"
+
+class PrimitiveLibraryReader():
+    """
+    A class to extract primitive port information from a Verilog file and insert it into the netlist. The input file is parsed using the Verilog Parser and if any module information is found for a definition in the given netlist, the port information (i.e. directions) is added.
+
+    parameters
+    ----------
+    architecture - the targeted architecture. Must be a type from spydrnet.util.architecture
+    netlist - the current netlist
+    """
+
+    def __init__(self, architecture, netlist):
+        self.input_file = architecture
+        self.netlist = netlist
+        self.definition_list = list()
+        self.netlist_defs = dict()
+        self.parsed_defs = dict()
+        self.parser = None
+    
+    def run(self):
+        self.initialize()
+        while(self.parser.tokenizer.has_next()):
+            self.progress_past_comments()
+            self.parser.parse_primitive(definition_list=self.definition_list, bypass_name_check=True)
+            definition = self.parser.current_definition
+            if definition:
+                self.parsed_defs[definition.name] = definition
+            if len(self.parsed_defs) == len(self.netlist_defs): # found all needed information
+                break
+        cnt = self.insert_info()
+        print("Found information for %d definitions" % cnt)
+    
+    def initialize(self):
+        self.parser = VerilogParser.from_filename(self.input_file)
+        self.parser.initialize_tokenizer()
+        self.parser.current_library = Library()
+        self.create_defintiion_dict()
+
+    def progress_past_comments(self):
+        token = self.parser.peek_token()
+        while(token != vt.MODULE and token != vt.PRIMITIVE):
+            # print(token)
+            self.parser.next_token()
+            token = self.parser.peek_token()
+
+    def create_defintiion_dict(self):
+        for definition in self.netlist.get_definitions():
+            self.netlist_defs[definition.name] = definition
+            self.definition_list.append(definition.name)
+
+    def insert_info(self):
+        cnt = 0
+        for def_name, definition in self.netlist_defs.items():
+            if def_name in self.parsed_defs.keys():
+                match = self.parsed_defs[def_name]
+                port_dict = self.create_port_dict(match)
+                # print(definition.name + " " + str(port_dict))
+                for port in definition.get_ports():
+                    if port.name is None: # no port name, so assume it's the only port.
+                        port.name = next(key for key in port_dict.keys())
+                        # print("Port name was None so changed to " + port.name)
+                    port.direction = port_dict[port.name]
+                cnt+=1
+        return cnt
+
+    def create_port_dict(self, definition):
+        port_dict = dict()
+        for port in definition.get_ports():
+            port_dict[port.name] = port.direction
+            # print(port.name + " has direction " + str(port.direction))
+        return port_dict
\ No newline at end of file
diff --git a/spydrnet/parsers/verilog/parser.py b/spydrnet/parsers/verilog/parser.py
index 57d9acee..ffd32c7b 100644
--- a/spydrnet/parsers/verilog/parser.py
+++ b/spydrnet/parsers/verilog/parser.py
@@ -2,7 +2,7 @@
 # please see the BYU CCl SpyDrNet license file for terms of usage.
 
 
-from spydrnet.parsers.verilog.tokenizer import VerilogTokenizer
+from spydrnet.parsers.verilog.tokenizer import VerilogTokenizer, VerilogTokenizerSimple
 import spydrnet.parsers.verilog.verilog_tokens as vt
 from spydrnet.ir import Netlist, Library, Definition, Port, Cable, Instance, OuterPin
 from spydrnet.plugins import namespace_manager
@@ -104,6 +104,8 @@ def __init__(self):
 
         self.blackbox_holder = self.BlackboxHolder()
 
+        self.implicitly_mapped_ports = dict()
+
     def parse(self):
         ''' parse a verilog netlist represented by verilog file
 
@@ -115,7 +117,7 @@ def parse(self):
         self.parse_verilog()
         namespace_manager.default = ns_default
         self.tokenizer.__del__()
-        return self.netlist
+        return self.netlist   
 
     def initialize_tokenizer(self):
         self.tokenizer = VerilogTokenizer(self.filename)
@@ -173,7 +175,7 @@ def parse_verilog(self):
         self.netlist = sdn.Netlist()
         self.netlist.name = "SDN_VERILOG_NETLIST"
         self.work = self.netlist.create_library("work")
-        self.primitives = self.netlist.create_library("SDN.verilog_primitives")
+        self.primitives = self.netlist.create_library("hdi_primitives")
         self.current_library = self.work
 
         preprocessor_defines = set()
@@ -239,6 +241,8 @@ def parse_verilog(self):
                     "something at the top level of the file", "got unexpected token", token)
 
         self.add_blackbox_definitions()
+        
+        self.connect_implicitly_mapped_ports()
 
         return self.netlist
 
@@ -248,16 +252,28 @@ def add_blackbox_definitions(self):
             d["VERILOG.primitive"] = True
             self.current_library.add_definition(d)
 
-    def parse_primitive(self):
-        '''similar to parse module but it will only look for the inputs and outputs to get an idea of how those things look'''
+    def parse_primitive(self, definition_list = [], bypass_name_check=False):
+        '''
+        similar to parse module but it will only look for the inputs and outputs to get an idea of how those things look
 
+        definition_list is an optional parameter that is used by primitive_library_reader as primitive libraries are parsed. If the primitive name is not
+        in the definition list, it is not needed and will be skipped.
+        '''
         token = self.next_token()
         assert token == vt.MODULE or token == vt.PRIMITIVE, self.error_string(
             vt.MODULE, "to begin module statement", token)
         token = self.next_token()
-        assert vt.is_valid_identifier(token), self.error_string(
-            "identifier", "not a valid module name", token)
+        if not bypass_name_check:
+            assert vt.is_valid_identifier(token), self.error_string(
+                "identifier", "not a valid module name", token)
         name = token
+        
+        if definition_list:
+            if name not in definition_list: # we don't need this primitive info
+                while(token != vt.END_MODULE):
+                    token = self.next_token()
+                # self.next_token()
+                return
 
         definition = self.blackbox_holder.get_blackbox(name)
         self.blackbox_holder.define(name)
@@ -417,7 +433,7 @@ def parse_module_header_port_alias(self):
 
         example syntax
         .canale({\\canale[3] ,\\canale[2] ,\\canale[1] ,\\canale[0] }),'''
-
+        
         token = self.next_token()
         assert token == vt.DOT, self.error_string(
             vt.DOT, "for port aliasing", token)
@@ -445,12 +461,13 @@ def parse_module_header_port_alias(self):
             name, left_index=len(wires)-1, right_index=0)
 
         # connect the wires to the pins
-
         assert len(port.pins) == len(
             wires), "Internal Error: the pins in a created port and the number of wires the aliased cable do not match up"
 
-        for i in range(len(port.pins)):
-            wires[i].connect_pin(port.pins[i])
+        pin_list = list(p for p in port.pins)
+        pin_list.sort(reverse=True, key=self.pin_sort_func)
+        for i in range(len(pin_list)):
+            wires[i].connect_pin(pin_list[i])
 
     def parse_cable_concatenation(self):
         '''parse a concatenation structure of cables, create the cables mentioned, and deal with indicies
@@ -465,6 +482,7 @@ def parse_cable_concatenation(self):
         while token != vt.CLOSE_BRACE:
             cable, left, right = self.parse_variable_instantiation()
             wires_temp = self.get_wires_from_cable(cable, left, right)
+            wires_temp.sort(reverse=True,key=self.wire_sort_func)
             for w in wires_temp:
                 wires.append(w)
             token = self.next_token()
@@ -474,6 +492,9 @@ def parse_cable_concatenation(self):
 
         return wires
 
+    def wire_sort_func(self, w):
+        return w.cable.wires.index(w)
+
     def parse_module_header_port(self):
         '''parse the port declaration in the module header'''
         token = self.peek_token()
@@ -512,8 +533,11 @@ def parse_module_header_port(self):
         # wire together the cables and the port
         assert len(port.pins) == len(cable.wires), self.error_string(
             "the pins in a created port and the number of wires in it's cable do not match up", "wires: " + str(len(cable.wires)), "pins: " + str(len(port.pins)))
-        for i in range(len(port.pins)):
-            cable.wires[i].connect_pin(port.pins[i])
+        
+        pin_list = list(p for p in port.pins)
+        pin_list.sort(reverse=False, key=self.pin_sort_func) 
+        for i in range(len(pin_list)):
+            cable.wires[i].connect_pin(pin_list[i])
 
     def parse_module_body(self):
         '''
@@ -613,15 +637,16 @@ def parse_port_declaration(self, properties):
             else:
                 port = self.create_or_update_port(port_list.pop(
                 ).name, left_index=left, right_index=right, direction=direction, defining=True)
-
+            
             if len(cable.wires) > 1:
                 self.connect_resized_port_cable(cable, port)
 
-    def parse_cable_declaration(self, properties):
-        token = self.next_token()
-        assert token in [vt.REG, vt.WIRE, vt.TRI0, vt.TRI1], self.error_string(
-            "reg, tri1, tri0, or wire", "for cable declaration", token)
-        var_type = token
+    def parse_cable_declaration(self, properties, var_type = None):
+        if not var_type:
+            token = self.next_token()
+            assert token in [vt.REG, vt.WIRE, vt.TRI0, vt.TRI1], self.error_string(
+                "reg, tri1, tri0, or wire", "for cable declaration", token)
+            var_type = token
 
         token = self.peek_token()
         if token == vt.OPEN_BRACKET:
@@ -640,8 +665,11 @@ def parse_cable_declaration(self, properties):
         cable["VERILOG.InlineConstraints"] = properties
 
         token = self.next_token()
-        assert token == vt.SEMI_COLON, self.error_string(
-            vt.SEMI_COLON, "to end cable declaration", token)
+        if token == vt.COMMA: # continue listing wires
+            self.parse_cable_declaration(dict(), var_type)
+        else:
+            assert token == vt.SEMI_COLON, self.error_string(
+                vt.SEMI_COLON, "to end cable declaration", token)
 
     def parse_instantiation(self, properties):
         token = self.next_token()
@@ -659,6 +687,37 @@ def parse_instantiation(self, properties):
             "instance name", "for instantiation", token)
         name = token
 
+        # the current definition is instancing the current top instance, so a change needs to be made
+        if def_name == self.netlist.top_instance.reference.name:
+            # print(self.current_definition.name + " is instancing the current top instance (" + name+ " which is a "+ self.netlist.top_instance.reference.name+")")
+            old_top_instance = self.netlist.top_instance
+
+            new_level = self.current_definition
+            # we know the current top is not right. So now we can move it up a level.
+            # But double check to make sure nothing is instancing the potential new top.
+            # Move up levels until we reach a new top
+            if (len(self.current_definition.references) > 0):
+                current_level = list(x for x in self.current_definition.references)[0]
+                while(True):
+                    current_level = current_level.parent
+                    try:
+                        current_level.parent
+                    except AttributeError:
+                        new_level = current_level
+                        break
+
+            self.netlist.top_instance = sdn.Instance()
+            self.netlist.top_instance.name = new_level.name + "_top"
+            self.netlist.top_instance.reference = new_level
+            self.netlist.name = "SDN_VERILOG_NETLIST_" + new_level.name
+
+            # print("New top instance is "+ self.netlist.top_instance.name)
+
+            # this instance should just go away. It was created to be the top instance but we don't want that 
+            # it has no parent. And now with no reference, it should have no ties to the netlist.
+            old_top_instance.reference = None
+
+
         token = self.peek_token()
         assert token == vt.OPEN_PARENTHESIS, self.error_string(
             vt.OPEN_PARENTHESIS, "to start port to cable mapping", token)
@@ -707,6 +766,7 @@ def parse_defparam_parameters(self):
         assert token == vt.EQUAL, self.error_string(vt.EQUAL, "separate the key from the value in a defparam statement", token)
         token = self.next_token()
         value = token
+        params[key] = value
         token = self.next_token()
         assert token == vt.SEMI_COLON, self.error_string(vt.SEMI_COLON, "to end the defparam statement", token)
         self.set_instance_parameters(instance, params)
@@ -722,12 +782,15 @@ def parse_parameter_mapping(self):
         assert token == vt.OPEN_PARENTHESIS, self.error_string(
             vt.OPEN_PARENTHESIS, "after # to begin parameter mapping", token)
 
-        while token != vt.CLOSE_PARENTHESIS:
-            k, v = self.parse_parameter_map_single()
-            params[k] = v
+        if self.peek_token() == vt.CLOSE_PARENTHESIS: # empty parameters
             token = self.next_token()
-            assert token in [vt.CLOSE_PARENTHESIS, vt.COMMA], self.error_string(
-                vt.COMMA + " or " + vt.CLOSE_PARENTHESIS, "to separate parameters or end parameter mapping", token)
+        else:
+            while token != vt.CLOSE_PARENTHESIS:
+                k, v = self.parse_parameter_map_single()
+                params[k] = v
+                token = self.next_token()
+                assert token in [vt.CLOSE_PARENTHESIS, vt.COMMA], self.error_string(
+                    vt.COMMA + " or " + vt.CLOSE_PARENTHESIS, "to separate parameters or end parameter mapping", token)
 
         assert token == vt.CLOSE_PARENTHESIS, self.error_string(
             vt.CLOSE_PARENTHESIS, "to terminate ", token)
@@ -763,11 +826,20 @@ def parse_port_mapping(self):
         assert token == vt.OPEN_PARENTHESIS, self.error_string(
             vt.OPEN_PARENTHESIS, "to start the port mapping", token)
 
-        while token != vt.CLOSE_PARENTHESIS:
-            self.parse_port_map_single()
-            token = self.next_token()
-            assert token in [vt.COMMA, vt.CLOSE_PARENTHESIS], self.error_string(
-                vt.COMMA + " or " + vt.CLOSE_PARENTHESIS, "between port mapping elements or to end the port mapping", token)
+        peeked_token = self.peek_token()
+        if peeked_token != vt.DOT: # the ports are implicitly mapped
+            token_list = list()
+            while (token != vt.CLOSE_PARENTHESIS):
+                token_list.append(token)
+                token = self.next_token()
+            token_list.append(token)
+            self.implicitly_mapped_ports[self.current_instance] = token_list
+        else: # the ports are explicitly mapped
+            while token != vt.CLOSE_PARENTHESIS:
+                self.parse_port_map_single()
+                token = self.next_token()
+        assert token in [vt.COMMA, vt.CLOSE_PARENTHESIS], self.error_string(
+            vt.COMMA + " or " + vt.CLOSE_PARENTHESIS, "between port mapping elements or to end the port mapping", token)
 
     def parse_port_map_single(self):
         '''acutally does the mapping of the pins'''
@@ -801,8 +873,9 @@ def parse_port_map_single(self):
                 "pins length to match or exceed cable.wires length", "INTERNAL ERROR", str(len(pins)) + "!=" + str(len(wires)))
 
             # there can be unconnected pins at the end of the port.
+            pins.sort(reverse=True, key=self.pin_sort_func)
             for i in range(len(wires)):
-                wires[i].connect_pin(pins[i])
+               wires[i].connect_pin(pins[i])
 
             token = self.next_token()
 
@@ -814,6 +887,59 @@ def parse_port_map_single(self):
 
         assert token == vt.CLOSE_PARENTHESIS, self.error_string(
             vt.CLOSE_PARENTHESIS, "to end cable name in port mapping", token)
+    
+    def pin_sort_func(self, p):
+        if isinstance(p, sdn.OuterPin):
+            return p.inner_pin.port.pins.index(p.inner_pin)
+        return p.port.pins.index(p)
+
+    def connect_implicitly_mapped_ports(self):
+        for instance, token_list in self.implicitly_mapped_ports.items():
+            self.current_instance = instance
+            self.current_definition = instance.parent
+            port_list = list(x for x in instance.reference.get_ports())
+            self.tokenizer = VerilogTokenizerSimple(token_list)
+
+            token = self.next_token()
+            assert token == vt.OPEN_PARENTHESIS, self.error_string(
+                vt.OPEN_PARENTHESIS, "to encapsulate cable name in port mapping", token)
+            
+            index = 0
+            while (token != vt.CLOSE_PARENTHESIS):
+                token = self.peek_token()
+
+                if token == vt.OPEN_BRACE:
+                    wires = self.parse_cable_concatenation()
+                else:
+                    cable, left, right = self.parse_variable_instantiation()
+                    wires = self.get_wires_from_cable(cable, left, right)
+
+                if (index > len(port_list) - 1): # no port exists yet i.e. no module information in netlist
+                    # print("Not enough ports for "+ instance.name)
+                    port = instance.reference.create_port()
+                    self.populate_new_port(port, None, len(wires)-1, 0, None)
+                else:
+                    port = port_list[index]
+
+                pins = list()
+                for pin in self.current_instance.pins:
+                    if pin.inner_pin in port.pins:
+                        pins.append(pin)
+
+                assert len(pins) >= len(wires), self.error_string(
+                    "pins length to match or exceed cable.wires length", "INTERNAL ERROR", str(len(pins)) + "!=" + str(len(wires)))
+
+                # there can be unconnected pins at the end of the port.
+                pin_list = list(p for p in pins)
+                pin_list.sort(reverse=True, key=self.pin_sort_func)
+                for i in range(len(wires)):
+                    wires[i].connect_pin(pin_list[i])
+
+                token = self.next_token()
+                index += 1
+
+            assert token == vt.CLOSE_PARENTHESIS, self.error_string(
+                vt.CLOSE_PARENTHESIS, "to end cable name in port mapping", token)
 
     def parse_assign(self):
         token = self.next_token()
@@ -844,7 +970,7 @@ def parse_variable_instantiation(self):
             assert token[1] == vt.SINGLE_QUOTE, self.error_string(vt.SINGLE_QUOTE, "in the constant", token)
             assert token[2] == 'b', self.error_string('b', "in the constant", token)
             assert token[3] in ["0", "1", "x", "X", "z", "Z"], self.error_string("one of 0, 1, x, X, z, Z", "represent the constant value after '", token)
-            name = "\\<const" + token[2] + "> "
+            name = "\\<const" + token[3] + "> "
         elif vt.is_numeric(token[0]):
             assert False, self.error_string("single bit constant", "multibit constants not supported", token)
         else:
@@ -947,11 +1073,12 @@ def get_assignment_definition(self, width):
             in_port.direction = sdn.Port.Direction.IN
             out_port.direction = sdn.Port.Direction.OUT
 
-            cable = definition.create_cable("through")
-            cable.create_wires(width)
-            for i in range(width):
-                cable.wires[i].connect_pin(in_port.pins[i])
-                cable.wires[i].connect_pin(out_port.pins[i])
+            # no need for this. It actually messes with other spydrnet functions like uniquify() and is_leaf()
+            # cable = definition.create_cable("through")
+            # cable.create_wires(width)
+            # for i in range(width):
+            #     cable.wires[i].connect_pin(in_port.pins[i])
+            #     cable.wires[i].connect_pin(out_port.pins[i])
 
         return definition
 
@@ -1027,9 +1154,8 @@ def get_wires_from_cable(self, cable, left, right):
             left = left - cable.lower_index
             right = right - cable.lower_index
             temp_wires = cable.wires[min(left, right): max(left, right) + 1]
-            if left > right:
-                temp_wires = reversed(temp_wires)
-
+            # if right > left:
+            temp_wires.reverse()
             for w in temp_wires:
                 wires.append(w)
 
@@ -1041,7 +1167,9 @@ def get_wires_from_cable(self, cable, left, right):
             wires.append(cable.wires[index])
 
         else:
-            for w in cable.wires:
+            temp_wires = list(w for w in cable.wires)
+            temp_wires.reverse()
+            for w in temp_wires:
                 wires.append(w)
 
         return wires
@@ -1091,6 +1219,10 @@ def connect_resized_port_cable(self, resized_cable, resized_port):
         for i in range(len(resized_port.pins)):
             # I think these should be lined up right?
             if resized_port.pins[i] not in resized_cable.wires[i].pins:
+                if resized_port.pins[i].wire:
+                    continue
+                    # the resized_port's pin is already connected
+                    # this likely occurred because of an alias statement.
                 resized_cable.wires[i].connect_pin(resized_port.pins[i])
 
     def create_or_update_cable(self, name, left_index=None, right_index=None, var_type=None, defining=False):
@@ -1220,13 +1352,17 @@ def create_or_update_port(self, name, left_index=None, right_index=None, directi
             port_upper = port.lower_index + len(port.pins) - 1
 
         if in_upper is not None and in_lower is not None:
-
-            if in_lower < port_lower:
-                prepend = port_lower - in_lower
-                self.prepend_pins(port, prepend)
-            if in_upper > port_upper:
-                postpend = in_upper - port_upper
-                self.postpend_pins(port, postpend)
+            # to prevent unneccessary pins being added, check to see if port
+            # width is already correct
+            if (in_upper-in_lower) == (port_upper-port_lower):
+                None
+            else:
+                if in_lower < port_lower:
+                    prepend = port_lower - in_lower
+                    self.prepend_pins(port, prepend)
+                if in_upper > port_upper:
+                    postpend = in_upper - port_upper
+                    self.postpend_pins(port, postpend)
 
         if direction is not None:
             port.direction = direction
diff --git a/spydrnet/parsers/verilog/tokenizer.py b/spydrnet/parsers/verilog/tokenizer.py
index e75bbcd4..a6d6ef31 100644
--- a/spydrnet/parsers/verilog/tokenizer.py
+++ b/spydrnet/parsers/verilog/tokenizer.py
@@ -105,3 +105,46 @@ def generate_tokens(self):
     def close(self):
         if self.input_stream:
             self.input_stream.close()
+
+
+class VerilogTokenizerSimple():
+    def __init__(self, token_list):
+        self.token = None
+        self.next_token = None
+        self.line_number = 0
+        self.token_list = token_list
+        self.generator = self.generate_tokens()
+
+    def __del__(self):
+        if hasattr(self, "input_stream"):
+            self.close()
+
+    def generate_tokens(self):
+        for token in self.token_list:
+            yield token
+
+    def has_next(self):
+        try:
+            self.peek()
+            return True
+        except StopIteration:
+            return False
+
+    def next(self):
+        if self.next_token is not None:
+            self.token = self.next_token
+            self.next_token = None
+        else:
+            self.token = next(self.generator)
+        return self.token
+
+    def peek(self):
+        if self.next_token is not None:
+            return self.next_token
+        else:
+            token = next(self.generator)
+            while len(token) >= 2 and (token[0:2] == vt.OPEN_LINE_COMMENT
+                                       or token[0:2] == vt.OPEN_BLOCK_COMMENT):
+                token = next(self.generator)
+            self.next_token = token
+            return self.next_token
diff --git a/spydrnet/support_files/architecture_libraries/f4pga_xilinx_7series.v.zip b/spydrnet/support_files/architecture_libraries/f4pga_xilinx_7series.v.zip
new file mode 100644
index 00000000..26d8f648
Binary files /dev/null and b/spydrnet/support_files/architecture_libraries/f4pga_xilinx_7series.v.zip differ
diff --git a/spydrnet/support_files/architecture_libraries/lifcl.v.zip b/spydrnet/support_files/architecture_libraries/lifcl.v.zip
new file mode 100644
index 00000000..57a8ab7e
Binary files /dev/null and b/spydrnet/support_files/architecture_libraries/lifcl.v.zip differ
diff --git a/spydrnet/support_files/architecture_libraries/xilinx_7series.v.zip b/spydrnet/support_files/architecture_libraries/xilinx_7series.v.zip
new file mode 100644
index 00000000..25d5bf7f
Binary files /dev/null and b/spydrnet/support_files/architecture_libraries/xilinx_7series.v.zip differ
diff --git a/spydrnet/support_files/architecture_libraries/yosys_internal_cells.v.zip b/spydrnet/support_files/architecture_libraries/yosys_internal_cells.v.zip
new file mode 100644
index 00000000..046f467c
Binary files /dev/null and b/spydrnet/support_files/architecture_libraries/yosys_internal_cells.v.zip differ
diff --git a/spydrnet/util/architecture.py b/spydrnet/util/architecture.py
new file mode 100644
index 00000000..db602ff7
--- /dev/null
+++ b/spydrnet/util/architecture.py
@@ -0,0 +1,10 @@
+import os
+import spydrnet as sdn
+
+base_dir = os.path.dirname(os.path.abspath(sdn.__file__))
+base_file_path = os.path.join(base_dir, 'support_files', 'architecture_libraries')
+
+XILINX_7SERIES = os.path.join(base_file_path, "xilinx_7series.v.zip")
+F4PGA_XILINX_7SERIES = os.path.join(base_file_path, "f4pga_xilinx_7series.v.zip")
+LATTICE_LIFCL = os.path.join(base_file_path, "lifcl.v.zip")
+YOSYS_CELLS = os.path.join(base_file_path, "yosys_internal_cells.v.zip")
\ No newline at end of file
diff --git a/spydrnet/util/reinsert_space.py b/spydrnet/util/reinsert_space.py
new file mode 100644
index 00000000..c78ee0a9
--- /dev/null
+++ b/spydrnet/util/reinsert_space.py
@@ -0,0 +1,23 @@
+def reinserting_space(netlist,voters):
+    
+    for voter in voters:
+        for obj in voters[voter]:
+            obj.name = ''.join((obj.name, "_wire"))  
+
+    for instance in netlist.get_instances():
+        if instance.name is None:
+            continue
+        if "\\" in instance.name:
+            instance.name = ''.join((instance.name, " "))
+            
+    for port in netlist.get_ports():
+        if port.name is None:
+            continue
+        if "\\" in port.name:
+            port.name = ''.join((port.name, " "))    
+        
+    for cable in netlist.get_cables():
+        if cable.name is None:
+            continue
+        if "\\" in cable.name:
+            cable.name = ''.join((cable.name, " "))  
\ No newline at end of file
diff --git a/spydrnet/util/remove_space.py b/spydrnet/util/remove_space.py
new file mode 100644
index 00000000..7d6fea69
--- /dev/null
+++ b/spydrnet/util/remove_space.py
@@ -0,0 +1,24 @@
+def removing_space(netlist):    
+    
+    for instance in netlist.get_instances():
+        if instance.name is None:
+            continue
+        if "\\" in instance.name:
+            update_name = instance.name.replace(" ", "")
+            instance.name = update_name    
+    
+    for port in netlist.get_ports():
+        if port.name is None:
+            continue
+        if "\\" in port.name:
+            update_name = port.name.replace(" ", "")
+            port.name = update_name
+
+    for cable in netlist.get_cables():
+        if cable.name is None:
+            continue
+        if "\\" in cable.name:
+            update_name = cable.name.replace(" ", "")
+            cable.name = update_name
+
+            
\ No newline at end of file


Test patch:
diff --git a/spydrnet/composers/eblif/tests/test_eblif_composer.py b/spydrnet/composers/eblif/tests/test_eblif_composer.py
index b71bbf63..4199bd16 100644
--- a/spydrnet/composers/eblif/tests/test_eblif_composer.py
+++ b/spydrnet/composers/eblif/tests/test_eblif_composer.py
@@ -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
         
\ No newline at end of file
diff --git a/spydrnet/composers/verilog/tests/test_composer_unit.py b/spydrnet/composers/verilog/tests/test_composer_unit.py
index db9727be..75a88fa0 100644
--- a/spydrnet/composers/verilog/tests/test_composer_unit.py
+++ b/spydrnet/composers/verilog/tests/test_composer_unit.py
@@ -138,13 +138,15 @@ def initialize_instance_port_connections(self, instance, definition):
 
         single_bit_expected = "." + single_bit_port.name + "(" + single_bit_cable.name + ")"
 
-        multi_bit_expected = "." + multi_bit_port.name + "(" + multi_bit_cable.name + ")"
+        multi_bit_expected = "." + multi_bit_port.name + "(" + multi_bit_cable.name + "[" + str(len(multi_bit_cable.wires) - 1 + multi_bit_cable.lower_index) + ":" + \
+                                    str(multi_bit_cable.lower_index) + "]"")"
 
-        offset_expected = "." + multi_bit_port_offset.name + "(" + multi_bit_cable.name + ")"
+        offset_expected = "." + multi_bit_port_offset.name + "(" + multi_bit_cable.name + "[" + str(len(multi_bit_cable.wires) - 1 + multi_bit_cable.lower_index) + ":" + \
+                                    str(multi_bit_cable.lower_index) + "]"")"
 
         partial_expected = "." + partial_port.name + "(" + multi_bit_cable.name + "[1:0])"
 
-        concatenated_expected = "." + concatenated_port.name + "({" + ccs[0].name + ', ' + ccs[1].name + ', ' + ccs[2].name + ', ' + ccs[3].name + "})"
+        concatenated_expected = "." + concatenated_port.name + "({" + ccs[3].name + ', ' + ccs[2].name + ', ' + ccs[1].name + ', ' + ccs[0].name + "})"
 
         return single_bit_port, single_bit_expected, \
             multi_bit_port, multi_bit_expected, \
@@ -278,7 +280,7 @@ def test_write_brackets_multi_bit(self):
         assert composer.file.compare("[2]")
         composer.file.clear()
         composer._write_brackets(port, 0, 3)
-        assert composer.file.compare("")
+        assert composer.file.compare("[3:0]")
         composer.file.clear()
         composer._write_brackets(port, 1, 2)
         assert composer.file.compare("[2:1]")
@@ -297,7 +299,7 @@ def test_write_brackets_multi_bit(self):
         assert composer.file.compare("[2]")
         composer.file.clear()
         composer._write_brackets(cable, 0, 3)
-        assert composer.file.compare("")
+        assert composer.file.compare("[3:0]")
         composer.file.clear()
         composer._write_brackets(cable, 1, 2)
         assert composer.file.compare("[2:1]")
@@ -336,7 +338,7 @@ def test_write_brackets_multi_bit_offset(self):
         assert composer.file.compare("[6]")
         composer.file.clear()
         composer._write_brackets(port, 4, 7)
-        assert composer.file.compare("")
+        assert composer.file.compare("[7:4]")
         composer.file.clear()
         composer._write_brackets(port, 5, 6)
         assert composer.file.compare("[6:5]")
@@ -355,7 +357,7 @@ def test_write_brackets_multi_bit_offset(self):
         assert composer.file.compare("[6]")
         composer.file.clear()
         composer._write_brackets(cable, 4, 7)
-        assert composer.file.compare("")
+        assert composer.file.compare("[7:4]")
         composer.file.clear()
         composer._write_brackets(cable, 5, 6)
         assert composer.file.compare("[6:5]")
@@ -568,7 +570,7 @@ def test_write_module_ports_header_and_body_alias(self):
         c2.wires[0].connect_pin(port_alias.pins[1])
 
         composer._write_module_header_port(port_alias)
-        assert composer.file.compare("." + port_alias.name + "({"+ c1.name + ", " + c2.name +"})")
+        assert composer.file.compare("." + port_alias.name + "({"+ c2.name + ", " + c1.name +"})")
         composer.file.clear()
         composer._write_module_body_port(port_alias)
         assert composer.file.compare("input " + c1.name + ";\n    " + "input " + c2.name + ";\n")
diff --git a/spydrnet/parsers/eblif/tests/test_eblif_parser.py b/spydrnet/parsers/eblif/tests/test_eblif_parser.py
index d016e3af..ec8bcaf5 100644
--- a/spydrnet/parsers/eblif/tests/test_eblif_parser.py
+++ b/spydrnet/parsers/eblif/tests/test_eblif_parser.py
@@ -50,7 +50,7 @@ def test_cables(self):
         for cable in self.netlist.get_cables():
             self.assertTrue(self.netlist_is_own_netlist(cable))
             count+=1
-        self.assertEqual(count,10)
+        self.assertEqual(count, 11)
 
     def netlist_is_own_netlist(self,object):
         netlist_list = list(x for x in object.get_netlists())
diff --git a/spydrnet/parsers/tests/test_parsers.py b/spydrnet/parsers/tests/test_parsers.py
index fad682ba..fcdf6906 100644
--- a/spydrnet/parsers/tests/test_parsers.py
+++ b/spydrnet/parsers/tests/test_parsers.py
@@ -1,7 +1,49 @@
 import unittest
+import os
 import spydrnet as sdn
+from spydrnet.util.netlist_type import VERILOG, EBLIF
+from spydrnet.util.architecture import XILINX_7SERIES
 
 
 class TestParsers(unittest.TestCase):
     def test_parse(self):
         self.assertRaises(RuntimeError, sdn.parse, "fakefile.fakeext")
+
+
+
+class TestParseWithArchitecture(unittest.TestCase):
+    def test_verilog(self):
+        netlist = sdn.load_example_netlist_by_name("b13", VERILOG)
+        netlist.compose("b13.v", write_blackbox = False)
+
+        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():
+                    self.assertEqual(port.direction, sdn.UNDEFINED)
+
+        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():
+                    self.assertNotEqual(port.direction, sdn.UNDEFINED, definition.name)
+
+        os.remove("b13.v")
+    
+    def test_eblif(self):
+        netlist = sdn.load_example_netlist_by_name("toggle", EBLIF)
+        netlist.compose("toggle.eblif", write_blackbox = False)
+
+        netlist_1 = sdn.parse("toggle.eblif")
+        for definition in netlist_1.get_definitions():
+            if definition is not netlist_1.top_instance.reference and "logic-gate" not in definition.name:
+                for port in definition.get_ports():
+                    self.assertEqual(port.direction, sdn.UNDEFINED, definition.name)
+
+        netlist_2 = sdn.parse("toggle.eblif", XILINX_7SERIES)
+        for definition in netlist_2.get_definitions():
+            if definition is not netlist_2.top_instance.reference:
+                for port in definition.get_ports():
+                    self.assertNotEqual(port.direction, sdn.UNDEFINED, definition.name)
+
+        os.remove("toggle.eblif")
diff --git a/spydrnet/parsers/verilog/tests/test_verilogParser.py b/spydrnet/parsers/verilog/tests/test_verilogParser.py
index 4fe1e4a5..9f7c30fe 100644
--- a/spydrnet/parsers/verilog/tests/test_verilogParser.py
+++ b/spydrnet/parsers/verilog/tests/test_verilogParser.py
@@ -6,6 +6,7 @@
 from spydrnet.parsers.verilog.parser import VerilogParser
 import spydrnet.parsers.verilog.verilog_tokens as vt
 from spydrnet import parsers
+from spydrnet.util.selection import Selection
 import os
 
 class TestVerilogParser(unittest.TestCase):
@@ -815,6 +816,33 @@ def test_parse_port_map_single(self):
         for p in parser.current_instance.pins:
             assert p in w_pins
 
+    def test_parse_implicitly_mapped_ports(self):
+        # create dummy netlist
+        to_write = "module top (input clk, output out);\n"
+        to_write += "\twire clk_c, VCC_net, out;\n"
+        to_write += "\tINST my_inst (clk_c, VCC_net, out);\n"
+        to_write += "endmodule\n\n"
+        to_write += "module INST (input port_0, input port_1, output port_2);\n"
+        to_write += "endmodule"
+        f = open("test_netlist.v", "x")
+        f.write(to_write)
+        f.close()
+
+        parser = VerilogParser.from_filename("test_netlist.v")
+        parser.parse()
+        netlist = parser.netlist
+
+        instance = next(netlist.get_instances("my_inst"))
+        self.assertEqual(instance.name, "my_inst")
+        connections = ["clk_c", "VCC_net", "out"]
+        for i in range(0,2):
+            port = next(instance.get_ports("port_"+str(i)))
+            self.assertEqual(len(port.pins), 1)
+            for pin in port.get_pins(selection=Selection.OUTSIDE):
+                self.assertEqual(pin.wire.cable.name, connections[i])
+
+        os.remove("test_netlist.v")
+
     ############################################################################
     ##Port creation and modification
     ############################################################################
@@ -1135,10 +1163,8 @@ def test_create_new_assignment_definition(self):
         assert len(definition.ports) == 2
         assert len(definition.ports[0].pins) == width
         assert len(definition.ports[1].pins) == width
-        assert len(definition.cables) == 1
-        for i in range(width):
-            assert definition.ports[0].pins[i] in definition.cables[0].wires[i].pins
-            assert definition.ports[1].pins[i] in definition.cables[0].wires[i].pins
+        assert len(definition.cables) == 0
+
 
 
     def test_connect_assigned_wires(self):
@@ -1251,6 +1277,33 @@ def test_parser_star_list(self):
         assert "DONT_TOUCH" in stars2
         assert stars2["DONT_TOUCH"] == None
         
+    ############################################
+    ##test hierarchy
+    ############################################
+
+    def test_hierarchy_fixing(self):
+        # create dummy netlist with the top instance coming after the lower instance
+        to_write = "module INST (input port_0, input port_1, output port_2);\n"
+        to_write += "endmodule\n\n"
+        to_write += "module top (input clk, output out);\n"
+        to_write += "\twire clk_c, VCC_net, out;\n"
+        to_write += "\tINST my_inst (clk_c, VCC_net, out);\n"
+        to_write += "endmodule\n"
+        f = open("test_netlist.v", "x")
+        f.write(to_write)
+        f.close()
+
+        parser = VerilogParser.from_filename("test_netlist.v")
+        parser.parse()
+        netlist = parser.netlist
+
+        self.assertEqual(netlist.top_instance.name, "top_top")
+        instance = next(netlist.get_instances("my_inst"))
+        self.assertTrue(instance.parent is netlist.top_instance.reference)
+        self.assertTrue(instance in netlist.top_instance.reference.children)
+        self.assertEqual(len(instance.reference.references), 1)
+
+        os.remove("test_netlist.v")
 
 
     ############################################
@@ -1308,6 +1361,9 @@ def test_get_wires_from_cable_helper(self):
         expected1 = [e11, [cable1.wires[0]], [cable1.wires[0]], [cable1.wires[1]], cable1.wires[2:5]]
         expected2 = [e21, [cable2.wires[0]], [cable2.wires[0]], [cable2.wires[1]], cable2.wires[2:5]]
 
+        expected1[4].reverse()
+        expected2[4].reverse()
+
         for i in range(len(tests)):
             left1 = tests[i][0] + cable1.lower_index
             if tests[i][1] != None:
@@ -1330,6 +1386,31 @@ def test_get_wires_from_cable_helper(self):
                 w22 = expected2[i][j]
                 assert w21 == w22, "the wires are not the same or not in the same order"
 
+    def test_constant_parsing(self):
+        """
+        Tests multiple wire decalaration on the same line in verilog
+        """
+        parser = VerilogParser()
+
+        # Check constant 0 net declaration
+        tokens = ("1'b0", vt.SEMI_COLON)
+        tokenizer = self.TestTokenizer(tokens)
+        parser = VerilogParser()
+        parser.tokenizer = tokenizer
+
+        parser.current_definition = sdn.Definition()
+        cable, _, _ = parser.parse_variable_instantiation()
+        self.assertEqual(cable.name, "\\<const0> ", "Check const wire name")
+
+        # Check constant 1 net declaration
+        tokens = ("1'b1", vt.SEMI_COLON)
+        tokenizer = self.TestTokenizer(tokens)
+        parser = VerilogParser()
+        parser.tokenizer = tokenizer
+
+        parser.current_definition = sdn.Definition()
+        cable, _, _ = parser.parse_variable_instantiation()
+        self.assertEqual(cable.name, "\\<const1> ", "Check const wire name")
 
 
 if __name__ == '__main__':
diff --git a/spydrnet/util/tests/test_get_hwires.py b/spydrnet/util/tests/test_get_hwires.py
index 14c2ba7f..51d24ec8 100644
--- a/spydrnet/util/tests/test_get_hwires.py
+++ b/spydrnet/util/tests/test_get_hwires.py
@@ -217,7 +217,7 @@ def test_through_hierarchy_again(self):
 
         # look at wire_name
         href = next(sdn.get_hwires(middle_floating_wire))
-        assert ('middle/middle_cable[1]', href.name)
+        assert ('middle/middle_cable[1]' == href.name)
         hrefs = set(sdn.get_hwires(netlist.top_instance, recursive=True))
         assert (href in hrefs)