mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-02 11:08:01 +02:00
Convert port index lists to three simple lists.
This commit is contained in:
@@ -73,9 +73,9 @@ class delay(simulation):
|
||||
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
||||
|
||||
#Adding port options here which the characterizer cannot handle. Some may be added later like ROM
|
||||
if len(self.read_index) == 0:
|
||||
if len(self.read_ports) == 0:
|
||||
debug.error("Characterizer does not currently support SRAMs without read ports.",1)
|
||||
if len(self.write_index) == 0:
|
||||
if len(self.write_ports) == 0:
|
||||
debug.error("Characterizer does not currently support SRAMs without write ports.",1)
|
||||
|
||||
def write_generic_stimulus(self):
|
||||
@@ -89,12 +89,12 @@ class delay(simulation):
|
||||
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||
self.stim.inst_sram(sram=self.sram,
|
||||
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(self.total_ports,self.write_index,self.read_index),
|
||||
port_info=(len(self.all_ports),self.write_ports,self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size,
|
||||
sram_name=self.name)
|
||||
self.sf.write("\n* SRAM output loads\n")
|
||||
for port in self.read_index:
|
||||
for port in self.read_ports:
|
||||
for i in range(self.word_size):
|
||||
self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port,i,self.dout_name,self.load))
|
||||
|
||||
@@ -132,7 +132,7 @@ class delay(simulation):
|
||||
self.gen_control()
|
||||
|
||||
self.sf.write("\n* Generation of Port clock signal\n")
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_pulse(sig_name="CLK{0}".format(port),
|
||||
v1=0,
|
||||
v2=self.vdd_voltage,
|
||||
@@ -171,24 +171,24 @@ class delay(simulation):
|
||||
|
||||
# generate data and addr signals
|
||||
self.sf.write("\n* Generation of data and address signals\n")
|
||||
for write_port in self.write_index:
|
||||
for write_port in self.write_ports:
|
||||
for i in range(self.word_size):
|
||||
self.stim.gen_constant(sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i),
|
||||
v_val=0)
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
for i in range(self.addr_size):
|
||||
self.stim.gen_constant(sig_name="{0}{1}_{2}".format(self.addr_name,port, i),
|
||||
v_val=0)
|
||||
|
||||
# generate control signals
|
||||
self.sf.write("\n* Generation of control signals\n")
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_constant(sig_name="CSB{0}".format(port), v_val=self.vdd_voltage)
|
||||
if port in self.write_index and port in self.read_index:
|
||||
if port in self.readwrite_ports:
|
||||
self.stim.gen_constant(sig_name="WEB{0}".format(port), v_val=self.vdd_voltage)
|
||||
|
||||
self.sf.write("\n* Generation of global clock signal\n")
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_constant(sig_name="CLK{0}".format(port), v_val=0)
|
||||
|
||||
self.write_power_measures()
|
||||
@@ -317,7 +317,7 @@ class delay(simulation):
|
||||
double the period until we find a valid period to use as a
|
||||
starting point.
|
||||
"""
|
||||
debug.check(port in self.read_index, "Characterizer requires a read port to determine a period.")
|
||||
debug.check(port in self.read_ports, "Characterizer requires a read port to determine a period.")
|
||||
|
||||
feasible_period = float(tech.spice["feasible_period"])
|
||||
time_out = 9
|
||||
@@ -362,18 +362,18 @@ class delay(simulation):
|
||||
Loops through all read ports determining the feasible period and collecting
|
||||
delay information from each port.
|
||||
"""
|
||||
feasible_delays = [{} for i in range(self.total_ports)]
|
||||
feasible_delays = [{} for i in self.all_ports]
|
||||
|
||||
#Get initial feasible delays from first port
|
||||
feasible_delays[self.read_index[0]] = self.find_feasible_period_one_port(self.read_index[0])
|
||||
feasible_delays[self.read_ports[0]] = self.find_feasible_period_one_port(self.read_ports[0])
|
||||
previous_period = self.period
|
||||
|
||||
|
||||
#Loops through all the ports checks if the feasible period works. Everything restarts it if does not.
|
||||
#Write ports do not produce delays which is why they are not included here.
|
||||
i = 1
|
||||
while i < len(self.read_index):
|
||||
port = self.read_index[i]
|
||||
while i < len(self.read_ports):
|
||||
port = self.read_ports[i]
|
||||
#Only extract port values from the specified port, not the entire results.
|
||||
feasible_delays[port].update(self.find_feasible_period_one_port(port))
|
||||
#Function sets the period. Restart the entire process if period changes to collect accurate delays
|
||||
@@ -416,7 +416,7 @@ class delay(simulation):
|
||||
#Sanity Check
|
||||
debug.check(self.period > 0, "Target simulation period non-positive")
|
||||
|
||||
result = [{} for i in range(self.total_ports)]
|
||||
result = [{} for i in self.all_ports]
|
||||
# Checking from not data_value to data_value
|
||||
self.write_delay_stimulus()
|
||||
|
||||
@@ -518,7 +518,7 @@ class delay(simulation):
|
||||
|
||||
#Find the minimum period for all ports. Start at one port and perform binary search then use that delay as a starting position.
|
||||
#For testing purposes, only checks read ports.
|
||||
for port in self.read_index:
|
||||
for port in self.read_ports:
|
||||
target_period = self.find_min_period_one_port(feasible_delays, port, lb_period, ub_period, target_period)
|
||||
#The min period of one port becomes the new lower bound. Reset the upper_bound.
|
||||
lb_period = target_period
|
||||
@@ -683,8 +683,8 @@ class delay(simulation):
|
||||
"""Simulate all specified output loads and input slews pairs of all ports"""
|
||||
measure_data = self.get_empty_measure_data_dict()
|
||||
#Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways.
|
||||
self.targ_read_ports = self.read_index
|
||||
self.targ_write_ports = self.write_index
|
||||
self.targ_read_ports = self.read_ports
|
||||
self.targ_write_ports = self.write_ports
|
||||
for slew in slews:
|
||||
for load in loads:
|
||||
self.set_load_slew(load,slew)
|
||||
@@ -693,7 +693,7 @@ class delay(simulation):
|
||||
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load))
|
||||
debug.info(1, "Simulation Passed: Port {0} slew={1} load={2}".format("All", self.slew,self.load))
|
||||
#The results has a dict for every port but dicts can be empty (e.g. ports were not targeted).
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
for mname,value in delay_results[port].items():
|
||||
if "power" in mname:
|
||||
# Subtract partial array leakage and add full array leakage for the power measures
|
||||
@@ -763,15 +763,15 @@ class delay(simulation):
|
||||
|
||||
def get_available_port(self,get_read_port):
|
||||
"""Returns the first accessible read or write port. """
|
||||
if get_read_port and len(self.read_index) > 0:
|
||||
return self.read_index[0]
|
||||
elif not get_read_port and len(self.write_index) > 0:
|
||||
return self.write_index[0]
|
||||
if get_read_port and len(self.read_ports) > 0:
|
||||
return self.read_ports[0]
|
||||
elif not get_read_port and len(self.write_ports) > 0:
|
||||
return self.write_ports[0]
|
||||
return None
|
||||
|
||||
def set_stimulus_variables(self):
|
||||
simulation.set_stimulus_variables(self)
|
||||
self.measure_cycles = [{} for port in range(self.total_ports)]
|
||||
self.measure_cycles = [{} for port in self.all_ports]
|
||||
|
||||
def create_test_cycles(self):
|
||||
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||
@@ -819,7 +819,7 @@ class delay(simulation):
|
||||
for load in loads:
|
||||
self.set_load_slew(load,slew)
|
||||
bank_delay = self.sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
for mname in self.delay_meas_names+self.power_meas_names:
|
||||
if "power" in mname:
|
||||
port_data[port][mname].append(power.dynamic)
|
||||
@@ -877,7 +877,7 @@ class delay(simulation):
|
||||
|
||||
def gen_data(self):
|
||||
""" Generates the PWL data inputs for a simulation timing test. """
|
||||
for write_port in self.write_index:
|
||||
for write_port in self.write_ports:
|
||||
for i in range(self.word_size):
|
||||
sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i)
|
||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[write_port][i], self.period, self.slew, 0.05)
|
||||
@@ -887,16 +887,16 @@ class delay(simulation):
|
||||
Generates the address inputs for a simulation timing test.
|
||||
This alternates between all 1's and all 0's for the address.
|
||||
"""
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
for i in range(self.addr_size):
|
||||
sig_name = "{0}{1}_{2}".format(self.addr_name,port,i)
|
||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.addr_values[port][i], self.period, self.slew, 0.05)
|
||||
|
||||
def gen_control(self):
|
||||
""" Generates the control signals """
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05)
|
||||
if port in self.read_index and port in self.write_index:
|
||||
if port in self.readwrite_ports:
|
||||
self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05)
|
||||
|
||||
|
||||
@@ -904,5 +904,5 @@ class delay(simulation):
|
||||
"""Make a dict of lists for each type of delay and power measurement to append results to"""
|
||||
measure_names = self.delay_meas_names + self.power_meas_names
|
||||
#Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists.
|
||||
measure_data = [{mname:[] for mname in measure_names} for i in range(self.total_ports)]
|
||||
measure_data = [{mname:[] for mname in measure_names} for i in self.all_ports]
|
||||
return measure_data
|
||||
|
||||
@@ -80,8 +80,8 @@ class functional(simulation):
|
||||
|
||||
# Read at least once. For multiport, it is important that one read cycle uses all RW and R port to read from the same address simultaniously.
|
||||
# This will test the viablilty of the transistor sizing in the bitcell.
|
||||
for port in range(self.total_ports):
|
||||
if self.port_id[port] == "w":
|
||||
for port in self.all_ports:
|
||||
if port in self.write_ports:
|
||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
|
||||
else:
|
||||
comment = self.gen_cycle_comment("read", word, addr, port, self.t_current)
|
||||
@@ -94,10 +94,10 @@ class functional(simulation):
|
||||
# Perform a random sequence of writes and reads on random ports, using random addresses and random words
|
||||
for i in range(self.num_cycles):
|
||||
w_addrs = []
|
||||
for port in range(self.total_ports):
|
||||
if self.port_id[port] == "rw":
|
||||
for port in self.all_ports:
|
||||
if port in self.readwrite_ports:
|
||||
op = random.choice(rw_ops)
|
||||
elif self.port_id[port] == "w":
|
||||
elif port in self.write_ports:
|
||||
op = random.choice(w_ops)
|
||||
else:
|
||||
op = random.choice(r_ops)
|
||||
@@ -225,17 +225,17 @@ class functional(simulation):
|
||||
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||
self.stim.inst_sram(sram=self.sram,
|
||||
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(self.total_ports, self.write_index, self.read_index),
|
||||
port_info=(len(self.all_ports), self.write_ports, self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size,
|
||||
sram_name=self.name)
|
||||
|
||||
# Add load capacitance to each of the read ports
|
||||
self.sf.write("\n* SRAM output loads\n")
|
||||
for port in range(self.total_read):
|
||||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
sig_name="{0}{1}_{2} ".format(self.dout_name, self.read_index[port], bit)
|
||||
self.sf.write("CD{0}{1} {2} 0 {3}f\n".format(self.read_index[port], bit, sig_name, self.load))
|
||||
sig_name="{0}{1}_{2} ".format(self.dout_name, port, bit)
|
||||
self.sf.write("CD{0}{1} {2} 0 {3}f\n".format(port, bit, sig_name, self.load))
|
||||
|
||||
# Write debug comments to stim file
|
||||
self.sf.write("\n\n * Sequence of operations\n")
|
||||
@@ -244,27 +244,27 @@ class functional(simulation):
|
||||
|
||||
# Generate data input bits
|
||||
self.sf.write("\n* Generation of data and address signals\n")
|
||||
for port in range(self.total_write):
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
sig_name="{0}{1}_{2} ".format(self.din_name, port, bit)
|
||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, self.slew, 0.05)
|
||||
|
||||
# Generate address bits
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
for bit in range(self.addr_size):
|
||||
sig_name="{0}{1}_{2} ".format(self.addr_name, port, bit)
|
||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.addr_values[port][bit], self.period, self.slew, 0.05)
|
||||
|
||||
# Generate control signals
|
||||
self.sf.write("\n * Generation of control signals\n")
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_pwl("CSB{}".format(port), self.cycle_times , self.csb_values[port], self.period, self.slew, 0.05)
|
||||
|
||||
for port in range(self.num_rw_ports):
|
||||
for port in self.readwrite_ports:
|
||||
self.stim.gen_pwl("WEB{}".format(port), self.cycle_times , self.web_values[port], self.period, self.slew, 0.05)
|
||||
|
||||
# Generate CLK signals
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.stim.gen_pulse(sig_name="{0}{1}".format(tech.spice["clk"], port),
|
||||
v1=self.gnd_voltage,
|
||||
v2=self.vdd_voltage,
|
||||
|
||||
@@ -22,13 +22,10 @@ class simulation():
|
||||
self.num_banks = self.sram.num_banks
|
||||
self.sp_file = spfile
|
||||
|
||||
self.total_ports = self.sram.total_ports
|
||||
self.total_write = self.sram.total_write
|
||||
self.total_read = self.sram.total_read
|
||||
self.read_index = self.sram.read_index
|
||||
self.write_index = self.sram.write_index
|
||||
self.num_rw_ports = self.sram.num_rw_ports
|
||||
self.port_id = self.sram.port_id
|
||||
self.all_ports = self.sram.all_ports
|
||||
self.readwrite_ports = self.sram.readwrite_ports
|
||||
self.read_ports = self.sram.read_ports
|
||||
self.write_ports = self.sram.write_ports
|
||||
|
||||
def set_corner(self,corner):
|
||||
""" Set the corner values """
|
||||
@@ -48,12 +45,12 @@ class simulation():
|
||||
self.t_current = 0
|
||||
|
||||
# control signals: only one cs_b for entire multiported sram, one we_b for each write port
|
||||
self.csb_values = [[] for port in range(self.total_ports)]
|
||||
self.web_values = [[] for port in range(self.num_rw_ports)]
|
||||
self.csb_values = [[] for port in self.all_ports]
|
||||
self.web_values = [[] for port in self.readwrite_ports]
|
||||
|
||||
# Three dimensional list to handle each addr and data bits for wach port over the number of checks
|
||||
self.addr_values = [[[] for bit in range(self.addr_size)] for port in range(self.total_ports)]
|
||||
self.data_values = [[[] for bit in range(self.word_size)] for port in range(self.total_write)]
|
||||
self.addr_values = [[[] for bit in range(self.addr_size)] for port in self.all_ports]
|
||||
self.data_values = [[[] for bit in range(self.word_size)] for port in self.write_ports]
|
||||
|
||||
# For generating comments in SPICE stimulus
|
||||
self.cycle_comments = []
|
||||
@@ -75,7 +72,7 @@ class simulation():
|
||||
# Append the values depending on the type of port
|
||||
self.csb_values[port].append(csb_val)
|
||||
# If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
||||
if port < self.num_rw_ports:
|
||||
if port in self.readwrite_ports:
|
||||
self.web_values[port].append(web_val)
|
||||
|
||||
def add_data(self, data, port):
|
||||
@@ -108,7 +105,7 @@ class simulation():
|
||||
|
||||
def add_write(self, comment, address, data, port):
|
||||
""" Add the control values for a write cycle. """
|
||||
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
||||
debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
self.append_cycle_comment(port, comment)
|
||||
@@ -123,13 +120,13 @@ class simulation():
|
||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
||||
noop_data = "0"*self.word_size
|
||||
#Add noops to all other ports.
|
||||
for unselected_port in range(self.total_ports):
|
||||
for unselected_port in self.all_ports:
|
||||
if unselected_port != port:
|
||||
self.add_noop_one_port(address, noop_data, unselected_port)
|
||||
|
||||
def add_read(self, comment, address, din_data, port):
|
||||
""" Add the control values for a read cycle. """
|
||||
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
||||
debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
self.append_cycle_comment(port, comment)
|
||||
@@ -139,14 +136,14 @@ class simulation():
|
||||
self.add_control_one_port(port, "read")
|
||||
|
||||
#If the port is also a readwrite then add data.
|
||||
if port in self.write_index:
|
||||
if port in self.write_ports:
|
||||
self.add_data(din_data,port)
|
||||
self.add_address(address, port)
|
||||
|
||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
||||
noop_data = "0"*self.word_size
|
||||
#Add noops to all other ports.
|
||||
for unselected_port in range(self.total_ports):
|
||||
for unselected_port in self.all_ports:
|
||||
if unselected_port != port:
|
||||
self.add_noop_one_port(address, noop_data, unselected_port)
|
||||
|
||||
@@ -159,12 +156,12 @@ class simulation():
|
||||
self.cycle_times.append(self.t_current)
|
||||
self.t_current += self.period
|
||||
|
||||
for port in range(self.total_ports):
|
||||
for port in self.all_ports:
|
||||
self.add_noop_one_port(address, data, port)
|
||||
|
||||
def add_write_one_port(self, comment, address, data, port):
|
||||
""" Add the control values for a write cycle. Does not increment the period. """
|
||||
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
||||
debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
|
||||
@@ -174,20 +171,20 @@ class simulation():
|
||||
|
||||
def add_read_one_port(self, comment, address, din_data, port):
|
||||
""" Add the control values for a read cycle. Does not increment the period. """
|
||||
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
||||
debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
|
||||
self.add_control_one_port(port, "read")
|
||||
#If the port is also a readwrite then add data.
|
||||
if port in self.write_index:
|
||||
if port in self.write_ports:
|
||||
self.add_data(din_data,port)
|
||||
self.add_address(address, port)
|
||||
|
||||
def add_noop_one_port(self, address, data, port):
|
||||
""" Add the control values for a noop to a single port. Does not increment the period. """
|
||||
self.add_control_one_port(port, "noop")
|
||||
if port in self.write_index:
|
||||
if port in self.write_ports:
|
||||
self.add_data(data,port)
|
||||
self.add_address(address, port)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user