Convert entire OpenRAM to use python3. Works with Python 3.6.

Major changes:
Remove mpmath library and use numpy instead.
Convert bytes to new bytearrays.
Fix class name check for duplicate gds instances.
Add explicit integer conversion from floats.
Fix importlib reload from importlib library
Fix new key/index syntax issues.
Fix filter and map conversion to lists.
Fix deprecation warnings.
Fix Circuits vs Netlist in Magic LVS results.
Fix file closing warnings.
This commit is contained in:
Matt Guthaus
2018-05-14 16:15:45 -07:00
parent 58628d7867
commit f34c4eb7dc
179 changed files with 803 additions and 42105 deletions
+3 -3
View File
@@ -1,9 +1,9 @@
import os
import debug
from globals import OPTS,find_exe,get_tool
import lib
import delay
import setup_hold
from .lib import *
from .delay import *
from .setup_hold import *
debug.info(2,"Initializing characterizer...")
+25 -23
View File
@@ -2,9 +2,9 @@ import sys,re,shutil
import debug
import tech
import math
import stimuli
from trim_spice import trim_spice
import charutils as ch
from .stimuli import *
from .trim_spice import *
from .charutils import *
import utils
from globals import OPTS
@@ -101,7 +101,7 @@ class delay():
self.sf.write("* Delay stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(self.period,
self.load,
self.slew))
self.stim = stimuli.stimuli(self.sf, self.corner)
self.stim = stimuli(self.sf, self.corner)
# include files in stimulus file
self.stim.write_include(self.trim_sp_file)
@@ -339,16 +339,16 @@ class delay():
# Checking from not data_value to data_value
self.write_delay_stimulus()
self.stim.run_sim()
delay_hl = ch.parse_output("timing", "delay_hl")
delay_lh = ch.parse_output("timing", "delay_lh")
slew_hl = ch.parse_output("timing", "slew_hl")
slew_lh = ch.parse_output("timing", "slew_lh")
delay_hl = parse_output("timing", "delay_hl")
delay_lh = parse_output("timing", "delay_lh")
slew_hl = parse_output("timing", "slew_hl")
slew_lh = parse_output("timing", "slew_lh")
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
read0_power=ch.parse_output("timing", "read0_power")
write0_power=ch.parse_output("timing", "write0_power")
read1_power=ch.parse_output("timing", "read1_power")
write1_power=ch.parse_output("timing", "write1_power")
read0_power=parse_output("timing", "read0_power")
write0_power=parse_output("timing", "write0_power")
read1_power=parse_output("timing", "read1_power")
write1_power=parse_output("timing", "write1_power")
if not self.check_valid_delays(delays):
return (False,{})
@@ -378,22 +378,24 @@ class delay():
self.write_power_stimulus(trim=False)
self.stim.run_sim()
leakage_power=ch.parse_output("timing", "leakage_power")
leakage_power=parse_output("timing", "leakage_power")
debug.check(leakage_power!="Failed","Could not measure leakage power.")
self.write_power_stimulus(trim=True)
self.stim.run_sim()
trim_leakage_power=ch.parse_output("timing", "leakage_power")
trim_leakage_power=parse_output("timing", "leakage_power")
debug.check(trim_leakage_power!="Failed","Could not measure leakage power.")
# For debug, you sometimes want to inspect each simulation.
#key=raw_input("press return to continue")
return (leakage_power*1e3, trim_leakage_power*1e3)
def check_valid_delays(self, (delay_hl, delay_lh, slew_hl, slew_lh)):
def check_valid_delays(self, delay_tuple):
""" Check if the measurements are defined and if they are valid. """
(delay_hl, delay_lh, slew_hl, slew_lh) = delay_tuple
# if it failed or the read was longer than a period
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
@@ -457,7 +459,7 @@ class delay():
else:
lb_period = target_period
if ch.relative_compare(ub_period, lb_period, error_tolerance=0.05):
if relative_compare(ub_period, lb_period, error_tolerance=0.05):
# ub_period is always feasible
return ub_period
@@ -471,10 +473,10 @@ class delay():
# Checking from not data_value to data_value
self.write_delay_stimulus()
self.stim.run_sim()
delay_hl = ch.parse_output("timing", "delay_hl")
delay_lh = ch.parse_output("timing", "delay_lh")
slew_hl = ch.parse_output("timing", "slew_hl")
slew_lh = ch.parse_output("timing", "slew_lh")
delay_hl = parse_output("timing", "delay_hl")
delay_lh = parse_output("timing", "delay_lh")
slew_hl = parse_output("timing", "slew_hl")
slew_lh = parse_output("timing", "slew_lh")
# if it failed or the read was longer than a period
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
@@ -495,10 +497,10 @@ class delay():
slew_lh))
return False
else:
if not ch.relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
if not relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay_lh,feasible_delay_lh))
return False
elif not ch.relative_compare(delay_hl,feasible_delay_hl,error_tolerance=0.05):
elif not relative_compare(delay_hl,feasible_delay_hl,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay_hl,feasible_delay_hl))
return False
@@ -602,7 +604,7 @@ class delay():
debug.info(1, "Min Period: {0}n with a delay of {1} / {2}".format(min_period, feasible_delay_lh, feasible_delay_hl))
# 4) Pack up the final measurements
char_data["min_period"] = ch.round_time(min_period)
char_data["min_period"] = round_time(min_period)
return char_data
+13 -13
View File
@@ -1,9 +1,9 @@
import os,sys,re
import debug
import math
import setup_hold
import delay
import charutils as ch
from .setup_hold import *
from .delay import *
from .charutils import *
import tech
import numpy as np
from globals import OPTS
@@ -186,9 +186,9 @@ class lib:
""" Helper function to create quoted, line wrapped array with each row of given length """
# check that the length is a multiple or give an error!
debug.check(len(values)%length == 0,"Values are not a multiple of the length. Cannot make a full array.")
rounded_values = map(ch.round_time,values)
rounded_values = list(map(round_time,values))
split_values = [rounded_values[i:i+length] for i in range(0, len(rounded_values), length)]
formatted_rows = map(self.create_list,split_values)
formatted_rows = list(map(self.create_list,split_values))
formatted_array = ",\\\n".join(formatted_rows)
return formatted_array
@@ -274,11 +274,11 @@ class lib:
self.lib.write(" timing_type : setup_rising; \n")
self.lib.write(" related_pin : \"clk\"; \n")
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
rounded_values = map(ch.round_time,self.times["setup_times_LH"])
rounded_values = list(map(round_time,self.times["setup_times_LH"]))
self.write_values(rounded_values,len(self.slews)," ")
self.lib.write(" }\n")
self.lib.write(" fall_constraint(CONSTRAINT_TABLE) {\n")
rounded_values = map(ch.round_time,self.times["setup_times_HL"])
rounded_values = list(map(round_time,self.times["setup_times_HL"]))
self.write_values(rounded_values,len(self.slews)," ")
self.lib.write(" }\n")
self.lib.write(" }\n")
@@ -286,11 +286,11 @@ class lib:
self.lib.write(" timing_type : hold_rising; \n")
self.lib.write(" related_pin : \"clk\"; \n")
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
rounded_values = map(ch.round_time,self.times["hold_times_LH"])
rounded_values = list(map(round_time,self.times["hold_times_LH"]))
self.write_values(rounded_values,len(self.slews)," ")
self.lib.write(" }\n")
self.lib.write(" fall_constraint(CONSTRAINT_TABLE) {\n")
rounded_values = map(ch.round_time,self.times["hold_times_HL"])
rounded_values = list(map(round_time,self.times["hold_times_HL"]))
self.write_values(rounded_values,len(self.slews)," ")
self.lib.write(" }\n")
self.lib.write(" }\n")
@@ -413,8 +413,8 @@ class lib:
self.lib.write(" }\n")
self.lib.write(" }\n")
min_pulse_width = ch.round_time(self.char_results["min_period"])/2.0
min_period = ch.round_time(self.char_results["min_period"])
min_pulse_width = round_time(self.char_results["min_period"])/2.0
min_period = round_time(self.char_results["min_period"])
self.lib.write(" timing(){ \n")
self.lib.write(" timing_type :\"min_pulse_width\"; \n")
self.lib.write(" related_pin : clk; \n")
@@ -443,7 +443,7 @@ class lib:
try:
self.d
except AttributeError:
self.d = delay.delay(self.sram, self.sp_file, self.corner)
self.d = delay(self.sram, self.sp_file, self.corner)
if self.use_model:
self.char_results = self.d.analytical_delay(self.sram,self.slews,self.loads)
else:
@@ -458,7 +458,7 @@ class lib:
try:
self.sh
except AttributeError:
self.sh = setup_hold.setup_hold(self.corner)
self.sh = setup_hold(self.corner)
if self.use_model:
self.times = self.sh.analytical_setuphold(self.slews,self.loads)
else:
+8 -8
View File
@@ -1,8 +1,8 @@
import sys
import tech
import stimuli
from .stimuli import *
import debug
import charutils as ch
from .charutils import *
import ms_flop
from globals import OPTS
@@ -38,7 +38,7 @@ class setup_hold():
# creates and opens the stimulus file for writing
temp_stim = OPTS.openram_temp + "stim.sp"
self.sf = open(temp_stim, "w")
self.stim = stimuli.stimuli(self.sf, self.corner)
self.stim = stimuli(self.sf, self.corner)
self.write_header(correct_value)
@@ -186,8 +186,8 @@ class setup_hold():
target_time=feasible_bound,
correct_value=correct_value)
self.stim.run_sim()
ideal_clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time"))
ideal_clk_to_q = convert_to_float(parse_output("timing", "clk2q_delay"))
setuphold_time = convert_to_float(parse_output("timing", "setup_hold_time"))
debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time))
if type(ideal_clk_to_q)!=float or type(setuphold_time)!=float:
@@ -219,8 +219,8 @@ class setup_hold():
self.stim.run_sim()
clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time"))
clk_to_q = convert_to_float(parse_output("timing", "clk2q_delay"))
setuphold_time = convert_to_float(parse_output("timing", "setup_hold_time"))
if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float:
if mode == "SETUP": # SETUP is clk-din, not din-clk
setuphold_time *= -1e9
@@ -235,7 +235,7 @@ class setup_hold():
infeasible_bound = target_time
#raw_input("Press Enter to continue...")
if ch.relative_compare(feasible_bound, infeasible_bound, error_tolerance=0.001):
if relative_compare(feasible_bound, infeasible_bound, error_tolerance=0.001):
debug.info(3,"CONVERGE {0} vs {1}".format(feasible_bound,infeasible_bound))
break