mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-07 11:21:14 +02:00
Move last few modules to base dir
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import gdsMill
|
||||
import tech
|
||||
import globals
|
||||
import math
|
||||
import debug
|
||||
import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
class lef:
|
||||
"""
|
||||
SRAM LEF Class open GDS file, read pins information, obstruction
|
||||
and write them to LEF file
|
||||
"""
|
||||
def __init__(self,layers):
|
||||
# LEF db units per micron
|
||||
self.lef_units = 1000
|
||||
# These are the layers of the obstructions
|
||||
self.lef_layers = layers
|
||||
|
||||
def lef_write(self, lef_name):
|
||||
"""Write the entire lef of the object to the file."""
|
||||
debug.info(3, "Writing to {0}".format(lef_name))
|
||||
|
||||
self.indent = "" # To maintain the indent level easily
|
||||
|
||||
self.lef = open(lef_name,"w")
|
||||
self.lef_write_header()
|
||||
for pin in self.pins:
|
||||
self.lef_write_pin(pin)
|
||||
self.lef_write_obstructions()
|
||||
self.lef_write_footer()
|
||||
self.lef.close()
|
||||
|
||||
def lef_write_header(self):
|
||||
""" Header of LEF file """
|
||||
self.lef.write("VERSION 5.4 ;\n")
|
||||
self.lef.write("NAMESCASESENSITIVE ON ;\n")
|
||||
self.lef.write("BUSBITCHARS \"[]\" ;\n")
|
||||
self.lef.write("DIVIDERCHAR \"/\" ;\n")
|
||||
self.lef.write("UNITS\n")
|
||||
self.lef.write(" DATABASE MICRONS {0} ;\n".format(self.lef_units))
|
||||
self.lef.write("END UNITS\n")
|
||||
|
||||
self.lef.write("SITE MacroSite\n")
|
||||
self.indent += " "
|
||||
self.lef.write("{0}CLASS Core ;\n".format(self.indent))
|
||||
self.lef.write("{0}SIZE {1} by {2} ;\n".format(self.indent,
|
||||
self.lef_units*self.width,
|
||||
self.lef_units*self.height))
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("END MacroSite\n")
|
||||
|
||||
self.lef.write("{0}MACRO {1}\n".format(self.indent,self.name))
|
||||
self.indent += " "
|
||||
self.lef.write("{0}CLASS BLOCK ;\n".format(self.indent))
|
||||
self.lef.write("{0}SIZE {1} BY {2} ;\n" .format(self.indent,
|
||||
self.lef_units*self.width,
|
||||
self.lef_units*self.height))
|
||||
self.lef.write("{0}SYMMETRY X Y R90 ;\n".format(self.indent))
|
||||
self.lef.write("{0}SITE MacroSite ;\n".format(self.indent))
|
||||
|
||||
|
||||
def lef_write_footer(self):
|
||||
self.lef.write("{0}END {1}\n".format(self.indent,self.name))
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("END LIBRARY\n")
|
||||
|
||||
|
||||
def lef_write_pin(self, name):
|
||||
pin_dir = self.get_pin_dir(name)
|
||||
pin_type = self.get_pin_type(name)
|
||||
self.lef.write("{0}PIN {1}\n".format(self.indent,name))
|
||||
self.indent += " "
|
||||
|
||||
self.lef.write("{0}DIRECTION {1} ;\n".format(self.indent,pin_dir))
|
||||
|
||||
if pin_type in ["POWER","GROUND"]:
|
||||
self.lef.write("{0}USE {1} ; \n".format(self.indent,pin_type))
|
||||
self.lef.write("{0}SHAPE ABUTMENT ; \n".format(self.indent))
|
||||
|
||||
self.lef.write("{0}PORT\n".format(self.indent))
|
||||
self.indent += " "
|
||||
|
||||
# We could sort these together to minimize different layer sections, but meh.
|
||||
pin_list = self.get_pins(name)
|
||||
for pin in pin_list:
|
||||
self.lef.write("{0}LAYER {1} ;\n".format(self.indent,pin.layer))
|
||||
self.lef_write_rect(pin.rect)
|
||||
|
||||
# End the PORT
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("{0}END\n".format(self.indent))
|
||||
|
||||
# End the PIN
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("{0}END {1}\n".format(self.indent,name))
|
||||
|
||||
def lef_write_obstructions(self):
|
||||
""" Write all the obstructions on each layer """
|
||||
self.lef.write("{0}OBS\n".format(self.indent))
|
||||
for layer in self.lef_layers:
|
||||
self.lef.write("{0}LAYER {1} ;\n".format(self.indent,layer))
|
||||
self.indent += " "
|
||||
blockages = self.get_blockages(layer,True)
|
||||
for b in blockages:
|
||||
self.lef_write_rect(b)
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("{0}END\n".format(self.indent))
|
||||
|
||||
def lef_write_rect(self, rect):
|
||||
""" Write a LEF rectangle """
|
||||
self.lef.write("{0}RECT ".format(self.indent))
|
||||
for item in rect:
|
||||
self.lef.write(" {0} {1}".format(self.lef_units*item[0], self.lef_units*item[1]))
|
||||
self.lef.write(" ;\n")
|
||||
@@ -0,0 +1,120 @@
|
||||
from tech import drc
|
||||
import debug
|
||||
from contact import contact
|
||||
from itertools import tee
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
|
||||
class route():
|
||||
"""
|
||||
Object route (used by the router module)
|
||||
Add a route of minimium metal width between a set of points.
|
||||
The wire must be completely rectilinear and the
|
||||
z-dimension of the points refers to the layers (plus via)
|
||||
The points are the center of the wire.
|
||||
This can have non-preferred direction routing.
|
||||
"""
|
||||
def __init__(self, obj, layer_stack, path):
|
||||
name = "route_{0}".format(route.unique_route_id)
|
||||
route.unique_route_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(3, "create route obj {0}".format(name))
|
||||
|
||||
self.obj = obj
|
||||
self.layer_stack = layer_stack
|
||||
self.path = path
|
||||
|
||||
self.setup_layers()
|
||||
self.create_wires()
|
||||
|
||||
|
||||
def setup_layers(self):
|
||||
(horiz_layer, via_layer, vert_layer) = self.layer_stack
|
||||
self.via_layer_name = via_layer
|
||||
|
||||
self.vert_layer_name = vert_layer
|
||||
self.vert_layer_width = drc["minwidth_{0}".format(vert_layer)]
|
||||
|
||||
self.horiz_layer_name = horiz_layer
|
||||
self.horiz_layer_width = drc["minwidth_{0}".format(horiz_layer)]
|
||||
# offset this by 1/2 the via size
|
||||
self.c=contact(self.layer_stack, (1, 1))
|
||||
|
||||
|
||||
def create_wires(self):
|
||||
"""
|
||||
Add the wire segments of the route.
|
||||
"""
|
||||
|
||||
def pairwise(iterable):
|
||||
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip(a, b)
|
||||
|
||||
plist = pairwise(self.path)
|
||||
for p0,p1 in plist:
|
||||
if p0.z != p1.z: # via
|
||||
# offset if not rotated
|
||||
#via_offset = vector(p0.x+0.5*self.c.width,p0.y+0.5*self.c.height)
|
||||
# offset if rotated
|
||||
via_offset = vector(p0.x+0.5*self.c.height,p0.y-0.5*self.c.width)
|
||||
self.obj.add_via(self.layer_stack,via_offset,rotate=90)
|
||||
elif p0.x != p1.x and p0.y != p1.y: # diagonal!
|
||||
debug.error("Non-changing direction!")
|
||||
else:
|
||||
# this will draw an extra corner at the end but that is ok
|
||||
self.draw_corner_wire(p1)
|
||||
# draw the point to point wire
|
||||
self.draw_wire(p0,p1)
|
||||
|
||||
|
||||
|
||||
def draw_wire(self, p0, p1):
|
||||
"""
|
||||
This draws a straight wire with layer_minwidth
|
||||
"""
|
||||
layer_name = self.layer_stack[2*p0.z]
|
||||
layer_width = drc["minwidth_{0}".format(layer_name)]
|
||||
|
||||
# always route left to right or bottom to top
|
||||
if p0.z != p1.z:
|
||||
self.error("Adding a via as a wire!")
|
||||
elif p0.x < p1.x or p0.y < p1.y:
|
||||
start = p0
|
||||
end = p1
|
||||
elif p0.x > p1.x or p0.y > p1.y:
|
||||
start = p1
|
||||
end = p0
|
||||
else:
|
||||
debug.error("Neither horizontal or vertical wire.")
|
||||
|
||||
# now determine the route geometry and offset
|
||||
if start.x != end.x: # horizontal
|
||||
offset = start + vector3d(0,-0.5*layer_width,0)
|
||||
height = layer_width
|
||||
width = end.x - start.x
|
||||
elif start.y != end.y: # vertical
|
||||
offset = start + vector3d(-0.5*layer_width,0,0)
|
||||
height = end.y - start.y
|
||||
width = layer_width
|
||||
|
||||
deisgn.add_rect(layer=layer_name,
|
||||
offset=offset,
|
||||
width=width,
|
||||
height=height)
|
||||
|
||||
|
||||
def draw_corner_wire(self, p0):
|
||||
""" This function adds the corner squares since the center
|
||||
line convention only draws to the center of the corner."""
|
||||
|
||||
layer_name = self.layer_stack[2*p0.z]
|
||||
layer_width = drc["minwidth_{0}".format(layer_name)]
|
||||
offset = vector(p0.x-0.5*layer_width,p0.y-0.5*layer_width)
|
||||
self.obj.add_rect(layer=layer_name,
|
||||
offset=offset,
|
||||
width=layer_width,
|
||||
height=layer_width)
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import debug
|
||||
|
||||
class verilog:
|
||||
""" Create a behavioral Verilog file for simulation."""
|
||||
|
||||
def verilog_write(self,verilog_name):
|
||||
""" Write a behavioral Verilog model. """
|
||||
|
||||
self.vf = open(verilog_name, "w")
|
||||
|
||||
self.vf.write("// OpenRAM SRAM model\n")
|
||||
self.vf.write("// Words: {0}\n".format(self.num_words))
|
||||
self.vf.write("// Word size: {0}\n\n".format(self.word_size))
|
||||
|
||||
self.vf.write("module {0}(DATA,ADDR,CSb,WEb,OEb,clk);\n".format(self.name))
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size))
|
||||
self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size))
|
||||
self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n")
|
||||
self.vf.write(" parameter DELAY = 3 ;\n")
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" inout [DATA_WIDTH-1:0] DATA;\n")
|
||||
self.vf.write(" input [ADDR_WIDTH-1:0] ADDR;\n")
|
||||
self.vf.write(" input CSb; // active low chip select\n")
|
||||
self.vf.write(" input WEb; // active low write control\n")
|
||||
self.vf.write(" input OEb; // active output enable\n")
|
||||
self.vf.write(" input clk; // clock\n")
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" reg [DATA_WIDTH-1:0] data_out ;\n")
|
||||
self.vf.write(" reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];\n")
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" // Tri-State Buffer control\n")
|
||||
self.vf.write(" // output : When WEb = 1, oeb = 0, csb = 0\n")
|
||||
self.vf.write(" assign DATA = (!CSb && !OEb && WEb) ? data_out : {0}'bz;\n".format(self.word_size))
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" // Memory Write Block\n")
|
||||
self.vf.write(" // Write Operation : When WEb = 0, CSb = 0\n")
|
||||
self.vf.write(" always @ (posedge clk)\n")
|
||||
self.vf.write(" begin : MEM_WRITE\n")
|
||||
self.vf.write(" if ( !CSb && !WEb ) begin\n")
|
||||
self.vf.write(" mem[ADDR] = DATA;\n")
|
||||
self.vf.write(" $display($time,\" Writing %m ABUS=%b DATA=%b\",ADDR,DATA);\n")
|
||||
self.vf.write(" end\n")
|
||||
self.vf.write(" end\n\n")
|
||||
self.vf.write("\n")
|
||||
self.vf.write(" // Memory Read Block\n")
|
||||
self.vf.write(" // Read Operation : When WEb = 1, CSb = 0\n")
|
||||
self.vf.write(" always @ (posedge clk)\n")
|
||||
self.vf.write(" begin : MEM_READ\n")
|
||||
self.vf.write(" if (!CSb && WEb) begin\n")
|
||||
self.vf.write(" data_out <= #(DELAY) mem[ADDR];\n")
|
||||
self.vf.write(" $display($time,\" Reading %m ABUS=%b DATA=%b\",ADDR,mem[ADDR]);\n")
|
||||
self.vf.write(" end\n")
|
||||
self.vf.write(" end\n")
|
||||
self.vf.write("\n")
|
||||
self.vf.write("endmodule\n")
|
||||
|
||||
|
||||
self.vf.close()
|
||||
|
||||
Reference in New Issue
Block a user