mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into delay_ctrl
This commit is contained in:
commit
b91c628acf
3
Makefile
3
Makefile
|
|
@ -3,6 +3,9 @@ include $(TOP_DIR)/openram.mk
|
||||||
|
|
||||||
.DEFAULT_GOAL := install
|
.DEFAULT_GOAL := install
|
||||||
|
|
||||||
|
# Set the shell here
|
||||||
|
SHELL := /bin/bash
|
||||||
|
|
||||||
# Skywater PDK SRAM library
|
# Skywater PDK SRAM library
|
||||||
SRAM_LIB_DIR ?= $(PDK_ROOT)/sky130_fd_bd_sram
|
SRAM_LIB_DIR ?= $(PDK_ROOT)/sky130_fd_bd_sram
|
||||||
# Use this for release
|
# Use this for release
|
||||||
|
|
|
||||||
14
README.md
14
README.md
|
|
@ -57,13 +57,13 @@ OpenRAM is licensed under the [BSD 3-Clause License](./LICENSE).
|
||||||
# Publications
|
# Publications
|
||||||
|
|
||||||
+ [M. R. Guthaus, J. E. Stine, S. Ataei, B. Chen, B. Wu, M. Sarwar, "OpenRAM: An Open-Source Memory Compiler," Proceedings of the 35th International Conference on Computer-Aided Design (ICCAD), 2016.](https://escholarship.org/content/qt8x19c778/qt8x19c778_noSplash_b2b3fbbb57f1269f86d0de77865b0691.pdf)
|
+ [M. R. Guthaus, J. E. Stine, S. Ataei, B. Chen, B. Wu, M. Sarwar, "OpenRAM: An Open-Source Memory Compiler," Proceedings of the 35th International Conference on Computer-Aided Design (ICCAD), 2016.](https://escholarship.org/content/qt8x19c778/qt8x19c778_noSplash_b2b3fbbb57f1269f86d0de77865b0691.pdf)
|
||||||
+ [S. Ataei, J. Stine, M. Guthaus, “A 64 kb differential single-port 12T SRAM design with a bit-interleaving scheme for low-voltage operation in 32 nm SOI CMOS,” International Conference on Computer Design (ICCD), 2016, pp. 499-506.](https://escholarship.org/uc/item/99f6q9c9)
|
+ [S. Ataei, J. Stine, M. Guthaus, "A 64 kb differential single-port 12T SRAM design with a bit-interleaving scheme for low-voltage operation in 32 nm SOI CMOS," International Conference on Computer Design (ICCD), 2016, pp. 499-506.](https://escholarship.org/uc/item/99f6q9c9)
|
||||||
+ [E. Ebrahimi, M. Guthaus, J. Renau, “Timing Speculative SRAM”, IEEE International Symposium on Circuits and Systems (ISCAS), 2017.](https://escholarship.org/content/qt7nn0j5x3/qt7nn0j5x3_noSplash_172457455e1aceba20694c3d7aa489b4.pdf)
|
+ [E. Ebrahimi, M. Guthaus, J. Renau, "Timing Speculative SRAM," IEEE International Symposium on Circuits and Systems (ISCAS), 2017.](https://escholarship.org/content/qt7nn0j5x3/qt7nn0j5x3_noSplash_172457455e1aceba20694c3d7aa489b4.pdf)
|
||||||
+ [B. Wu, J.E. Stine, M.R. Guthaus, "Fast and Area-Efficient Word-Line Optimization", IEEE International Symposium on Circuits and Systems (ISCAS), 2019.](https://escholarship.org/content/qt98s4c1hp/qt98s4c1hp_noSplash_753dcc3e218f60aafff98ef77fb56384.pdf)
|
+ [B. Wu, J.E. Stine, M.R. Guthaus, "Fast and Area-Efficient Word-Line Optimization," IEEE International Symposium on Circuits and Systems (ISCAS), 2019.](https://escholarship.org/content/qt98s4c1hp/qt98s4c1hp_noSplash_753dcc3e218f60aafff98ef77fb56384.pdf)
|
||||||
+ [B. Wu, M. Guthaus, "Bottom Up Approach for High Speed SRAM Word-line Buffer Insertion Optimization", IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019.](https://ieeexplore.ieee.org/document/8920325)
|
+ [B. Wu, M. Guthaus, "Bottom Up Approach for High Speed SRAM Word-line Buffer Insertion Optimization," IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019.](https://ieeexplore.ieee.org/document/8920325)
|
||||||
+ [H. Nichols, M. Grimes, J. Sowash, J. Cirimelli-Low, M. Guthaus "Automated Synthesis of Multi-Port Memories and Control", IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019.](https://escholarship.org/content/qt7047n3k0/qt7047n3k0.pdf?t=q4gcij)
|
+ [H. Nichols, M. Grimes, J. Sowash, J. Cirimelli-Low, M. Guthaus "Automated Synthesis of Multi-Port Memories and Control," IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019.](https://escholarship.org/content/qt7047n3k0/qt7047n3k0.pdf?t=q4gcij)
|
||||||
+ [H. Nichols, "Statistical Modeling of SRAMs", M.S. Thesis, UCSC, 2022.](https://escholarship.org/content/qt7vx9n089/qt7vx9n089_noSplash_cfc4ba479d8eb1b6ec25d7c92357bc18.pdf?t=ra9wzr)
|
+ [M. Guthaus, H. Nichols, J. Cirimelli-Low, J. Kunzler, B. Wu, "Enabling Design Technology Co-Optimization of SRAMs though Open-Source Software," IEEE International Electron Devices Meeting (IEDM), 2020.](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9372047)
|
||||||
+ [M. Guthaus, H. Nichols, J. Cirimelli-Low, J. Kunzler, B. Wu, "Enabling Design Technology Co-Optimization of SRAMs though Open-Source Software", IEEE International Electron Devices Meeting (IEDM), 2020.](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9372047)
|
+ [H. Nichols, "Statistical Modeling of SRAMs," M.S. Thesis, UCSC, 2022.](https://escholarship.org/content/qt7vx9n089/qt7vx9n089_noSplash_cfc4ba479d8eb1b6ec25d7c92357bc18.pdf?t=ra9wzr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from .lef import *
|
||||||
from .logical_effort import *
|
from .logical_effort import *
|
||||||
from .pin_layout import *
|
from .pin_layout import *
|
||||||
from .power_data import *
|
from .power_data import *
|
||||||
|
from .rom_verilog import *
|
||||||
from .route import *
|
from .route import *
|
||||||
from .timing_graph import *
|
from .timing_graph import *
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2023 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.
|
||||||
|
#
|
||||||
|
import math
|
||||||
|
from openram.tech import spice
|
||||||
|
|
||||||
|
|
||||||
|
class rom_verilog:
|
||||||
|
"""
|
||||||
|
Create a behavioral Verilog file for simulation.
|
||||||
|
This is inherited by the rom_base class.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def verilog_write(self, verilog_name):
|
||||||
|
""" Write a behavioral Verilog model. """
|
||||||
|
self.vf = open(verilog_name, "w")
|
||||||
|
|
||||||
|
self.vf.write("// OpenROM ROM model\n")
|
||||||
|
|
||||||
|
#basic info
|
||||||
|
self.vf.write("// Words: {0}\n".format(self.num_words))
|
||||||
|
self.vf.write("// Word size: {0}\n".format(self.word_size))
|
||||||
|
self.vf.write("// Word per Row: {0}\n".format(self.words_per_row))
|
||||||
|
self.vf.write("// Data Type: {0}\n".format(self.data_type))
|
||||||
|
self.vf.write("// Data File: {0}\n".format(self.rom_data))
|
||||||
|
|
||||||
|
self.vf.write("\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.vdd_name = spice["power"]
|
||||||
|
except KeyError:
|
||||||
|
self.vdd_name = "vdd"
|
||||||
|
try:
|
||||||
|
self.gnd_name = spice["ground"]
|
||||||
|
except KeyError:
|
||||||
|
self.gnd_name = "gnd"
|
||||||
|
|
||||||
|
#add multiple banks later
|
||||||
|
self.vf.write("module {0}(\n".format(self.name))
|
||||||
|
self.vf.write("`ifdef USE_POWER_PINS\n")
|
||||||
|
self.vf.write(" {},\n".format(self.vdd_name))
|
||||||
|
self.vf.write(" {},\n".format(self.gnd_name))
|
||||||
|
self.vf.write("`endif\n")
|
||||||
|
|
||||||
|
for port in self.all_ports:
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.vf.write("// Port {0}: R\n".format(port))
|
||||||
|
self.vf.write(" clk{0},csb{0},addr{0},dout{0}".format(port))
|
||||||
|
# Continue for every port on a new line
|
||||||
|
if port != self.all_ports[-1]:
|
||||||
|
self.vf.write(",\n")
|
||||||
|
self.vf.write("\n );\n\n")
|
||||||
|
|
||||||
|
self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size))
|
||||||
|
self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(math.ceil(math.log(self.num_words,2))))
|
||||||
|
self.vf.write(" parameter ROM_DEPTH = 1 << ADDR_WIDTH;\n")
|
||||||
|
self.vf.write(" // FIXME: This delay is arbitrary.\n")
|
||||||
|
self.vf.write(" parameter DELAY = 3 ;\n")
|
||||||
|
self.vf.write(" parameter VERBOSE = 1 ; //Set to 0 to only display warnings\n")
|
||||||
|
self.vf.write(" parameter T_HOLD = 1 ; //Delay to hold dout value after posedge. Value is arbitrary\n")
|
||||||
|
self.vf.write("\n")
|
||||||
|
|
||||||
|
self.vf.write("`ifdef USE_POWER_PINS\n")
|
||||||
|
self.vf.write(" inout {};\n".format(self.vdd_name))
|
||||||
|
self.vf.write(" inout {};\n".format(self.gnd_name))
|
||||||
|
self.vf.write("`endif\n")
|
||||||
|
|
||||||
|
for port in self.all_ports:
|
||||||
|
self.add_inputs_outputs(port)
|
||||||
|
|
||||||
|
self.vf.write("\n")
|
||||||
|
|
||||||
|
# This is the memory array itself
|
||||||
|
self.vf.write(" reg [DATA_WIDTH-1:0] mem [0:ROM_DEPTH-1];\n\n")
|
||||||
|
|
||||||
|
#write memory init here
|
||||||
|
self.vf.write(f" initial begin\n")
|
||||||
|
if self.data_type == "bin":
|
||||||
|
self.vf.write(f" $readmemb(\"{self.rom_data}\",mem,0,ROM_DEPTH-1);\n")
|
||||||
|
elif self.data_type == "hex":
|
||||||
|
self.vf.write(f" $readmemh(\"{self.rom_data}\",mem,0, ROM_DEPTH-1);\n")
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Data type: {self.data_type} is not supported!")
|
||||||
|
self.vf.write(f" end\n\n")
|
||||||
|
|
||||||
|
for port in self.all_ports:
|
||||||
|
self.register_inputs(port)
|
||||||
|
|
||||||
|
for port in self.all_ports:
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.add_read_block(port)
|
||||||
|
|
||||||
|
self.vf.write("\n")
|
||||||
|
self.vf.write("endmodule\n")
|
||||||
|
self.vf.close()
|
||||||
|
|
||||||
|
def register_inputs(self, port):
|
||||||
|
"""
|
||||||
|
Register the control signal, address and data inputs.
|
||||||
|
"""
|
||||||
|
self.add_regs(port)
|
||||||
|
self.add_flops(port)
|
||||||
|
|
||||||
|
def add_regs(self, port):
|
||||||
|
"""
|
||||||
|
Create the input regs for the given port.
|
||||||
|
"""
|
||||||
|
self.vf.write(" reg csb{0}_reg;\n".format(port))
|
||||||
|
self.vf.write(" reg [ADDR_WIDTH-1:0] addr{0}_reg;\n".format(port))
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.vf.write(" reg [DATA_WIDTH-1:0] dout{0};\n".format(port))
|
||||||
|
|
||||||
|
|
||||||
|
def add_flops(self, port):
|
||||||
|
"""
|
||||||
|
Add the flop behavior logic for a port.
|
||||||
|
"""
|
||||||
|
self.vf.write("\n")
|
||||||
|
self.vf.write(" // All inputs are registers\n")
|
||||||
|
self.vf.write(" always @(posedge clk{0})\n".format(port))
|
||||||
|
self.vf.write(" begin\n")
|
||||||
|
self.vf.write(" csb{0}_reg = csb{0};\n".format(port))
|
||||||
|
self.vf.write(" addr{0}_reg = addr{0};\n".format(port))
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.add_write_read_checks(port)
|
||||||
|
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.vf.write(" #(T_HOLD) dout{0} = {1}'bx;\n".format(port, self.word_size))
|
||||||
|
self.vf.write(" if ( !csb{0}_reg && VERBOSE ) \n".format(port))
|
||||||
|
self.vf.write(" $display($time,\" Reading %m addr{0}=%b dout{0}=%b\",addr{0}_reg,mem[addr{0}_reg]);\n".format(port))
|
||||||
|
|
||||||
|
self.vf.write(" end\n\n")
|
||||||
|
|
||||||
|
def add_inputs_outputs(self, port):
|
||||||
|
"""
|
||||||
|
Add the module input and output declaration for a port.
|
||||||
|
"""
|
||||||
|
self.vf.write(" input clk{0}; // clock\n".format(port))
|
||||||
|
self.vf.write(" input csb{0}; // active low chip select\n".format(port))
|
||||||
|
|
||||||
|
self.vf.write(" input [ADDR_WIDTH-1:0] addr{0};\n".format(port))
|
||||||
|
if port in self.read_ports:
|
||||||
|
self.vf.write(" output [DATA_WIDTH-1:0] dout{0};\n".format(port))
|
||||||
|
|
||||||
|
def add_write_block(self, port):
|
||||||
|
"""
|
||||||
|
ROM does not take writes thus this function does nothing
|
||||||
|
"""
|
||||||
|
self.vf.write("\n")
|
||||||
|
def add_read_block(self, port):
|
||||||
|
"""
|
||||||
|
Add a read port block.
|
||||||
|
"""
|
||||||
|
self.vf.write("\n")
|
||||||
|
self.vf.write(" // Memory Read Block Port {0}\n".format(port))
|
||||||
|
self.vf.write(" // Read Operation : When web{0} = 1, csb{0} = 0\n".format(port))
|
||||||
|
self.vf.write(" always @ (negedge clk{0})\n".format(port))
|
||||||
|
self.vf.write(" begin : MEM_READ{0}\n".format(port))
|
||||||
|
self.vf.write(" if (!csb{0}_reg)\n".format(port))
|
||||||
|
self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port))
|
||||||
|
self.vf.write(" end\n")
|
||||||
|
|
||||||
|
def add_write_read_checks(self, rport):
|
||||||
|
"""
|
||||||
|
Since ROMs dont have write ports this does nothing
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
@ -10,13 +10,14 @@ import datetime
|
||||||
from math import ceil, log
|
from math import ceil, log
|
||||||
from openram.base import vector
|
from openram.base import vector
|
||||||
from openram.base import design
|
from openram.base import design
|
||||||
|
from openram.base import rom_verilog
|
||||||
from openram import OPTS, print_time
|
from openram import OPTS, print_time
|
||||||
from openram.sram_factory import factory
|
from openram.sram_factory import factory
|
||||||
from openram.tech import drc, layer, parameter
|
from openram.tech import drc, layer, parameter
|
||||||
from openram.router import router_tech
|
from openram.router import router_tech
|
||||||
|
|
||||||
|
|
||||||
class rom_bank(design):
|
class rom_bank(design,rom_verilog):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Rom data bank with row and column decoder + control logic
|
Rom data bank with row and column decoder + control logic
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ class sram_1bank(design, verilog, lef):
|
||||||
design.__init__(self, name)
|
design.__init__(self, name)
|
||||||
lef.__init__(self, ["m1", "m2", "m3", "m4"])
|
lef.__init__(self, ["m1", "m2", "m3", "m4"])
|
||||||
verilog.__init__(self)
|
verilog.__init__(self)
|
||||||
|
|
||||||
self.sram_config = sram_config
|
self.sram_config = sram_config
|
||||||
sram_config.set_local_config(self)
|
sram_config.set_local_config(self)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class options(optparse.Values):
|
||||||
###################
|
###################
|
||||||
rom_endian = "little"
|
rom_endian = "little"
|
||||||
rom_data = None
|
rom_data = None
|
||||||
|
data_type = "bin"
|
||||||
strap_spacing = 8
|
strap_spacing = 8
|
||||||
scramble_bits = True
|
scramble_bits = True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ class rom():
|
||||||
words_per_row=OPTS.words_per_row,
|
words_per_row=OPTS.words_per_row,
|
||||||
rom_endian=OPTS.rom_endian,
|
rom_endian=OPTS.rom_endian,
|
||||||
scramble_bits=OPTS.scramble_bits,
|
scramble_bits=OPTS.scramble_bits,
|
||||||
strap_spacing=OPTS.strap_spacing)
|
strap_spacing=OPTS.strap_spacing,
|
||||||
|
data_type=OPTS.data_type)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
name = OPTS.output_name
|
name = OPTS.output_name
|
||||||
|
|
@ -38,7 +39,7 @@ class rom():
|
||||||
from openram.base import design
|
from openram.base import design
|
||||||
design.name_map=[]
|
design.name_map=[]
|
||||||
|
|
||||||
debug.info(2, "create rom of size {0} with {1} num of words".format(self.word_size,
|
debug.print_raw("create rom of word size {0} with {1} num of words".format(self.word_size,
|
||||||
self.num_words))
|
self.num_words))
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
||||||
|
|
@ -137,20 +138,22 @@ class rom():
|
||||||
|
|
||||||
|
|
||||||
# Write the config file
|
# Write the config file
|
||||||
|
# Should also save the provided data file
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
copyfile(OPTS.config_file, OPTS.output_path + OPTS.output_name + '.py')
|
copyfile(OPTS.config_file, OPTS.output_path + OPTS.output_name + '.py')
|
||||||
|
copyfile(self.rom_data, OPTS.output_path + self.rom_data)
|
||||||
debug.print_raw("Config: Writing to {0}".format(OPTS.output_path + OPTS.output_name + '.py'))
|
debug.print_raw("Config: Writing to {0}".format(OPTS.output_path + OPTS.output_name + '.py'))
|
||||||
print_time("Config", datetime.datetime.now(), start_time)
|
print_time("Config", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
# TODO: Write the datasheet
|
# TODO: Write the datasheet
|
||||||
|
|
||||||
# TODO: Write a verilog model
|
#Write a verilog model
|
||||||
# start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
# vname = OPTS.output_path + self.r.name + '.v'
|
vname = OPTS.output_path + self.r.name + '.v'
|
||||||
# debug.print_raw("Verilog: Writing to {0}".format(vname))
|
debug.print_raw("Verilog: Writing to {0}".format(vname))
|
||||||
# self.verilog_write(vname)
|
self.verilog_write(vname)
|
||||||
# print_time("Verilog", datetime.datetime.now(), start_time)
|
print_time("Verilog", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
# Write out options if specified
|
# Write out options if specified
|
||||||
if OPTS.output_extended_config:
|
if OPTS.output_extended_config:
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ from openram import OPTS
|
||||||
class rom_config:
|
class rom_config:
|
||||||
""" This is a structure that is used to hold the ROM configuration options. """
|
""" This is a structure that is used to hold the ROM configuration options. """
|
||||||
|
|
||||||
def __init__(self, word_size, rom_data, words_per_row=None, rom_endian="little", scramble_bits=True, strap_spacing=8):
|
def __init__(self, word_size, rom_data, words_per_row=None, rom_endian="little", scramble_bits=True, strap_spacing=8, data_type="hex"):
|
||||||
self.word_size = word_size
|
self.word_size = word_size
|
||||||
self.word_bits = self.word_size * 8
|
self.word_bits = self.word_size * 8
|
||||||
self.rom_data = rom_data
|
self.rom_data = rom_data
|
||||||
self.strap_spacing = strap_spacing
|
self.strap_spacing = strap_spacing
|
||||||
# TODO: This currently does nothing. It should change the behavior of the chunk funciton.
|
# TODO: This currently does nothing. It should change the behavior of the chunk funciton.
|
||||||
self.endian = rom_endian
|
self.endian = rom_endian
|
||||||
|
self.data_type = data_type
|
||||||
# This should pretty much always be true. If you want to make silicon art you might set to false
|
# This should pretty much always be true. If you want to make silicon art you might set to false
|
||||||
self.scramble_bits = scramble_bits
|
self.scramble_bits = scramble_bits
|
||||||
# This will get over-written when we determine the organization
|
# This will get over-written when we determine the organization
|
||||||
|
|
@ -57,18 +57,12 @@ class rom_config:
|
||||||
def compute_sizes(self):
|
def compute_sizes(self):
|
||||||
""" Computes the organization of the memory using data size by trying to make it a rectangle."""
|
""" Computes the organization of the memory using data size by trying to make it a rectangle."""
|
||||||
|
|
||||||
# Read data as hexidecimal text file
|
if self.data_type == "hex":
|
||||||
hex_file = open(self.rom_data, 'r')
|
raw_data = self.read_data_hex()
|
||||||
hex_data = hex_file.read()
|
elif self.data_type == "bin":
|
||||||
|
raw_data = self.read_data_bin()
|
||||||
# Convert from hex into an int
|
else:
|
||||||
data_int = int(hex_data, 16)
|
debug.error(f"Invalid input data type: {self.data_type}", -1)
|
||||||
# Then from int into a right aligned, zero padded string
|
|
||||||
bin_string = bin(data_int)[2:].zfill(len(hex_data) * 4)
|
|
||||||
|
|
||||||
# Then turn the string into a list of ints
|
|
||||||
bin_data = list(bin_string)
|
|
||||||
raw_data = [int(x) for x in bin_data]
|
|
||||||
|
|
||||||
# data size in bytes
|
# data size in bytes
|
||||||
data_size = len(raw_data) / 8
|
data_size = len(raw_data) / 8
|
||||||
|
|
@ -93,6 +87,35 @@ class rom_config:
|
||||||
OPTS.words_per_row = self.words_per_row
|
OPTS.words_per_row = self.words_per_row
|
||||||
debug.info(1, "Read rom data file: length {0} bytes, {1} words, set number of cols to {2}, rows to {3}, with {4} words per row".format(data_size, self.num_words, self.cols, self.rows, self.words_per_row))
|
debug.info(1, "Read rom data file: length {0} bytes, {1} words, set number of cols to {2}, rows to {3}, with {4} words per row".format(data_size, self.num_words, self.cols, self.rows, self.words_per_row))
|
||||||
|
|
||||||
|
def read_data_hex(self) -> List[int]:
|
||||||
|
# Read data as hexidecimal text file
|
||||||
|
with open(self.rom_data, 'r') as hex_file:
|
||||||
|
hex_data = hex_file.read()
|
||||||
|
|
||||||
|
# Convert from hex into an int
|
||||||
|
data_int = int(hex_data, 16)
|
||||||
|
# Then from int into a right aligned, zero padded string
|
||||||
|
bin_string = bin(data_int)[2:].zfill(len(hex_data) * 4)
|
||||||
|
|
||||||
|
# Then turn the string into a list of ints
|
||||||
|
bin_data = list(bin_string)
|
||||||
|
raw_data = [int(x) for x in bin_data]
|
||||||
|
return raw_data
|
||||||
|
|
||||||
|
def read_data_bin(self) -> List[int]:
|
||||||
|
|
||||||
|
# Read data as a binary file
|
||||||
|
with open(self.rom_data, 'rb') as bin_file:
|
||||||
|
bin_data = bin_file.read()
|
||||||
|
|
||||||
|
# Convert from a list of bytes to a single string of bits
|
||||||
|
bin_string = "".join(f"{n:08b}" for n in bin_data)
|
||||||
|
|
||||||
|
# Then turn the string into a list of ints
|
||||||
|
bin_data = list(bin_string)
|
||||||
|
raw_data = [int(x) for x in bin_data]
|
||||||
|
return raw_data
|
||||||
|
|
||||||
|
|
||||||
def chunk_data(self, raw_data: List[int]):
|
def chunk_data(self, raw_data: List[int]):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,13 @@ This page of the documentation explains the architecture of OpenRAM.
|
||||||
* Control Logic with Replica Bitline
|
* Control Logic with Replica Bitline
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## ROM Architecture
|
||||||
|
* Bit-cell Array
|
||||||
|
* 1T NAND Bitcell
|
||||||
|
* Row Address Decoder
|
||||||
|
* Wordline Driver(s)
|
||||||
|
* Column Multiplexer
|
||||||
|
* Column Pre-Decoder
|
||||||
|
* Bitline Precharge(s)
|
||||||
|
* Control Logic
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
|
||||||
|
### [Go Back](./index.md#table-of-contents)
|
||||||
|
|
||||||
|
# Basic Usage
|
||||||
|
This page of the documentation explains the basic usage of OpenRAM's ROM compiler (OpenROM). For usage of the RAM compiler see [here](./basic_usage.md#go-back)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
1. [Environment Variable Setup](#environment-variable-setup-assuming-bash)
|
||||||
|
1. [Command Line Usage](#command-line-usage)
|
||||||
|
1. [Script Usage](#script-usage)
|
||||||
|
1. [Configuration Files](#configuration-files)
|
||||||
|
1. [Common Configuration File Options](#common-configuration-file-options)
|
||||||
|
1. [Output Files](#output-files)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Environment Variable Setup (assuming bash)
|
||||||
|
Environment configuration is the same as described in [basic SRAM usage](./basic_usage#environment-variable-setup-assuming-bash)
|
||||||
|
|
||||||
|
|
||||||
|
## Accepted Data formats
|
||||||
|
OpenROM currently supports input data formatted as a binary file or a text file
|
||||||
|
of hexadecimal-encoded data. For hexadecimal data, the input file must contain
|
||||||
|
a single line of hexadecimal text. The data in any input file will be written
|
||||||
|
the ROM in the order it appears in the input file, ie. the first bit in the input
|
||||||
|
will be written to address 0.
|
||||||
|
|
||||||
|
## Command Line Usage
|
||||||
|
Once you have defined the environment, you can run OpenROM from the command line
|
||||||
|
using a single configuration file written in Python. You can then run OpenROM by
|
||||||
|
executing:
|
||||||
|
```
|
||||||
|
python3 $OPENRAM_HOME/../rom_compiler.py myconfig
|
||||||
|
```
|
||||||
|
You can see all of the options for the configuration file in
|
||||||
|
$OPENRAM\_HOME/options.py
|
||||||
|
|
||||||
|
To run macros, it is suggested to use, for example:
|
||||||
|
```
|
||||||
|
cd OpenRAM/macros/rom_configs
|
||||||
|
make sky130_rom_1kbyte
|
||||||
|
```
|
||||||
|
|
||||||
|
* Common arguments:
|
||||||
|
* `-h` print all arguments
|
||||||
|
* `-t` specify technology (currently only sky130 is supported)
|
||||||
|
* `-v` increase verbosity of output
|
||||||
|
* `-n` don't run DRC/LVS
|
||||||
|
* `-d` don't purge /tmp directory contents
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
* Shares some configuration options with SRAM compiler.
|
||||||
|
* Complete configuration options are in `$OPENRAM_HOME/options.py`
|
||||||
|
* Some options can be specified on the command line as well
|
||||||
|
* Not recommended for replicating results
|
||||||
|
* Example configuration file:
|
||||||
|
```python
|
||||||
|
|
||||||
|
# Data word size
|
||||||
|
word_size = 2
|
||||||
|
|
||||||
|
# Enable LVS/DRC checking
|
||||||
|
check_lvsdrc = True
|
||||||
|
|
||||||
|
# Path to input data. Either binary file or hex.
|
||||||
|
rom_data = "data_1kbyte.bin"
|
||||||
|
# Format type of input data
|
||||||
|
data_type = "bin"
|
||||||
|
|
||||||
|
# Technology to use in $OPENRAM_TECH, currently only sky130 is supported
|
||||||
|
tech_name = "sky130"
|
||||||
|
|
||||||
|
# Output directory for the results
|
||||||
|
output_path = "temp"
|
||||||
|
# Output file base name
|
||||||
|
output_name = "rom_1kbyte"
|
||||||
|
|
||||||
|
# Only nominal process corner generation is currently supported
|
||||||
|
nominal_corner_only = True
|
||||||
|
|
||||||
|
# Add a supply ring to the generated layout
|
||||||
|
route_supplies = "ring"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Output Files
|
||||||
|
The output files are placed in the `output_dir` defined in the configuration
|
||||||
|
file.
|
||||||
|
|
||||||
|
The base name is specified by `output_name` and suffixes are added. Currently only layout and schematic files are generated.
|
||||||
|
|
||||||
|
The final results files are:
|
||||||
|
* GDS (.gds)
|
||||||
|
* SPICE (.sp)
|
||||||
|
* Log (.log)
|
||||||
|
* Configuration (.py) for replication of creation
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
### [Go Back](./index.md#table-of-contents)
|
### [Go Back](./index.md#table-of-contents)
|
||||||
|
|
||||||
# Basic Setup
|
# Basic Setup
|
||||||
This page shows the basic setup for using OpenRAM.
|
This page shows the basic setup for using OpenRAM to generate an SRAM.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
### [Go Back](./index.md#table-of-contents)
|
### [Go Back](./index.md#table-of-contents)
|
||||||
|
|
||||||
# Basic Usage
|
# Basic Usage
|
||||||
This page of the documentation explains the basic usage of OpenRAM.
|
This page of the documentation explains the basic usage of OpenRAM's SRAM compiler. For usage of the ROM compiler see [here](./basic_rom_usage.md#go-back)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ navigate through the documentation.
|
||||||
1. [Supported Technologies](#supported-technologies)
|
1. [Supported Technologies](#supported-technologies)
|
||||||
1. [Online Playground](./OpenRAM.ipynb)
|
1. [Online Playground](./OpenRAM.ipynb)
|
||||||
1. [Basic Setup](./basic_setup.md#go-back)
|
1. [Basic Setup](./basic_setup.md#go-back)
|
||||||
1. [Basic Usage](./basic_usage.md#go-back)
|
1. [Basic SRAM Usage](./basic_usage.md#go-back)
|
||||||
|
1. [Basic ROM Usage](./basic_rom_usage.md#go-back)
|
||||||
1. [Python Library](./python_library.md#go-back)
|
1. [Python Library](./python_library.md#go-back)
|
||||||
1. [Bitcells](./bitcells.md#go-back)
|
1. [Bitcells](./bitcells.md#go-back)
|
||||||
1. [Architecture](./architecture.md#go-back)
|
1. [Architecture](./architecture.md#go-back)
|
||||||
|
|
@ -115,4 +116,5 @@ Commercial tools (optional):
|
||||||
* Tom Golubev
|
* Tom Golubev
|
||||||
* Marcelo Sero
|
* Marcelo Sero
|
||||||
* Seokjoong Kim
|
* Seokjoong Kim
|
||||||
|
* Sage Walker
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ include $(TOP_DIR)/openram.mk
|
||||||
|
|
||||||
SKY130_PDK ?= $(PDK_ROOT)/sky130A
|
SKY130_PDK ?= $(PDK_ROOT)/sky130A
|
||||||
|
|
||||||
|
OPENRAM_DIR = $(MACRO_DIR)
|
||||||
OPENRAM_OPTS := $(OPENRAM_OPTS)
|
OPENRAM_OPTS := $(OPENRAM_OPTS)
|
||||||
# Define `OPENRAM_FULL` in your environment to run a full characterize
|
# Define `OPENRAM_FULL` in your environment to run a full characterize
|
||||||
ifeq ($(OPENRAM_FULL),)
|
ifeq ($(OPENRAM_FULL),)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -10,7 +10,8 @@ word_size = 1
|
||||||
|
|
||||||
check_lvsdrc = True
|
check_lvsdrc = True
|
||||||
|
|
||||||
rom_data = "macros/rom_configs/example_1kbyte.dat"
|
rom_data = "rom_configs/example_1kbyte.bin"
|
||||||
|
data_type = "bin"
|
||||||
|
|
||||||
output_name = "rom_1kbyte"
|
output_name = "rom_1kbyte"
|
||||||
output_path = "macro/{output_name}".format(**locals())
|
output_path = "macro/{output_name}".format(**locals())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2023 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.
|
||||||
|
#
|
||||||
tech_name = "sky130"
|
tech_name = "sky130"
|
||||||
nominal_corner_only = True
|
nominal_corner_only = True
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue