Skip to content

Commit 75cd896

Browse files
authored
Merge pull request #4767 from The-OpenROAD-Project-staging/ss-input-prune
pruned obsolete spreadsheet RAM code
2 parents f274d5d + e7265e8 commit 75cd896

5 files changed

Lines changed: 1 addition & 350 deletions

File tree

Lines changed: 1 addition & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,21 @@
11
#!/usr/bin/env python3
22

3-
import re
43
import sys
5-
import csv
6-
import argparse
74
import importlib.util
85

9-
from utils.timing_data import TimingData
10-
from utils.memory_config import MemoryConfig
11-
from utils.class_process import Process
12-
from utils.run_utils import RunUtils
136
from utils.rw_port_group import RWPortGroup
14-
from utils.ss_port_creator import SSPortCreator
15-
from utils.ss_port_organizer import SSPortOrganizer
16-
from utils.single_port_ssram import SinglePortSSRAM
17-
18-
# TODO
19-
# support reg file
207

218
#
229
# Class to generate a single port RAM from customer-specific spreadsheet input
2310
#
24-
# Usage: spreadsheet_ram.py --config <fakeram_config> --physical <physical_csv>
25-
# --mem_config <metrics_csv>
26-
# --mapping <custom_mapping> --output_dir <output_dir>
27-
#
28-
# where
29-
# fakeram_config - standard FakeRAM2.0 JSON config
30-
# physical_csv - CSV file containing physical data such as size, pins (layer
31-
# and rect) and obstructions
32-
# metrics_csv - CSV file containing power and timing characteristics
33-
# custom_mapping - Python3 file containing two mapping routines that are
34-
# custom-specific (see below)
35-
# output_dir - output directory name
36-
#
3711

3812

3913
class SSRAMGenerator:
4014
"""Container class for generating a spreadsheet-based memory"""
4115

42-
def __init__(self, config_file, util_file):
16+
def __init__(self, util_file):
4317
"""Initializer"""
4418
self._import_custom_mappings(util_file)
45-
if config_file:
46-
# Use config to get voltage
47-
self._process = Process(RunUtils.get_config(config_file))
4819

4920
def _import_custom_mappings(self, file_name):
5021
"""
@@ -69,31 +40,6 @@ def _import_custom_mappings(self, file_name):
6940
"VDD": "power",
7041
}
7142
72-
get_key_map - returns a dictionary that maps the CSV column to a
73-
dictionary that helps the SSRAMGenerator properly handle
74-
the data in its own structures. The dictionary recognizes
75-
the following keys:
76-
77-
key: name of the field in the functional or timing
78-
data object
79-
type: object type to convert into
80-
conversion: optional field for unit conversion (csv
81-
value is multiplied by the specified value
82-
83-
Example:
84-
key_map = {
85-
"Num Words": { "key": "depth", "type": int },
86-
"Num Bits": { "key": "width", "type": int },
87-
"Num Banks": { "key": "banks", "type": int },
88-
"Memory Name": { "key": "name", "type": str },
89-
"cin (pf)":{ "key": "cap_input_pf", "type": float },
90-
"corner.Ts (ns)": { "key": "t_setup_ns", "type": float },
91-
"corner.Th (ns)": { "key": "t_hold_ns", "type": float },
92-
"corner.Ta (ns)": { "key": "access_time_ns", "type": float },
93-
"corner.Tc (ns)": { "key": "cycle_time_ns", "type": float },
94-
"Static Power (uW)": { "key": "standby_leakage_per_bank_mW", "type": float, "conversion": 1e-3 },
95-
"Dynamic Power (uW/MHz)": { "key": "pin_dynamic_power_mW", "type": float , "conversion": 1e-3},
96-
}
9743
"""
9844

9945
module_name = "spreadsheet_utils"
@@ -102,135 +48,6 @@ def _import_custom_mappings(self, file_name):
10248
sys.modules[module_name] = self._util_module
10349
spec.loader.exec_module(self._util_module)
10450
self._pin_type_map = self._util_module.get_pin_type_map()
105-
self._key_map = self._util_module.get_key_map()
106-
107-
def create_memory(self, mem_config, physical):
108-
"""Extracts the data from the CSV files and returns the memory object"""
109-
110-
# Get the physical data and organize it
111-
phys_data = self.read_physical_file(physical)
112-
pin_org = SSPortOrganizer(self._pin_type_map)
113-
pin_org.organize_ports(phys_data)
114-
num_pins = len(phys_data["pin_data"])
115-
116-
# Get the metrics data and organize it
117-
macro_metrics = self.read_metrics_file(mem_config, phys_data["name"])
118-
timing_data = TimingData(macro_metrics)
119-
mem_config = MemoryConfig.from_json(macro_metrics)
120-
121-
mem = SinglePortSSRAM(mem_config, self._process, timing_data, num_pins)
122-
self.set_logical_pins(mem, pin_org)
123-
port_creator = SSPortCreator(mem, self._pin_type_map)
124-
port_creator.create_ports(phys_data["pin_data"])
125-
if "obs" in phys_data:
126-
port_creator.create_obs(phys_data["obs"])
127-
mem.get_physical_data().set_extents(
128-
float(phys_data["width"]), float(phys_data["height"])
129-
)
130-
# snap to grid to sync up the physical data fields
131-
mem.get_physical_data().snap_to_grid(1, 1)
132-
return mem
133-
134-
def read_physical_file(self, file_name):
135-
"""
136-
Reads the physical data CSV file and returns a dictionary that includes
137-
the pin and obstruction data
138-
"""
139-
140-
macro_data = {"pin_data": {}, "obs": []}
141-
with open(file_name, "r", encoding="utf-8-sig") as csv_fh:
142-
reader = csv.DictReader(csv_fh)
143-
is_first = True
144-
for row in reader:
145-
# MACRO,SIZE_WIDTH,SIZE_HEIGHT,SOURCE,PIN,USE,LAYER,x1,y1,x2,y2
146-
if is_first:
147-
macro_data["name"] = row["MACRO"]
148-
macro_data["width"] = row["SIZE_WIDTH"]
149-
macro_data["height"] = row["SIZE_HEIGHT"]
150-
is_first = False
151-
source = row["SOURCE"]
152-
if source == "PIN":
153-
pin_data = {
154-
"name": row["PIN"],
155-
"use": row["USE"],
156-
"layer": row["LAYER"],
157-
"rect": [
158-
float(row["x1"]),
159-
float(row["y1"]),
160-
float(row["x2"]),
161-
float(row["y2"]),
162-
],
163-
}
164-
if pin_data["name"] not in macro_data["pin_data"]:
165-
macro_data["pin_data"][pin_data["name"]] = pin_data
166-
else: # pragma: no cover
167-
raise Exception(
168-
"{} had multiple pin shapes".format(pin_data["name"])
169-
)
170-
elif source == "OBS":
171-
obs_data = {
172-
"layer": row["LAYER"],
173-
"layer_attr": None,
174-
"rect": [
175-
float(row["x1"]),
176-
float(row["y1"]),
177-
float(row["x2"]),
178-
float(row["y2"]),
179-
],
180-
}
181-
macro_data["obs"].append(obs_data)
182-
else:
183-
print(
184-
"Skipping {} since source is {}".format(
185-
row["PIN"], row["SOURCE"]
186-
)
187-
)
188-
return macro_data
189-
190-
def get_size_keys(self):
191-
"""Returns the keys that map to depth and width"""
192-
193-
depth_key = width_key = None
194-
for key, val in self._key_map.items():
195-
if val.get("key") == "depth":
196-
depth_key = key
197-
elif val.get("key") == "width":
198-
width_key = key
199-
return (depth_key, width_key)
200-
201-
def read_metrics_file(self, file_name, macro_name):
202-
"""
203-
Reads the metrics CSV file to extract the power and timing data.
204-
205-
Returns a dictionary that has been normalized to our expected metrics
206-
and Process/TimingData names
207-
208-
The depth and width are present on the first row and apply to all
209-
subsequent rows until they are set again on a subsequent row.
210-
Effectively, the cells should have been merged, but weren't.
211-
"""
212-
macro_metrics = {}
213-
depth = width = None
214-
depth_key, width_key = self.get_size_keys()
215-
with open(file_name, "r", encoding="utf-8-sig") as csv_fh:
216-
reader = csv.DictReader(csv_fh)
217-
for row in reader:
218-
if row[depth_key]:
219-
depth = row[depth_key]
220-
if row[width_key]:
221-
width = row[width_key]
222-
if row["memory_name"] == macro_name:
223-
row[depth_key] = depth
224-
row[width_key] = width
225-
for csv_key, metric_key_data in self._key_map.items():
226-
if csv_key in row and row[csv_key] != "N/A":
227-
metric_key = metric_key_data["key"]
228-
metric_type_fn = metric_key_data["type"]
229-
metric_conv_factor = metric_key_data.get("conversion", 1)
230-
macro_metrics[metric_key] = (
231-
metric_type_fn(row[csv_key]) * metric_conv_factor
232-
)
233-
return macro_metrics
23451

23552
def set_logical_pins(self, mem, pin_org):
23653
"""Sets the pins to be used for Verilog and Liberty output"""
@@ -261,44 +78,3 @@ def set_logical_pins(self, mem, pin_org):
26178
for src in pin_org.get_misc_ports():
26279
if src["type"] not in ["power", "ground"]:
26380
mem.add_misc_port(src["name"])
264-
265-
@staticmethod
266-
def main():
267-
"""Main driver"""
268-
parser = argparse.ArgumentParser(
269-
description="Create a set of memory colllateral from a spreadsheet input"
270-
)
271-
parser.add_argument(
272-
"--config",
273-
help="Input configuration file containing technology parameters",
274-
required=True,
275-
)
276-
parser.add_argument(
277-
"--mem_config",
278-
help="CSV file containing technical parameters such as size, timing, power",
279-
required=True,
280-
)
281-
parser.add_argument(
282-
"--physical",
283-
help="CSV file containing physical data such as pin locations and layers",
284-
required=True,
285-
)
286-
parser.add_argument(
287-
"--mapping", help="Custom Python mapping file", required=True
288-
)
289-
parser.add_argument(
290-
"--output_dir",
291-
action="store",
292-
help="Output directory ",
293-
required=False,
294-
default="results",
295-
)
296-
297-
args = parser.parse_args()
298-
rep = SSRAMGenerator(args.config, args.mapping)
299-
mem = rep.create_memory(args.mem_config, args.physical)
300-
RunUtils.write_memory(mem, args.output_dir)
301-
302-
303-
if __name__ == "__main__":
304-
SSRAMGenerator.main()

‎tools/FakeRAM2.0/test/dpsram_ss_flow_test.py‎

Lines changed: 0 additions & 40 deletions
This file was deleted.

‎tools/FakeRAM2.0/test/spsram_mask_test.py‎

100644100755
File mode changed.

‎tools/FakeRAM2.0/test/spsram_ss_flow_test.py‎

Lines changed: 0 additions & 40 deletions
This file was deleted.

‎tools/FakeRAM2.0/test/ss_flow_test_base.py‎

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)