mirror of https://github.com/VLSIDA/OpenRAM.git
All control routed and DRC clean. LVS errors.
This commit is contained in:
parent
5d59863efc
commit
c43a140b5e
|
|
@ -86,7 +86,7 @@ class bank(design.design):
|
||||||
for port in self.read_ports:
|
for port in self.read_ports:
|
||||||
self.add_pin("s_en{0}".format(port), "INPUT")
|
self.add_pin("s_en{0}".format(port), "INPUT")
|
||||||
for port in self.read_ports:
|
for port in self.read_ports:
|
||||||
self.add_pin("p_en{0}".format(port), "INPUT")
|
self.add_pin("p_en_bar{0}".format(port), "INPUT")
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
self.add_pin("w_en{0}".format(port), "INPUT")
|
self.add_pin("w_en{0}".format(port), "INPUT")
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
|
|
@ -356,13 +356,13 @@ class bank(design.design):
|
||||||
self.input_control_signals = []
|
self.input_control_signals = []
|
||||||
port_num = 0
|
port_num = 0
|
||||||
for port in range(OPTS.num_rw_ports):
|
for port in range(OPTS.num_rw_ports):
|
||||||
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en{}".format(port_num)])
|
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)])
|
||||||
port_num += 1
|
port_num += 1
|
||||||
for port in range(OPTS.num_w_ports):
|
for port in range(OPTS.num_w_ports):
|
||||||
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "w_en{}".format(port_num)])
|
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "w_en{}".format(port_num)])
|
||||||
port_num += 1
|
port_num += 1
|
||||||
for port in range(OPTS.num_r_ports):
|
for port in range(OPTS.num_r_ports):
|
||||||
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en{}".format(port_num)])
|
self.input_control_signals.append(["clk_buf{}".format(port_num), "wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)])
|
||||||
port_num += 1
|
port_num += 1
|
||||||
|
|
||||||
# These will be outputs of the gaters if this is multibank, if not, normal signals.
|
# These will be outputs of the gaters if this is multibank, if not, normal signals.
|
||||||
|
|
@ -490,7 +490,7 @@ class bank(design.design):
|
||||||
for i in range(self.num_cols):
|
for i in range(self.num_cols):
|
||||||
temp.append(self.bl_names[port]+"_{0}".format(i))
|
temp.append(self.bl_names[port]+"_{0}".format(i))
|
||||||
temp.append(self.br_names[port]+"_{0}".format(i))
|
temp.append(self.br_names[port]+"_{0}".format(i))
|
||||||
temp.extend([self.prefix+"p_en{0}".format(port), "vdd"])
|
temp.extend([self.prefix+"p_en_bar{0}".format(port), "vdd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -775,14 +775,14 @@ class bank(design.design):
|
||||||
""" Route the bank select logic. """
|
""" Route the bank select logic. """
|
||||||
|
|
||||||
if self.port_id[port] == "rw":
|
if self.port_id[port] == "rw":
|
||||||
bank_sel_signals = ["clk_buf", "w_en", "s_en", "p_en", "bank_sel"]
|
bank_sel_signals = ["clk_buf", "w_en", "s_en", "p_en_bar", "bank_sel"]
|
||||||
gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en", "gated_s_en", "gated_p_en"]
|
gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en", "gated_s_en", "gated_p_en_bar"]
|
||||||
elif self.port_id[port] == "w":
|
elif self.port_id[port] == "w":
|
||||||
bank_sel_signals = ["clk_buf", "w_en", "bank_sel"]
|
bank_sel_signals = ["clk_buf", "w_en", "bank_sel"]
|
||||||
gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en"]
|
gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en"]
|
||||||
else:
|
else:
|
||||||
bank_sel_signals = ["clk_buf", "s_en", "p_en", "bank_sel"]
|
bank_sel_signals = ["clk_buf", "s_en", "p_en_bar", "bank_sel"]
|
||||||
gated_bank_sel_signals = ["gated_clk_buf", "gated_s_en", "gated_p_en"]
|
gated_bank_sel_signals = ["gated_clk_buf", "gated_s_en", "gated_p_en_bar"]
|
||||||
|
|
||||||
copy_control_signals = self.input_control_signals[port]+["bank_sel{}".format(port)]
|
copy_control_signals = self.input_control_signals[port]+["bank_sel{}".format(port)]
|
||||||
for signal in range(len(copy_control_signals)):
|
for signal in range(len(copy_control_signals)):
|
||||||
|
|
@ -1226,7 +1226,7 @@ class bank(design.design):
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
# clk to wordline_driver
|
# clk to wordline_driver
|
||||||
control_signal = self.prefix+"p_en{}".format(port)
|
control_signal = self.prefix+"p_en_bar{}".format(port)
|
||||||
pin_pos = self.wordline_driver_inst[port].get_pin("en").bc()
|
pin_pos = self.wordline_driver_inst[port].get_pin("en").bc()
|
||||||
mid_pos = pin_pos - vector(0,self.m1_pitch)
|
mid_pos = pin_pos - vector(0,self.m1_pitch)
|
||||||
control_x_offset = self.bus_xoffset[port][control_signal].x
|
control_x_offset = self.bus_xoffset[port][control_signal].x
|
||||||
|
|
|
||||||
|
|
@ -135,9 +135,9 @@ class control_logic(design.design):
|
||||||
|
|
||||||
# list of output control signals (for making a vertical bus)
|
# list of output control signals (for making a vertical bus)
|
||||||
if self.port_type == "rw":
|
if self.port_type == "rw":
|
||||||
self.internal_bus_list = ["clk_buf", "gated_clk", "we", "we_bar", "cs"]
|
self.internal_bus_list = ["clk_buf", "gated_clk_bar", "gated_clk_buf", "we", "we_bar", "cs"]
|
||||||
else:
|
else:
|
||||||
self.internal_bus_list = ["clk_buf", "gated_clk", "cs"]
|
self.internal_bus_list = ["clk_buf", "gated_clk_bar", "gated_clk_buf", "cs"]
|
||||||
# leave space for the bus plus one extra space
|
# leave space for the bus plus one extra space
|
||||||
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
|
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
|
||||||
|
|
||||||
|
|
@ -165,12 +165,15 @@ class control_logic(design.design):
|
||||||
def create_instances(self):
|
def create_instances(self):
|
||||||
""" Create all the instances """
|
""" Create all the instances """
|
||||||
self.create_dffs()
|
self.create_dffs()
|
||||||
self.create_clk_rows()
|
self.create_clk_buf_row()
|
||||||
|
self.create_gated_clk_bar_row()
|
||||||
|
self.create_gated_clk_buf_row()
|
||||||
self.create_wlen_row()
|
self.create_wlen_row()
|
||||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||||
self.create_wen_row()
|
self.create_wen_row()
|
||||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||||
self.create_pen_row()
|
self.create_rbl_in_row()
|
||||||
|
self.create_pen_row()
|
||||||
self.create_sen_row()
|
self.create_sen_row()
|
||||||
self.create_rbl()
|
self.create_rbl()
|
||||||
|
|
||||||
|
|
@ -184,20 +187,27 @@ class control_logic(design.design):
|
||||||
# Add the control flops on the left of the bus
|
# Add the control flops on the left of the bus
|
||||||
self.place_dffs()
|
self.place_dffs()
|
||||||
|
|
||||||
|
# All of the control logic is placed to the right of the DFFs and bus
|
||||||
|
self.control_x_offset = self.ctrl_dff_array.width + self.internal_bus_width
|
||||||
|
|
||||||
row = 0
|
row = 0
|
||||||
# Add the logic on the right of the bus
|
# Add the logic on the right of the bus
|
||||||
self.place_clkbuf_row(row)
|
self.place_clk_buf_row(row)
|
||||||
row += 1
|
row += 1
|
||||||
self.place_gated_clk_row(row)
|
self.place_gated_clk_bar_row(row)
|
||||||
|
row += 1
|
||||||
|
self.place_gated_clk_buf_row(row)
|
||||||
row += 1
|
row += 1
|
||||||
self.place_wlen_row(row)
|
self.place_wlen_row(row)
|
||||||
row += 1
|
row += 1
|
||||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||||
self.place_we_row(row)
|
self.place_wen_row(row)
|
||||||
height = self.w_en_inst.uy()
|
height = self.w_en_inst.uy()
|
||||||
control_center_y = self.w_en_inst.uy()
|
control_center_y = self.w_en_inst.uy()
|
||||||
row += 1
|
row += 1
|
||||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||||
|
self.place_rbl_in_row(row)
|
||||||
|
row += 1
|
||||||
self.place_pen_row(row)
|
self.place_pen_row(row)
|
||||||
row += 1
|
row += 1
|
||||||
self.place_sen_row(row)
|
self.place_sen_row(row)
|
||||||
|
|
@ -212,10 +222,10 @@ class control_logic(design.design):
|
||||||
# Extra pitch on top and right
|
# Extra pitch on top and right
|
||||||
self.height = height + 2*self.m1_pitch
|
self.height = height + 2*self.m1_pitch
|
||||||
# Max of modules or logic rows
|
# Max of modules or logic rows
|
||||||
|
self.width = max([inst.rx() for inst in self.row_end_inst])
|
||||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||||
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
|
self.width = max(self.rbl_inst.rx() , self.width)
|
||||||
else:
|
self.width += self.m2_pitch
|
||||||
self.width = max([inst.rx() for inst in self.row_end_inst]) + self.m2_pitch
|
|
||||||
|
|
||||||
def route_all(self):
|
def route_all(self):
|
||||||
""" Routing between modules """
|
""" Routing between modules """
|
||||||
|
|
@ -225,9 +235,12 @@ class control_logic(design.design):
|
||||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||||
self.route_wen()
|
self.route_wen()
|
||||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||||
self.route_rbl()
|
self.route_rbl_in()
|
||||||
|
self.route_pen()
|
||||||
self.route_sen()
|
self.route_sen()
|
||||||
self.route_clk()
|
self.route_clk_buf()
|
||||||
|
self.route_gated_clk_bar()
|
||||||
|
self.route_gated_clk_buf()
|
||||||
self.route_supply()
|
self.route_supply()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -243,85 +256,191 @@ class control_logic(design.design):
|
||||||
|
|
||||||
# Add the RBL above the rows
|
# Add the RBL above the rows
|
||||||
# Add to the right of the control rows and routing channel
|
# Add to the right of the control rows and routing channel
|
||||||
self.replica_bitline_offset = vector(0, y_off)
|
offset = vector(0, y_off)
|
||||||
self.rbl_inst.place(self.replica_bitline_offset)
|
self.rbl_inst.place(offset)
|
||||||
|
|
||||||
|
|
||||||
def create_clk_rows(self):
|
def create_clk_buf_row(self):
|
||||||
""" Create the multistage and gated clock buffer """
|
""" Create the multistage and gated clock buffer """
|
||||||
self.clkbuf_inst = self.add_inst(name="clkbuf",
|
self.clkbuf_inst = self.add_inst(name="clkbuf",
|
||||||
mod=self.clkbuf)
|
mod=self.clkbuf)
|
||||||
self.connect_inst(["clk","clk_buf","vdd","gnd"])
|
self.connect_inst(["clk","clk_buf","vdd","gnd"])
|
||||||
|
|
||||||
|
|
||||||
|
def place_clk_buf_row(self,row):
|
||||||
|
""" Place the multistage clock buffer below the control flops """
|
||||||
|
x_off = self.control_x_offset
|
||||||
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off,y_off)
|
||||||
|
self.clkbuf_inst.place(offset, mirror)
|
||||||
|
|
||||||
|
self.row_end_inst.append(self.clkbuf_inst)
|
||||||
|
|
||||||
|
def route_clk_buf(self):
|
||||||
|
clk_pin = self.clkbuf_inst.get_pin("A")
|
||||||
|
self.add_layout_pin_segment_center(text="clk",
|
||||||
|
layer="metal2",
|
||||||
|
start=clk_pin.bc(),
|
||||||
|
end=clk_pin.bc().scale(1,0))
|
||||||
|
|
||||||
|
clkbuf_map = zip(["Z"], ["clk_buf"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.clkbuf_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
||||||
|
|
||||||
|
self.connect_output(self.clkbuf_inst, "Z", "clk_buf")
|
||||||
|
|
||||||
|
def create_gated_clk_bar_row(self):
|
||||||
self.clk_bar_inst = self.add_inst(name="clk_bar",
|
self.clk_bar_inst = self.add_inst(name="clk_bar",
|
||||||
mod=self.inv)
|
mod=self.inv)
|
||||||
self.connect_inst(["clk_buf","clk_bar","vdd","gnd"])
|
self.connect_inst(["clk_buf","clk_bar","vdd","gnd"])
|
||||||
self.gated_clk_inst = self.add_inst(name="gated_clkbuf",
|
|
||||||
mod=self.and2)
|
|
||||||
self.connect_inst(["cs","clk_bar","gated_clk","vdd","gnd"])
|
|
||||||
|
|
||||||
def place_clkbuf_row(self,row):
|
|
||||||
""" Place the multistage clock buffer below the control flops """
|
|
||||||
x_off = self.ctrl_dff_array.width + self.internal_bus_width
|
|
||||||
(y_off,mirror)=self.get_offset(row)
|
|
||||||
offset = vector(x_off,y_off)
|
|
||||||
self.clkbuf_inst.place(offset)
|
|
||||||
self.row_end_inst.append(self.clkbuf_inst)
|
|
||||||
|
|
||||||
def place_gated_clk_row(self,row):
|
|
||||||
""" Place the gated clk logic below the control flops """
|
|
||||||
x_off = self.ctrl_dff_array.width + self.internal_bus_width
|
|
||||||
(y_off,mirror)=self.get_offset(row)
|
|
||||||
offset = vector(x_off,y_off)
|
|
||||||
|
|
||||||
self.clk_bar_inst.place(offset)
|
self.gated_clk_bar_inst = self.add_inst(name="gated_clkbuf",
|
||||||
|
mod=self.and2)
|
||||||
|
self.connect_inst(["cs","clk_bar","gated_clk_bar","vdd","gnd"])
|
||||||
|
|
||||||
|
def place_gated_clk_bar_row(self,row):
|
||||||
|
""" Place the gated clk logic below the control flops """
|
||||||
|
x_off = self.control_x_offset
|
||||||
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off,y_off)
|
||||||
|
self.clk_bar_inst.place(offset, mirror)
|
||||||
|
|
||||||
x_off += self.inv.width
|
x_off += self.inv.width
|
||||||
|
|
||||||
offset = vector(x_off,y_off)
|
offset = vector(x_off,y_off)
|
||||||
self.gated_clk_inst.place(offset)
|
self.gated_clk_bar_inst.place(offset, mirror)
|
||||||
self.row_end_inst.append(self.gated_clk_inst)
|
|
||||||
|
|
||||||
def create_wlen_row(self):
|
|
||||||
# input pre_p_en, output: wl_en
|
|
||||||
self.p_en_inst=self.add_inst(name="buf_wl_en",
|
|
||||||
mod=self.buf16)
|
|
||||||
self.connect_inst(["gated_clk", "wl_en", "vdd", "gnd"])
|
|
||||||
|
|
||||||
|
self.row_end_inst.append(self.gated_clk_bar_inst)
|
||||||
|
|
||||||
def place_wlen_row(self, row):
|
def route_gated_clk_bar(self):
|
||||||
x_off = self.ctrl_dff_array.width + self.internal_bus_width
|
out_pos = self.clk_bar_inst.get_pin("Z").center()
|
||||||
|
in_pos = self.gated_clk_bar_inst.get_pin("B").center()
|
||||||
|
mid1 = vector(in_pos.x,out_pos.y)
|
||||||
|
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1, in_pos])
|
||||||
|
|
||||||
|
clkbuf_map = zip(["A"], ["cs"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
clkbuf_map = zip(["A"], ["clk_buf"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
clkbuf_map = zip(["Z"], ["gated_clk_bar"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
||||||
|
|
||||||
|
def create_gated_clk_buf_row(self):
|
||||||
|
self.gated_clk_buf_inst = self.add_inst(name="gated_clkinv",
|
||||||
|
mod=self.and2)
|
||||||
|
self.connect_inst(["cs","clk_buf","gated_clk_buf","vdd","gnd"])
|
||||||
|
|
||||||
|
def place_gated_clk_buf_row(self,row):
|
||||||
|
""" Place the gated clk logic below the control flops """
|
||||||
|
x_off = self.control_x_offset
|
||||||
(y_off,mirror)=self.get_offset(row)
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
self.wl_en_offset = vector(x_off, y_off)
|
offset = vector(x_off,y_off)
|
||||||
self.wl_en_inst.place(offset=self.wl_en_offset,
|
self.gated_clk_buf_inst.place(offset, mirror)
|
||||||
mirror=mirror)
|
|
||||||
|
self.row_end_inst.append(self.gated_clk_buf_inst)
|
||||||
|
|
||||||
|
def route_gated_clk_buf(self):
|
||||||
|
clkbuf_map = zip(["A", "B"], ["clk_buf", "we_bar"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
|
||||||
|
clkbuf_map = zip(["Z"], ["gated_clk_buf"])
|
||||||
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
||||||
|
|
||||||
|
def create_wlen_row(self):
|
||||||
|
# input pre_p_en, output: wl_en
|
||||||
|
self.wl_en_inst=self.add_inst(name="buf_wl_en",
|
||||||
|
mod=self.buf16)
|
||||||
|
self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"])
|
||||||
|
|
||||||
|
def place_wlen_row(self, row):
|
||||||
|
x_off = self.control_x_offset
|
||||||
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off, y_off)
|
||||||
|
self.wl_en_inst.place(offset, mirror)
|
||||||
|
|
||||||
self.row_end_inst.append(self.wl_en_inst)
|
self.row_end_inst.append(self.wl_en_inst)
|
||||||
|
|
||||||
|
def route_wlen(self):
|
||||||
|
wlen_map = zip(["A"], ["gated_clk_bar"])
|
||||||
|
self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets)
|
||||||
|
self.connect_output(self.wl_en_inst, "Z", "wl_en")
|
||||||
|
|
||||||
|
def create_rbl_in_row(self):
|
||||||
|
# input: gated_clk_bar, we_bar, output: rbl_in
|
||||||
|
self.rbl_in_inst=self.add_inst(name="and2_rbl_in",
|
||||||
|
mod=self.and2)
|
||||||
|
self.connect_inst(["gated_clk_bar", "we_bar", "rbl_in", "vdd", "gnd"])
|
||||||
|
|
||||||
|
def place_rbl_in_row(self,row):
|
||||||
|
x_off = self.control_x_offset
|
||||||
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off, y_off)
|
||||||
|
self.rbl_in_inst.place(offset, mirror)
|
||||||
|
|
||||||
|
self.row_end_inst.append(self.rbl_in_inst)
|
||||||
|
|
||||||
|
def route_rbl_in(self):
|
||||||
|
""" Connect the logic for the rbl_in generation """
|
||||||
|
|
||||||
|
# Connect the NAND gate inputs to the bus
|
||||||
|
rbl_in_map = zip(["A", "B"], ["gated_clk_bar", "we_bar"])
|
||||||
|
self.connect_vertical_bus(rbl_in_map, self.rbl_in_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
# Connect the output of the precharge enable to the RBL input
|
||||||
|
out_pos = self.rbl_in_inst.get_pin("Z").center()
|
||||||
|
in_pos = self.rbl_inst.get_pin("en").center()
|
||||||
|
mid1 = vector(in_pos.x,out_pos.y)
|
||||||
|
self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, in_pos])
|
||||||
|
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||||
|
offset=out_pos,
|
||||||
|
rotate=90)
|
||||||
|
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||||
|
offset=out_pos,
|
||||||
|
rotate=90)
|
||||||
|
|
||||||
def create_pen_row(self):
|
def create_pen_row(self):
|
||||||
# input: gated_clk, we_bar, output: pre_p_en
|
# input: gated_clk_bar, we_bar, output: pre_p_en
|
||||||
self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en",
|
self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en",
|
||||||
mod=self.and2)
|
mod=self.and2)
|
||||||
self.connect_inst(["gated_clk", "we_bar", "pre_p_en", "vdd", "gnd"])
|
self.connect_inst(["gated_clk_buf", "we_bar", "pre_p_en", "vdd", "gnd"])
|
||||||
|
|
||||||
|
|
||||||
# input: pre_p_en, output: p_en_bar
|
# input: pre_p_en, output: p_en_bar
|
||||||
self.p_en_inst=self.add_inst(name="inv_p_en_bar",
|
self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar",
|
||||||
mod=self.inv8)
|
mod=self.inv8)
|
||||||
self.connect_inst(["pre_p_en", "p_en_bar", "vdd", "gnd"])
|
self.connect_inst(["pre_p_en", "p_en_bar", "vdd", "gnd"])
|
||||||
|
|
||||||
|
|
||||||
def place_pen_row(self,row):
|
def place_pen_row(self,row):
|
||||||
x_off = self.ctrl_dff_array.width + self.internal_bus_width
|
x_off = self.control_x_offset
|
||||||
(y_off,mirror)=self.get_offset(row)
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off, y_off)
|
||||||
|
self.pre_p_en_inst.place(offset, mirror)
|
||||||
|
|
||||||
self.pre_p_en_offset = vector(x_off, y_off)
|
x_off += self.and2.width
|
||||||
self.pre_p_en_inst.place(offset=self.pre_p_en_offset,
|
|
||||||
mirror=mirror)
|
offset = vector(x_off,y_off)
|
||||||
|
self.p_en_bar_inst.place(offset, mirror)
|
||||||
|
|
||||||
self.row_end_inst.append(self.pre_p_en_inst)
|
self.row_end_inst.append(self.pre_p_en_inst)
|
||||||
|
|
||||||
|
def route_pen(self):
|
||||||
|
# Connect the NAND gate inputs to the bus
|
||||||
|
pre_p_en_in_map = zip(["A", "B"], ["gated_clk_buf", "we_bar"])
|
||||||
|
self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
out_pos = self.pre_p_en_inst.get_pin("Z").center()
|
||||||
|
in_pos = self.p_en_bar_inst.get_pin("A").lc()
|
||||||
|
mid1 = vector(out_pos.x,in_pos.y)
|
||||||
|
self.add_wire(("metal1","via1","metal2"),[out_pos,mid1,in_pos])
|
||||||
|
|
||||||
|
self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar")
|
||||||
|
|
||||||
def create_sen_row(self):
|
def create_sen_row(self):
|
||||||
""" Create the sense enable buffer. """
|
""" Create the sense enable buffer. """
|
||||||
|
|
@ -336,14 +455,69 @@ class control_logic(design.design):
|
||||||
The sense enable buffer gets placed to the far right of the
|
The sense enable buffer gets placed to the far right of the
|
||||||
row.
|
row.
|
||||||
"""
|
"""
|
||||||
x_off = self.ctrl_dff_array.width + self.internal_bus_width
|
x_off = self.control_x_offset
|
||||||
(y_off,mirror)=self.get_offset(row)
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
self.s_en_offset = vector(x_off, y_off)
|
offset = vector(x_off, y_off)
|
||||||
self.s_en_inst.place(offset=self.s_en_offset,
|
self.s_en_inst.place(offset, mirror)
|
||||||
mirror=mirror)
|
|
||||||
self.row_end_inst.append(self.s_en_inst)
|
|
||||||
|
|
||||||
|
self.row_end_inst.append(self.s_en_inst)
|
||||||
|
|
||||||
|
|
||||||
|
def route_sen(self):
|
||||||
|
|
||||||
|
out_pos = self.rbl_inst.get_pin("out").bc()
|
||||||
|
in_pos = self.s_en_inst.get_pin("A").lc()
|
||||||
|
mid1 = vector(out_pos.x,in_pos.y)
|
||||||
|
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos])
|
||||||
|
|
||||||
|
self.connect_output(self.s_en_inst, "Z", "s_en")
|
||||||
|
|
||||||
|
|
||||||
|
def create_wen_row(self):
|
||||||
|
# input: we (or cs) output: w_en
|
||||||
|
if self.port_type == "rw":
|
||||||
|
input_name = "we"
|
||||||
|
else:
|
||||||
|
# No we for write-only reports, so use cs
|
||||||
|
input_name = "cs"
|
||||||
|
|
||||||
|
# BUFFER FOR W_EN
|
||||||
|
self.w_en_inst = self.add_inst(name="buf_w_en_buf",
|
||||||
|
mod=self.buf8)
|
||||||
|
self.connect_inst([input_name, "w_en", "vdd", "gnd"])
|
||||||
|
|
||||||
|
|
||||||
|
def place_wen_row(self,row):
|
||||||
|
x_off = self.ctrl_dff_inst.width + self.internal_bus_width
|
||||||
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
|
offset = vector(x_off, y_off)
|
||||||
|
self.w_en_inst.place(offset, mirror)
|
||||||
|
|
||||||
|
self.row_end_inst.append(self.w_en_inst)
|
||||||
|
|
||||||
|
def route_wen(self):
|
||||||
|
|
||||||
|
if self.port_type == "rw":
|
||||||
|
input_name = "we"
|
||||||
|
else:
|
||||||
|
input_name = "cs"
|
||||||
|
|
||||||
|
wen_map = zip(["A"], [input_name])
|
||||||
|
self.connect_vertical_bus(wen_map, self.w_en_inst, self.rail_offsets)
|
||||||
|
|
||||||
|
self.connect_output(self.w_en_inst, "Z", "w_en")
|
||||||
|
|
||||||
|
def create_dffs(self):
|
||||||
|
""" Add the three input DFFs (with inverters) """
|
||||||
|
self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs",
|
||||||
|
mod=self.ctrl_dff_array)
|
||||||
|
self.connect_inst(self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list)
|
||||||
|
|
||||||
|
def place_dffs(self):
|
||||||
|
""" Place the input DFFs (with inverters) """
|
||||||
|
self.ctrl_dff_inst.place(vector(0,0))
|
||||||
|
|
||||||
def route_dffs(self):
|
def route_dffs(self):
|
||||||
""" Route the input inverters """
|
""" Route the input inverters """
|
||||||
|
|
@ -368,18 +542,8 @@ class control_logic(design.design):
|
||||||
if (self.port_type == "rw"):
|
if (self.port_type == "rw"):
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst, "din_1", "web")
|
self.copy_layout_pin(self.ctrl_dff_inst, "din_1", "web")
|
||||||
|
|
||||||
|
|
||||||
def create_dffs(self):
|
|
||||||
""" Add the three input DFFs (with inverters) """
|
|
||||||
self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs",
|
|
||||||
mod=self.ctrl_dff_array)
|
|
||||||
self.connect_inst(self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list)
|
|
||||||
|
|
||||||
def place_dffs(self):
|
|
||||||
""" Place the input DFFs (with inverters) """
|
|
||||||
self.ctrl_dff_inst.place(vector(0,0))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_offset(self,row):
|
def get_offset(self,row):
|
||||||
""" Compute the y-offset and mirroring """
|
""" Compute the y-offset and mirroring """
|
||||||
y_off = row*self.and2.height
|
y_off = row*self.and2.height
|
||||||
|
|
@ -391,55 +555,8 @@ class control_logic(design.design):
|
||||||
|
|
||||||
return (y_off,mirror)
|
return (y_off,mirror)
|
||||||
|
|
||||||
def create_wen_row(self):
|
|
||||||
# input: we (or cs) output: w_en
|
|
||||||
if self.port_type == "rw":
|
|
||||||
input_name = "we"
|
|
||||||
else:
|
|
||||||
# No we for write-only reports, so use cs
|
|
||||||
input_name = "cs"
|
|
||||||
|
|
||||||
# BUFFER FOR W_EN
|
|
||||||
self.w_en_inst = self.add_inst(name="buf_w_en_buf",
|
|
||||||
mod=self.buf8)
|
|
||||||
self.connect_inst(["we", "w_en", "vdd", "gnd"])
|
|
||||||
|
|
||||||
|
|
||||||
def place_wen_row(self,row):
|
|
||||||
x_off = self.ctrl_dff_inst.width + self.internal_bus_width
|
|
||||||
(y_off,mirror)=self.get_offset(row)
|
|
||||||
|
|
||||||
if self.port_type == "rw":
|
|
||||||
pre_w_en_offset = vector(x_off, y_off)
|
|
||||||
self.pre_w_en_inst.place(offset=pre_w_en_offset,
|
|
||||||
mirror=mirror)
|
|
||||||
x_off += self.and2.width
|
|
||||||
|
|
||||||
w_en_offset = vector(x_off, y_off)
|
|
||||||
self.w_en_inst.place(offset=w_en_offset,
|
|
||||||
mirror=mirror)
|
|
||||||
|
|
||||||
self.row_end_inst.append(self.w_en_inst)
|
|
||||||
|
|
||||||
|
|
||||||
def route_rbl(self):
|
|
||||||
""" Connect the logic for the rbl_in generation """
|
|
||||||
|
|
||||||
# Connect the NAND gate inputs to the bus
|
|
||||||
pre_p_en_in_map = zip(["A", "B"], ["gated_clk", "we_bar"])
|
|
||||||
self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets)
|
|
||||||
|
|
||||||
# Connect the output of the precharge enable to the RBL input
|
|
||||||
pre_p_en_out_pos = self.pre_p_en_inst.get_pin("Z").center()
|
|
||||||
rbl_in_pos = self.rbl_inst.get_pin("en").center()
|
|
||||||
mid1 = vector(rbl_in_pos.x,pre_p_en_out_pos.y)
|
|
||||||
self.add_wire(("metal3","via2","metal2"),[pre_p_en_out_pos,mid1,rbl_in_pos])
|
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
|
||||||
offset=pre_p_en_out_pos,
|
|
||||||
rotate=90)
|
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
|
||||||
offset=pre_p_en_out_pos,
|
|
||||||
rotate=90)
|
|
||||||
|
|
||||||
|
|
||||||
def connect_rail_from_right(self,inst, pin, rail):
|
def connect_rail_from_right(self,inst, pin, rail):
|
||||||
|
|
@ -489,62 +606,7 @@ class control_logic(design.design):
|
||||||
offset=rail_pos,
|
offset=rail_pos,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
def route_pen(self):
|
|
||||||
pre_p_en_out_pos = self.pre_p_en_inst.get_pin("Z").center()
|
|
||||||
in_pos = self.s_en_inst.get_pin("A").lc()
|
|
||||||
mid1 = vector(rbl_out_pos.x,in_pos.y)
|
|
||||||
self.add_wire(("metal1","via1","metal2"),[rbl_out_pos,mid1,in_pos])
|
|
||||||
|
|
||||||
self.connect_output(self.inv_p_en_bar_inst, "Z", "p_en_bar")
|
|
||||||
|
|
||||||
def route_wlen(self):
|
|
||||||
|
|
||||||
wlen_map = zip(["A"], ["gated_clk"])
|
|
||||||
self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets)
|
|
||||||
self.connect_output(self.wl_en_inst, "Z", "wl_en")
|
|
||||||
|
|
||||||
def route_wen(self):
|
|
||||||
|
|
||||||
if self.port_type == "rw":
|
|
||||||
input_name = "we"
|
|
||||||
else:
|
|
||||||
input_name = "cs"
|
|
||||||
|
|
||||||
wen_map = zip(["A"], [input_name])
|
|
||||||
self.connect_vertical_bus(wen_map, self.w_en_inst, self.rail_offsets)
|
|
||||||
|
|
||||||
self.connect_output(self.w_en_inst, "Z", "w_en")
|
|
||||||
|
|
||||||
def route_sen(self):
|
|
||||||
|
|
||||||
rbl_out_pos = self.rbl_inst.get_pin("out").bc()
|
|
||||||
in_pos = self.s_en_inst.get_pin("A").lc()
|
|
||||||
mid1 = vector(rbl_out_pos.x,in_pos.y)
|
|
||||||
self.add_wire(("metal1","via1","metal2"),[rbl_out_pos,mid1,in_pos])
|
|
||||||
|
|
||||||
self.connect_output(self.s_en_inst, "Z", "s_en")
|
|
||||||
|
|
||||||
def route_clk(self):
|
|
||||||
""" Route the clk and clk_buf_bar signal internally """
|
|
||||||
|
|
||||||
clk_pin = self.clkbuf_inst.get_pin("A")
|
|
||||||
self.add_layout_pin_segment_center(text="clk",
|
|
||||||
layer="metal2",
|
|
||||||
start=clk_pin.bc(),
|
|
||||||
end=clk_pin.bc().scale(1,0))
|
|
||||||
|
|
||||||
clk_bar_out_pin = self.clk_bar_inst.get_pin("Z")
|
|
||||||
clk_bar_in_pin = self.gated_clk_inst.get_pin("B")
|
|
||||||
mid1 = vector(clk_bar_out_pos.x,clk_bar_in_pos.y)
|
|
||||||
self.add_wire(("metal1","via1","metal2"),[clk_bar_out_pos,mid1,clk_bar_in_pos])
|
|
||||||
|
|
||||||
clkbuf_map = zip(["Z"], ["clk_buf"])
|
|
||||||
self.connect_vertical_bus(clkbuf_map, self.clkbuf_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
|
||||||
|
|
||||||
clkbuf_map = zip(["Z"], ["gated_clk"])
|
|
||||||
self.connect_vertical_bus(clkbuf_map, self.gated_clk_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
|
||||||
|
|
||||||
self.connect_output(self.clkbuf_inst, "Z", "clk_buf")
|
|
||||||
|
|
||||||
def connect_output(self, inst, pin_name, out_name):
|
def connect_output(self, inst, pin_name, out_name):
|
||||||
""" Create an output pin on the right side from the pin of a given instance. """
|
""" Create an output pin on the right side from the pin of a given instance. """
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ class hierarchical_decoder(design.design):
|
||||||
for i in range(len(self.predec_groups[0])):
|
for i in range(len(self.predec_groups[0])):
|
||||||
for j in range(len(self.predec_groups[1])):
|
for j in range(len(self.predec_groups[1])):
|
||||||
for k in range(len(self.predec_groups[2])):
|
for k in range(len(self.predec_groups[2])):
|
||||||
row = (len(self.predec_groups[0])+len(self.predec_groups[1])) * k \
|
row = (len(self.predec_groups[0])*len(self.predec_groups[1])) * k \
|
||||||
+ len(self.predec_groups[0])*j + i
|
+ len(self.predec_groups[0])*j + i
|
||||||
|
|
||||||
name = self.NAND_FORMAT.format(row)
|
name = self.NAND_FORMAT.format(row)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue