From e292767166b7f44a41b4dfe0d93d58dc91d59acc Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 24 Apr 2019 14:23:22 -0700 Subject: [PATCH] Added graph creation and functions in base class and lower level modules. --- compiler/base/hierarchy_design.py | 13 ++++++++++--- compiler/bitcells/bitcell.py | 11 ++++++++++- compiler/bitcells/bitcell_1rw_1r.py | 12 ++++++++++++ compiler/bitcells/bitcell_1w_1r.py | 11 +++++++++++ compiler/bitcells/pbitcell.py | 12 ++++++++++++ compiler/bitcells/replica_bitcell.py | 9 +++++++++ compiler/bitcells/replica_bitcell_1rw_1r.py | 11 +++++++++++ compiler/bitcells/replica_bitcell_1w_1r.py | 11 +++++++++++ compiler/{base => characterizer}/graph_util.py | 5 ++++- compiler/modules/bank.py | 6 ++++++ compiler/modules/bitcell_array.py | 10 ++++++++++ compiler/modules/dff.py | 8 ++++++++ compiler/modules/hierarchical_decoder.py | 1 + compiler/modules/precharge_array.py | 1 + compiler/modules/sense_amp.py | 13 ++++++++++++- compiler/modules/tri_gate.py | 12 +++++++++++- compiler/modules/write_driver.py | 12 ++++++++++++ compiler/pgates/pnand2.py | 9 +++++++++ compiler/sram_1bank.py | 16 ++++++++++++++++ compiler/tests/05_bitcell_1rw_1r_array_test.py | 2 +- compiler/tests/05_bitcell_array_test.py | 2 +- compiler/tests/12_tri_gate_array_test.py | 2 +- compiler/tests/21_hspice_delay_test.py | 17 +++++++++++++++++ 23 files changed, 196 insertions(+), 10 deletions(-) rename compiler/{base => characterizer}/graph_util.py (90%) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 607859a4..a8d0f5bf 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -24,7 +24,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): self.name = name hierarchy_layout.layout.__init__(self, name) hierarchy_spice.spice.__init__(self, name) - + self.init_graph_params() def get_layout_pins(self,inst): """ Return a map of pin locations of the instance offset """ @@ -100,6 +100,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): os.remove(tempgds) #Example graph run + # import graph_util # graph = graph_util.graph() # pins = ['A','Z','vdd','gnd'] # d.build_graph(graph,"Xpdriver",pins) @@ -108,6 +109,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): # debug.info(1,"{}".format(graph)) # graph.printAllPaths('A', 'Z') + def init_graph_params(self): + """Initializes parameters relevant to the graph creation""" + #Only initializes a set for checking instances which should not be added + self.graph_inst_exclude = set() + def build_graph(self, graph, inst_name, port_nets): """Recursively create graph from instances in module.""" @@ -115,9 +121,10 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): if len(port_nets) != len(self.pins): debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) port_dict = {i:j for i,j in zip(self.pins, port_nets)} - debug.info(1, "Instance name={}".format(inst_name)) + debug.info(3, "Instance name={}".format(inst_name)) for subinst, conns in zip(self.insts, self.conns): - debug.info(1, "Sub-Instance={}".format(subinst)) + if subinst in self.graph_inst_exclude: + continue subinst_name = inst_name+'.X'+subinst.name subinst_ports = self.translate_nets(conns, port_dict, inst_name) subinst.mod.build_graph(graph, subinst_name, subinst_ports) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 3f1d02d3..798ee3f9 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -24,7 +24,7 @@ class bitcell(design.design): self.width = bitcell.width self.height = bitcell.height self.pin_map = bitcell.pin_map - + def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node @@ -74,3 +74,12 @@ class bitcell(design.design): #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl->bl, wl->br. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[0]) + graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index e597167f..58b0ca98 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -99,3 +99,15 @@ class bitcell_1rw_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) + diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index cf487fba..3d1febdd 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -99,3 +99,14 @@ class bitcell_1w_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 94c294db..cff7b5cf 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -893,3 +893,15 @@ class pbitcell(design.design): access_tx_cin = self.readwrite_nmos.get_cin() return 2*access_tx_cin + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Done manually to make the graph acyclic.""" + #The base graph function can make this but it would contain loops and path + #searches would essentially be useless. + # Edges added wl->bl, wl->br for every port + + num_wl = len(self.rw_wl_names) + len(self.w_wl_names) + len(self.r_wl_names) + wl_pos = 2*num_wl #there are this many bitlines nets before the wls in the port list + for i in range(num_wl): + bl_pos = i*2 + graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos]) + graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos+1]) diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index d8b8b76e..8d77ff7b 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -29,3 +29,12 @@ class replica_bitcell(design.design): #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl->bl, wl->br. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[0]) + graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 8f7b3b38..67871525 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -30,3 +30,14 @@ class replica_bitcell_1rw_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index 6f59adec..1f5c3266 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -30,3 +30,14 @@ class replica_bitcell_1w_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file diff --git a/compiler/base/graph_util.py b/compiler/characterizer/graph_util.py similarity index 90% rename from compiler/base/graph_util.py rename to compiler/characterizer/graph_util.py index b795e67f..c20f3c91 100644 --- a/compiler/base/graph_util.py +++ b/compiler/characterizer/graph_util.py @@ -36,9 +36,11 @@ class graph(): # Create an array to store paths path = [] + self.path_count = 0 # Call the recursive helper function to print all paths - self.printAllPathsUtil(s, d,visited, path) + self.printAllPathsUtil(s, d,visited, path) + debug.info(1, "Paths found={}".format(self.path_count)) def printAllPathsUtil(self, u, d, visited, path): @@ -50,6 +52,7 @@ class graph(): # current path[] if u == d: debug.info(1,"{}".format(path)) + self.path_count+=1 else: # If current vertex is not destination #Recur for all the vertices adjacent to this vertex diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 5b556660..aaa44b08 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1279,3 +1279,9 @@ class bank(design.design): """Get the relative capacitance of all the sense amp enable connections in the bank""" #Current bank only uses sen as an enable for the sense amps. return self.sense_amp_array.get_en_cin() + + def graph_exclude_precharge(self): + """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" + for inst in self.precharge_array_inst: + if inst != None: + self.graph_inst_exclude.add(inst) \ No newline at end of file diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 79c68241..a06a7e90 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -193,3 +193,13 @@ class bitcell_array(design.design): bitcell_wl_cin = self.cell.get_wl_cin() total_cin = bitcell_wl_cin * self.column_size return total_cin + + def graph_exclude_bits(self, targ_row, targ_col): + """Excludes bits in column from being added to graph except target""" + #Function is not robust with column mux configurations + for row in range(self.row_size): + if row == targ_row: + continue + self.graph_inst_exclude.add(self.cell_inst[row,targ_col]) + + \ No newline at end of file diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 753ae41a..9b9dd0fe 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -50,3 +50,11 @@ class dff(design.design): #Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width. return parameter["dff_clk_cin"] + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: clk->Q. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[1]) + \ No newline at end of file diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index bd17b37e..6b5e6050 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -621,3 +621,4 @@ class hierarchical_decoder(design.design): else: pre = self.pre3_8 return pre.input_load() + diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index 67581e1a..04f212fb 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -107,3 +107,4 @@ class precharge_array(design.design): #Assume single port precharge_en_cin = self.pc_cell.get_en_cin() return precharge_en_cin*self.columns + \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 8d739041..431fc1b5 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -51,4 +51,15 @@ class sense_amp(design.design): pmos_cin = parameter["sa_en_pmos_size"]/drc("minwidth_tx") nmos_cin = parameter["sa_en_nmos_size"]/drc("minwidth_tx") #sen is connected to 2 pmos isolation TX and 1 nmos per sense amp. - return 2*pmos_cin + nmos_cin \ No newline at end of file + return 2*pmos_cin + nmos_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: en->dout, bl->dout + # br->dout not included to reduce complexity + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[2]) + graph.add_edge(port_nets[3],port_nets[2]) + \ No newline at end of file diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 688b3644..6a1efdea 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -10,7 +10,7 @@ class tri_gate(design.design): netlist should be available in the technology library. """ - pin_names = ["in", "en", "en_bar", "out", "gnd", "vdd"] + pin_names = ["in", "out", "en", "en_bar", "gnd", "vdd"] (width,height) = utils.get_libcell_size("tri_gate", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "tri_gate", GDS["unit"]) @@ -42,3 +42,13 @@ class tri_gate(design.design): def input_load(self): return 9*spice["min_tx_gate_c"] + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: en->out, en_bar->out, in->out. + # A liberal amount of edges were added, may be reduced later for complexity. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[1]) + graph.add_edge(port_nets[2],port_nets[1]) + graph.add_edge(port_nets[3],port_nets[1]) \ No newline at end of file diff --git a/compiler/modules/write_driver.py b/compiler/modules/write_driver.py index 34c51245..d20a0135 100644 --- a/compiler/modules/write_driver.py +++ b/compiler/modules/write_driver.py @@ -28,3 +28,15 @@ class write_driver(design.design): """Get the relative capacitance of a single input""" # This is approximated from SCMOS. It has roughly 5 3x transistor gates. return 5*3 + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: din->bl, din->br, en->bl, en->br + # A liberal amount of edges were added, may be reduced later for complexity. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[1]) + graph.add_edge(port_nets[0],port_nets[2]) + graph.add_edge(port_nets[3],port_nets[1]) + graph.add_edge(port_nets[3],port_nets[2]) \ No newline at end of file diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 95a9bc28..eb2484af 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -32,6 +32,8 @@ class pnand2(pgate.pgate): if not OPTS.netlist_only: self.create_layout() + #For characterization purposes only + self.exclude_nmos_from_graph() def create_netlist(self): self.add_pins() @@ -259,3 +261,10 @@ class pnand2(pgate.pgate): """ parasitic_delay = 2 return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) + + def exclude_nmos_from_graph(self): + """Exclude the nmos TXs from the graph to reduce complexity""" + #The pull-down network has an internal net which causes 2 different in->out paths + #Removing them simplifies generic path searching. + self.graph_inst_exclude.add(self.nmos1_inst) + self.graph_inst_exclude.add(self.nmos2_inst) diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index cbfec653..abe08f40 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -305,3 +305,19 @@ class sram_1bank(sram_base): self.add_label(text=n, layer=pin.layer, offset=pin.center()) + + def graph_exclude_data_dff(self): + """Removes data dff from search graph. """ + #Data dffs are only for writing so are not useful for evaluating read delay. + for inst in self.data_dff_insts: + self.graph_inst_exclude.add(inst) + + def graph_exclude_addr_dff(self): + """Removes data dff from search graph. """ + #Address is considered not part of the critical path, subjectively removed + for inst in self.row_addr_dff_insts: + self.graph_inst_exclude.add(inst) + + if self.col_addr_dff: + for inst in self.col_addr_dff_insts: + self.graph_inst_exclude.add(inst) diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 9ea0cc32..865b10b9 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -26,7 +26,7 @@ class bitcell_1rw_1r_array_test(openram_test): OPTS.num_w_ports = 0 a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) - + globals.end_openram() # run the test from the command line diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 82eaf256..eef69fd6 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -22,7 +22,7 @@ class array_test(openram_test): debug.info(2, "Testing 4x4 array for 6t_cell") a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) - + globals.end_openram() # run the test from the command line diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 04ef1369..cff8595a 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -20,7 +20,7 @@ class tri_gate_array_test(openram_test): debug.info(1, "Testing tri_gate_array for columns=8, word_size=8") a = factory.create(module_type="tri_gate_array", columns=8, word_size=8) self.local_check(a) - + debug.info(1, "Testing tri_gate_array for columns=16, word_size=8") a = factory.create(module_type="tri_gate_array", columns=16, word_size=8) self.local_check(a) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index abe65b02..fe9c4951 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -33,6 +33,23 @@ class timing_sram_test(openram_test): c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) + + #Exclude things known not to be in critical path. + #Intended for characterizing read paths. Somewhat hacky implementation + s.s.bank.bitcell_array.graph_exclude_bits(15,0) + s.s.bank.graph_exclude_precharge() + s.s.graph_exclude_addr_dff() + s.s.graph_exclude_data_dff() + + debug.info(1,'pins={}'.format(s.s.pins)) + import graph_util + graph = graph_util.graph() + pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd'] + s.s.build_graph(graph,"Xsram",pins) + graph.remove_edges('vdd') + graph.remove_edges('gnd') + debug.info(1,"{}".format(graph)) + graph.printAllPaths('clk0', 'DOUT0[0]') tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice)