mirror of https://github.com/VLSIDA/OpenRAM.git
Added shared classes between regression models, added and changed some debug messages
This commit is contained in:
parent
6d2a35e929
commit
70fe90f0af
|
|
@ -19,6 +19,7 @@ from .simulation import *
|
||||||
from .measurements import *
|
from .measurements import *
|
||||||
from .model_check import *
|
from .model_check import *
|
||||||
from .analytical_util import *
|
from .analytical_util import *
|
||||||
|
from .regression_model import *
|
||||||
|
|
||||||
debug.info(1,"Initializing characterizer...")
|
debug.info(1,"Initializing characterizer...")
|
||||||
OPTS.spice_exe = ""
|
OPTS.spice_exe = ""
|
||||||
|
|
|
||||||
|
|
@ -254,9 +254,9 @@ def scale_input_datapoint(point, file_path):
|
||||||
training.
|
training.
|
||||||
"""
|
"""
|
||||||
maxs, mins, avgs = get_max_min_from_file(file_path)
|
maxs, mins, avgs = get_max_min_from_file(file_path)
|
||||||
debug.info(1, "maxs={}".format(maxs))
|
debug.info(3, "maxs={}".format(maxs))
|
||||||
debug.info(1, "mins={}".format(mins))
|
debug.info(3, "mins={}".format(mins))
|
||||||
debug.info(1, "point={}".format(point))
|
debug.info(3, "point={}".format(point))
|
||||||
|
|
||||||
scaled_point = []
|
scaled_point = []
|
||||||
for feature, mx, mn in zip(point, maxs, mins):
|
for feature, mx, mn in zip(point, maxs, mins):
|
||||||
|
|
|
||||||
|
|
@ -6,131 +6,17 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
from .analytical_util import *
|
from .regression_model import regression_model
|
||||||
from .simulation import simulation
|
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
import os
|
|
||||||
from sklearn.linear_model import LinearRegression
|
from sklearn.linear_model import LinearRegression
|
||||||
import math
|
|
||||||
|
|
||||||
relative_data_path = "/sim_data"
|
|
||||||
data_fnames = ["rise_delay.csv",
|
|
||||||
"fall_delay.csv",
|
|
||||||
"rise_slew.csv",
|
|
||||||
"fall_slew.csv",
|
|
||||||
"write1_power.csv",
|
|
||||||
"write0_power.csv",
|
|
||||||
"read1_power.csv",
|
|
||||||
"read0_power.csv",
|
|
||||||
"leakage_data.csv"]
|
|
||||||
# Positions must correspond to data_fname list
|
|
||||||
lib_dnames = ["delay_lh",
|
|
||||||
"delay_hl",
|
|
||||||
"slew_lh",
|
|
||||||
"slew_hl",
|
|
||||||
"write1_power",
|
|
||||||
"write0_power",
|
|
||||||
"read1_power",
|
|
||||||
"read0_power",
|
|
||||||
"leakage_power"]
|
|
||||||
data_dir = OPTS.openram_tech+relative_data_path
|
|
||||||
data_paths = {dname:data_dir +'/'+fname for dname, fname in zip(lib_dnames, data_fnames)}
|
|
||||||
|
|
||||||
class linear_regression(simulation):
|
class linear_regression(regression_model):
|
||||||
|
|
||||||
def __init__(self, sram, spfile, corner):
|
def __init__(self, sram, spfile, corner):
|
||||||
super().__init__(sram, spfile, corner)
|
super().__init__(sram, spfile, corner)
|
||||||
self.set_corner(corner)
|
|
||||||
|
|
||||||
def get_lib_values(self, slews, loads):
|
|
||||||
"""
|
|
||||||
A model and prediction is created for each output needed for the LIB
|
|
||||||
"""
|
|
||||||
|
|
||||||
log_num_words = math.log(OPTS.num_words, 2)
|
|
||||||
debug.info(1, "OPTS.words_per_row={}".format(OPTS.words_per_row))
|
|
||||||
model_inputs = [log_num_words,
|
|
||||||
OPTS.word_size,
|
|
||||||
OPTS.words_per_row,
|
|
||||||
self.sram.width * self.sram.height,
|
|
||||||
process_transform[self.process],
|
|
||||||
self.vdd_voltage,
|
|
||||||
self.temperature]
|
|
||||||
|
|
||||||
self.create_measurement_names()
|
|
||||||
models = self.train_models()
|
|
||||||
|
|
||||||
# Set delay/power for slews and loads
|
|
||||||
port_data = self.get_empty_measure_data_dict()
|
|
||||||
debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)')
|
|
||||||
max_delay = 0.0
|
|
||||||
for slew in slews:
|
|
||||||
for load in loads:
|
|
||||||
# List returned with value order being delay, power, leakage, slew
|
|
||||||
sram_vals = self.get_predictions(model_inputs+[slew, load], models)
|
|
||||||
# Delay is only calculated on a single port and replicated for now.
|
|
||||||
for port in self.all_ports:
|
|
||||||
port_data[port]['delay_lh'].append(sram_vals['delay_lh'])
|
|
||||||
port_data[port]['delay_hl'].append(sram_vals['delay_hl'])
|
|
||||||
port_data[port]['slew_lh'].append(sram_vals['slew_lh'])
|
|
||||||
port_data[port]['slew_hl'].append(sram_vals['slew_hl'])
|
|
||||||
|
|
||||||
port_data[port]['write1_power'].append(sram_vals['write1_power'])
|
|
||||||
port_data[port]['write0_power'].append(sram_vals['write0_power'])
|
|
||||||
port_data[port]['read1_power'].append(sram_vals['read1_power'])
|
|
||||||
port_data[port]['read0_power'].append(sram_vals['read0_power'])
|
|
||||||
|
|
||||||
# Disabled power not modeled. Copied from other power predictions
|
|
||||||
port_data[port]['disabled_write1_power'].append(sram_vals['write1_power'])
|
|
||||||
port_data[port]['disabled_write0_power'].append(sram_vals['write0_power'])
|
|
||||||
port_data[port]['disabled_read1_power'].append(sram_vals['read1_power'])
|
|
||||||
port_data[port]['disabled_read0_power'].append(sram_vals['read0_power'])
|
|
||||||
|
|
||||||
|
|
||||||
# Estimate the period as double the delay with margin
|
|
||||||
period_margin = 0.1
|
|
||||||
sram_data = {"min_period": sram_vals['delay_lh'] * 2,
|
|
||||||
"leakage_power": sram_vals["leakage_power"]}
|
|
||||||
|
|
||||||
debug.info(2, "SRAM Data:\n{}".format(sram_data))
|
|
||||||
debug.info(2, "Port Data:\n{}".format(port_data))
|
|
||||||
|
|
||||||
return (sram_data, port_data)
|
|
||||||
|
|
||||||
def get_predictions(self, model_inputs, models):
|
|
||||||
"""
|
|
||||||
Generate a model and prediction for LIB output
|
|
||||||
"""
|
|
||||||
|
|
||||||
#Scaled the inputs using first data file as a reference
|
|
||||||
data_name = lib_dnames[0]
|
|
||||||
scaled_inputs = np.asarray([scale_input_datapoint(model_inputs, data_paths[data_name])])
|
|
||||||
|
|
||||||
predictions = {}
|
|
||||||
for dname in data_paths.keys():
|
|
||||||
path = data_paths[dname]
|
|
||||||
m = models[dname]
|
|
||||||
|
|
||||||
features, labels = get_scaled_data(path)
|
|
||||||
scaled_pred = self.model_prediction(m, scaled_inputs)
|
|
||||||
pred = unscale_data(scaled_pred.tolist(), path)
|
|
||||||
debug.info(1,"Unscaled Prediction = {}".format(pred))
|
|
||||||
predictions[dname] = pred[0][0]
|
|
||||||
return predictions
|
|
||||||
|
|
||||||
def train_models(self):
|
|
||||||
"""
|
|
||||||
Generate and return models
|
|
||||||
"""
|
|
||||||
models = {}
|
|
||||||
for dname, dpath in data_paths.items():
|
|
||||||
features, labels = get_scaled_data(dpath)
|
|
||||||
model = self.generate_model(features, labels)
|
|
||||||
models[dname] = model
|
|
||||||
return models
|
|
||||||
|
|
||||||
|
|
||||||
def generate_model(self, features, labels):
|
def generate_model(self, features, labels):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -6,121 +6,19 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
from .analytical_util import *
|
from .regression_model import regression_model
|
||||||
from .simulation import simulation
|
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
import os
|
|
||||||
import math
|
|
||||||
import numpy as np
|
|
||||||
from tensorflow import keras
|
from tensorflow import keras
|
||||||
from tensorflow.keras import layers
|
from tensorflow.keras import layers
|
||||||
import tensorflow as tf
|
import tensorflow as tf
|
||||||
|
|
||||||
relative_data_path = "/sim_data"
|
|
||||||
data_fnames = ["rise_delay.csv",
|
|
||||||
"fall_delay.csv",
|
|
||||||
"rise_slew.csv",
|
|
||||||
"fall_slew.csv",
|
|
||||||
"write1_power.csv",
|
|
||||||
"write0_power.csv",
|
|
||||||
"read1_power.csv",
|
|
||||||
"read0_power.csv",
|
|
||||||
"leakage_data.csv"]
|
|
||||||
|
|
||||||
data_dir = OPTS.openram_tech+relative_data_path
|
|
||||||
data_paths = [data_dir +'/'+fname for fname in data_fnames]
|
|
||||||
|
|
||||||
class neural_network(simulation):
|
class neural_network(regression_model):
|
||||||
|
|
||||||
def __init__(self, sram, spfile, corner):
|
def __init__(self, sram, spfile, corner):
|
||||||
super().__init__(sram, spfile, corner)
|
super().__init__(sram, spfile, corner)
|
||||||
self.set_corner(corner)
|
|
||||||
|
|
||||||
def get_lib_values(self, slews, loads):
|
|
||||||
"""
|
|
||||||
A model and prediction is created for each output needed for the LIB
|
|
||||||
"""
|
|
||||||
|
|
||||||
log_num_words = math.log(OPTS.num_words, 2)
|
|
||||||
debug.info(1, "OPTS.words_per_row={}".format(OPTS.words_per_row))
|
|
||||||
model_inputs = [log_num_words,
|
|
||||||
OPTS.word_size,
|
|
||||||
OPTS.words_per_row,
|
|
||||||
self.sram.width * self.sram.height,
|
|
||||||
process_transform[self.process],
|
|
||||||
self.vdd_voltage,
|
|
||||||
self.temperature]
|
|
||||||
|
|
||||||
self.create_measurement_names()
|
|
||||||
models = self.train_models()
|
|
||||||
|
|
||||||
# Set delay/power for slews and loads
|
|
||||||
port_data = self.get_empty_measure_data_dict()
|
|
||||||
debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)')
|
|
||||||
max_delay = 0.0
|
|
||||||
for slew in slews:
|
|
||||||
for load in loads:
|
|
||||||
# List returned with value order being delay, power, leakage, slew
|
|
||||||
# FIXME: make order less hard coded
|
|
||||||
sram_vals = self.get_predictions(model_inputs+[slew, load], models)
|
|
||||||
# Delay is only calculated on a single port and replicated for now.
|
|
||||||
for port in self.all_ports:
|
|
||||||
port_data[port]['delay_lh'].append(sram_vals[0][0][0])
|
|
||||||
port_data[port]['delay_hl'].append(sram_vals[1][0][0])
|
|
||||||
port_data[port]['slew_lh'].append(sram_vals[2][0][0])
|
|
||||||
port_data[port]['slew_hl'].append(sram_vals[3][0][0])
|
|
||||||
|
|
||||||
port_data[port]['write1_power'].append(sram_vals[4][0][0])
|
|
||||||
port_data[port]['write0_power'].append(sram_vals[5][0][0])
|
|
||||||
port_data[port]['read1_power'].append(sram_vals[6][0][0])
|
|
||||||
port_data[port]['read0_power'].append(sram_vals[7][0][0])
|
|
||||||
|
|
||||||
# Disabled power not modeled. Copied from other power predictions
|
|
||||||
port_data[port]['disabled_write1_power'].append(sram_vals[4][0][0])
|
|
||||||
port_data[port]['disabled_write0_power'].append(sram_vals[5][0][0])
|
|
||||||
port_data[port]['disabled_read1_power'].append(sram_vals[6][0][0])
|
|
||||||
port_data[port]['disabled_read0_power'].append(sram_vals[7][0][0])
|
|
||||||
|
|
||||||
|
|
||||||
# Estimate the period as double the delay with margin
|
|
||||||
period_margin = 0.1
|
|
||||||
sram_data = {"min_period": sram_vals[0][0][0] * 2,
|
|
||||||
"leakage_power": sram_vals[8][0][0]}
|
|
||||||
|
|
||||||
debug.info(2, "SRAM Data:\n{}".format(sram_data))
|
|
||||||
debug.info(2, "Port Data:\n{}".format(port_data))
|
|
||||||
|
|
||||||
return (sram_data, port_data)
|
|
||||||
|
|
||||||
def get_predictions(self, model_inputs, models):
|
|
||||||
"""
|
|
||||||
Generate a model and prediction for LIB output
|
|
||||||
"""
|
|
||||||
|
|
||||||
scaled_inputs = np.asarray([scale_input_datapoint(model_inputs, data_paths[0])])
|
|
||||||
|
|
||||||
predictions = []
|
|
||||||
for m, path in zip(models, data_paths):
|
|
||||||
features, labels = get_scaled_data(path)
|
|
||||||
scaled_pred = self.model_prediction(m, scaled_inputs)
|
|
||||||
pred = unscale_data(scaled_pred.tolist(), path)
|
|
||||||
debug.info(1,"Unscaled Prediction = {}".format(pred))
|
|
||||||
predictions.append(pred)
|
|
||||||
return predictions
|
|
||||||
|
|
||||||
def train_models(self):
|
|
||||||
"""
|
|
||||||
Generate and return models
|
|
||||||
"""
|
|
||||||
models = []
|
|
||||||
for path in data_paths:
|
|
||||||
features, labels = get_scaled_data(path)
|
|
||||||
model = self.generate_model(features, labels)
|
|
||||||
models.append(model)
|
|
||||||
return models
|
|
||||||
|
|
||||||
|
|
||||||
def generate_model(self, features, labels):
|
def generate_model(self, features, labels):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2019 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
from .analytical_util import *
|
||||||
|
from .simulation import simulation
|
||||||
|
from globals import OPTS
|
||||||
|
import debug
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
relative_data_path = "/sim_data"
|
||||||
|
data_fnames = ["rise_delay.csv",
|
||||||
|
"fall_delay.csv",
|
||||||
|
"rise_slew.csv",
|
||||||
|
"fall_slew.csv",
|
||||||
|
"write1_power.csv",
|
||||||
|
"write0_power.csv",
|
||||||
|
"read1_power.csv",
|
||||||
|
"read0_power.csv",
|
||||||
|
"leakage_data.csv"]
|
||||||
|
# Positions must correspond to data_fname list
|
||||||
|
lib_dnames = ["delay_lh",
|
||||||
|
"delay_hl",
|
||||||
|
"slew_lh",
|
||||||
|
"slew_hl",
|
||||||
|
"write1_power",
|
||||||
|
"write0_power",
|
||||||
|
"read1_power",
|
||||||
|
"read0_power",
|
||||||
|
"leakage_power"]
|
||||||
|
data_dir = OPTS.openram_tech+relative_data_path
|
||||||
|
data_paths = {dname:data_dir +'/'+fname for dname, fname in zip(lib_dnames, data_fnames)}
|
||||||
|
|
||||||
|
class regression_model(simulation):
|
||||||
|
|
||||||
|
def __init__(self, sram, spfile, corner):
|
||||||
|
super().__init__(sram, spfile, corner)
|
||||||
|
self.set_corner(corner)
|
||||||
|
|
||||||
|
def get_lib_values(self, slews, loads):
|
||||||
|
"""
|
||||||
|
A model and prediction is created for each output needed for the LIB
|
||||||
|
"""
|
||||||
|
|
||||||
|
debug.info(1, "Characterizing SRAM using linear regression models.")
|
||||||
|
log_num_words = math.log(OPTS.num_words, 2)
|
||||||
|
model_inputs = [log_num_words,
|
||||||
|
OPTS.word_size,
|
||||||
|
OPTS.words_per_row,
|
||||||
|
self.sram.width * self.sram.height,
|
||||||
|
process_transform[self.process],
|
||||||
|
self.vdd_voltage,
|
||||||
|
self.temperature]
|
||||||
|
|
||||||
|
self.create_measurement_names()
|
||||||
|
models = self.train_models()
|
||||||
|
|
||||||
|
# Set delay/power for slews and loads
|
||||||
|
port_data = self.get_empty_measure_data_dict()
|
||||||
|
debug.info(1, 'Slew, Load, Port, Delay(ns), Slew(ns)')
|
||||||
|
max_delay = 0.0
|
||||||
|
for slew in slews:
|
||||||
|
for load in loads:
|
||||||
|
# List returned with value order being delay, power, leakage, slew
|
||||||
|
sram_vals = self.get_predictions(model_inputs+[slew, load], models)
|
||||||
|
# Delay is only calculated on a single port and replicated for now.
|
||||||
|
for port in self.all_ports:
|
||||||
|
port_data[port]['delay_lh'].append(sram_vals['delay_lh'])
|
||||||
|
port_data[port]['delay_hl'].append(sram_vals['delay_hl'])
|
||||||
|
port_data[port]['slew_lh'].append(sram_vals['slew_lh'])
|
||||||
|
port_data[port]['slew_hl'].append(sram_vals['slew_hl'])
|
||||||
|
|
||||||
|
port_data[port]['write1_power'].append(sram_vals['write1_power'])
|
||||||
|
port_data[port]['write0_power'].append(sram_vals['write0_power'])
|
||||||
|
port_data[port]['read1_power'].append(sram_vals['read1_power'])
|
||||||
|
port_data[port]['read0_power'].append(sram_vals['read0_power'])
|
||||||
|
|
||||||
|
# Disabled power not modeled. Copied from other power predictions
|
||||||
|
port_data[port]['disabled_write1_power'].append(sram_vals['write1_power'])
|
||||||
|
port_data[port]['disabled_write0_power'].append(sram_vals['write0_power'])
|
||||||
|
port_data[port]['disabled_read1_power'].append(sram_vals['read1_power'])
|
||||||
|
port_data[port]['disabled_read0_power'].append(sram_vals['read0_power'])
|
||||||
|
|
||||||
|
debug.info(1, '{}, {}, {}, {}, {}'.format(slew,
|
||||||
|
load,
|
||||||
|
port,
|
||||||
|
sram_vals['delay_lh'],
|
||||||
|
sram_vals['slew_lh']))
|
||||||
|
# Estimate the period as double the delay with margin
|
||||||
|
period_margin = 0.1
|
||||||
|
sram_data = {"min_period": sram_vals['delay_lh'] * 2,
|
||||||
|
"leakage_power": sram_vals["leakage_power"]}
|
||||||
|
|
||||||
|
debug.info(2, "SRAM Data:\n{}".format(sram_data))
|
||||||
|
debug.info(2, "Port Data:\n{}".format(port_data))
|
||||||
|
|
||||||
|
return (sram_data, port_data)
|
||||||
|
|
||||||
|
def get_predictions(self, model_inputs, models):
|
||||||
|
"""
|
||||||
|
Generate a model and prediction for LIB output
|
||||||
|
"""
|
||||||
|
|
||||||
|
#Scaled the inputs using first data file as a reference
|
||||||
|
data_name = lib_dnames[0]
|
||||||
|
scaled_inputs = np.asarray([scale_input_datapoint(model_inputs, data_paths[data_name])])
|
||||||
|
|
||||||
|
predictions = {}
|
||||||
|
for dname in data_paths.keys():
|
||||||
|
path = data_paths[dname]
|
||||||
|
m = models[dname]
|
||||||
|
|
||||||
|
features, labels = get_scaled_data(path)
|
||||||
|
scaled_pred = self.model_prediction(m, scaled_inputs)
|
||||||
|
pred = unscale_data(scaled_pred.tolist(), path)
|
||||||
|
debug.info(2,"Unscaled Prediction = {}".format(pred))
|
||||||
|
predictions[dname] = pred[0][0]
|
||||||
|
return predictions
|
||||||
|
|
||||||
|
def train_models(self):
|
||||||
|
"""
|
||||||
|
Generate and return models
|
||||||
|
"""
|
||||||
|
models = {}
|
||||||
|
for dname, dpath in data_paths.items():
|
||||||
|
features, labels = get_scaled_data(dpath)
|
||||||
|
model = self.generate_model(features, labels)
|
||||||
|
models[dname] = model
|
||||||
|
return models
|
||||||
|
|
||||||
Loading…
Reference in New Issue