Skip to content

Commit fc78efe

Browse files
committed
ram added and update the PDN
1 parent bd8c870 commit fc78efe

28 files changed

Lines changed: 347535 additions & 13 deletions

build.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import argparse
2+
import json
3+
import os
4+
from pathlib import Path
5+
from typing import Any, List
6+
7+
from openlane.common import get_opdks_rev
8+
from openlane.flows.misc import OpenInKLayout
9+
from openlane.flows.classic import Classic
10+
from openlane.steps.odb import OdbpyStep
11+
from openlane.steps import OpenROAD
12+
import volare
13+
14+
15+
class CustomPower(OdbpyStep):
16+
id = "TT.Top.CustomPower"
17+
name = "Custom Power connections for RAM32 macro"
18+
19+
def get_script_path(self):
20+
return os.path.join(os.path.dirname(__file__), "odb_power.py")
21+
22+
def get_command(self) -> List[str]:
23+
macro = self.config["MACROS"]["RAM32"]
24+
instance = macro.instances["memory.ram_macro"]
25+
return super().get_command() + [
26+
"--macro-x-pos", str(instance.location[0]),
27+
]
28+
29+
30+
class ProjectFlow(Classic):
31+
pass
32+
33+
34+
def rewrite_path_string(s: str) -> str:
35+
# 1) Fix tt_tool-generated paths that escape src/ with ../tt/...
36+
if s.startswith("./../tt/"):
37+
return "tt/" + s[len("./../tt/"):]
38+
if s.startswith("../tt/"):
39+
return "tt/" + s[len("../tt/"):]
40+
41+
# 2) Fix dir:: paths that were originally intended to be relative to src/
42+
if s.startswith("dir::"):
43+
inner = s[len("dir::"):]
44+
if inner.startswith("src/") or inner.startswith("tt/") or inner.startswith("/"):
45+
return s
46+
return "dir::src/" + inner
47+
48+
return s
49+
50+
51+
def rewrite_obj(obj: Any) -> Any:
52+
if isinstance(obj, dict):
53+
return {k: rewrite_obj(v) for k, v in obj.items()}
54+
if isinstance(obj, list):
55+
return [rewrite_obj(v) for v in obj]
56+
if isinstance(obj, str):
57+
return rewrite_path_string(obj)
58+
return obj
59+
60+
61+
if __name__ == "__main__":
62+
parser = argparse.ArgumentParser(
63+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
64+
)
65+
parser.add_argument(
66+
"--open-in-klayout",
67+
action="store_true",
68+
help="Open the last run in KLayout",
69+
)
70+
args = parser.parse_args()
71+
72+
ProjectFlow.Steps.insert(
73+
ProjectFlow.Steps.index(OpenROAD.GeneratePDN) + 1,
74+
CustomPower
75+
)
76+
77+
pdk_root = volare.get_volare_home(os.getenv("PDK_ROOT"))
78+
volare.enable(pdk_root, "sky130", get_opdks_rev())
79+
80+
src_cfg = Path("src/config_merged.json")
81+
patched_cfg = Path("build_config.json")
82+
83+
with src_cfg.open("r", encoding="utf-8") as f:
84+
cfg = json.load(f)
85+
86+
cfg = rewrite_obj(cfg)
87+
88+
with patched_cfg.open("w", encoding="utf-8") as f:
89+
json.dump(cfg, f, indent=2, ensure_ascii=False)
90+
f.write("\n")
91+
92+
flow_class = OpenInKLayout if args.open_in_klayout else ProjectFlow
93+
flow = flow_class(
94+
str(patched_cfg),
95+
design_dir=".",
96+
pdk_root=pdk_root,
97+
pdk="sky130A",
98+
)
99+
flow.start(tag="wokwi")

build_config.json

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
{
2+
"PL_TARGET_DENSITY_PCT": 66,
3+
"CLOCK_PERIOD": 20,
4+
"PL_RESIZER_HOLD_SLACK_MARGIN": 0.1,
5+
"GRT_RESIZER_HOLD_SLACK_MARGIN": 0.05,
6+
"RUN_LINTER": 1,
7+
"LINTER_INCLUDE_PDK_MODELS": 1,
8+
"CLOCK_PORT": "clk",
9+
"RUN_IRDROP_REPORT": false,
10+
"VERILOG_INCLUDE_DIRS": [
11+
"src/utoss-risc-v"
12+
],
13+
"VERILOG_DEFINES": [
14+
"UTOSS_RISCV_HARDENING"
15+
],
16+
"EXTRA_VERILOG_MODELS": [
17+
"dir::src/RAM32.sv"
18+
],
19+
"FP_PDN_CHECK_NODES": false,
20+
"FP_PDN_VOFFSET": 26.32,
21+
"FP_PDN_CFG": "dir::src/pdn_cfg.tcl",
22+
"MACROS": {
23+
"RAM32": {
24+
"instances": {
25+
"memory.ram_macro": {
26+
"location": [
27+
10,
28+
10
29+
],
30+
"orientation": "N"
31+
}
32+
},
33+
"gds": [
34+
"dir::src/macros/RAM32.gds"
35+
],
36+
"lef": [
37+
"dir::src/macros/RAM32.lef"
38+
],
39+
"nl": [
40+
"dir::src/macros/RAM32.nl.v"
41+
],
42+
"spef": {
43+
"min_*": [
44+
"dir::src/macros/RAM32.min_.spef"
45+
],
46+
"nom_*": [
47+
"dir::src/macros/RAM32.nom_.spef"
48+
],
49+
"max_*": [
50+
"dir::src/macros/RAM32.max_.spef"
51+
]
52+
},
53+
"lib": {
54+
"min_tt_025C_1v80": "dir::src/macros/RAM32.lib/min_tt_025C_1v80/RAM32__min_tt_025C_1v80.lib",
55+
"nom_tt_025C_1v80": "dir::src/macros/RAM32.lib/nom_tt_025C_1v80/RAM32__nom_tt_025C_1v80.lib",
56+
"max_tt_025C_1v80": "dir::src/macros/RAM32.lib/max_tt_025C_1v80/RAM32__max_tt_025C_1v80.lib",
57+
"min_ff_n40C_1v95": "dir::src/macros/RAM32.lib/min_ff_n40C_1v95/RAM32__min_ff_n40C_1v95.lib",
58+
"nom_ff_n40C_1v95": "dir::src/macros/RAM32.lib/nom_ff_n40C_1v95/RAM32__nom_ff_n40C_1v95.lib",
59+
"max_ff_n40C_1v95": "dir::src/macros/RAM32.lib/max_ff_n40C_1v95/RAM32__max_ff_n40C_1v95.lib",
60+
"min_ss_100C_1v60": "dir::src/macros/RAM32.lib/min_ss_100C_1v60/RAM32__min_ss_100C_1v60.lib",
61+
"nom_ss_100C_1v60": "dir::src/macros/RAM32.lib/nom_ss_100C_1v60/RAM32__nom_ss_100C_1v60.lib",
62+
"max_ss_100C_1v60": "dir::src/macros/RAM32.lib/max_ss_100C_1v60/RAM32__max_ss_100C_1v60.lib"
63+
}
64+
}
65+
},
66+
"RT_MAX_LAYER": "met4",
67+
"MAGIC_LEF_WRITE_USE_GDS": true,
68+
"RUN_KLAYOUT_XOR": 0,
69+
"RUN_KLAYOUT_DRC": 0,
70+
"DESIGN_REPAIR_BUFFER_OUTPUT_PORTS": 0,
71+
"TOP_MARGIN_MULT": 1,
72+
"BOTTOM_MARGIN_MULT": 1,
73+
"LEFT_MARGIN_MULT": 6,
74+
"RIGHT_MARGIN_MULT": 6,
75+
"FP_SIZING": "absolute",
76+
"GRT_ALLOW_CONGESTION": 1,
77+
"FP_IO_HLENGTH": 2,
78+
"FP_IO_VLENGTH": 2,
79+
"FP_PDN_VPITCH": 153.6,
80+
"RUN_CTS": 1,
81+
"FP_PDN_MULTILAYER": 0,
82+
"MAGIC_DEF_LABELS": 0,
83+
"MAGIC_WRITE_LEF_PINONLY": 1,
84+
"DESIGN_NAME": "tt_um_utoss_riscv",
85+
"VERILOG_FILES": [
86+
"dir::src/tt_um_utoss_riscv.sv",
87+
"dir::src/MA.sv",
88+
"dir::src/RAM32.sv",
89+
"dir::src/utoss-risc-v/src/ALU_ALUdecoder/ALU.v",
90+
"dir::src/utoss-risc-v/src/ALU_ALUdecoder/ALUdecoder.sv",
91+
"dir::src/utoss-risc-v/src/ControlFSM.sv",
92+
"dir::src/utoss-risc-v/src/fetch.sv",
93+
"dir::src/utoss-risc-v/src/Instruction_Decode/Instruction_Decode.sv",
94+
"dir::src/utoss-risc-v/src/Instruction_Decode/MemoryLoader.sv",
95+
"dir::src/utoss-risc-v/src/Instruction_Decode/RegisterFile.v",
96+
"dir::src/utoss-risc-v/src/params.svh",
97+
"dir::src/utoss-risc-v/src/types.svh",
98+
"dir::src/utoss-risc-v/src/utils.svh",
99+
"dir::src/utoss-risc-v/src/utoss_riscv.sv"
100+
],
101+
"DIE_AREA": "0 0 1378.16 225.76",
102+
"FP_DEF_TEMPLATE": "dir::src/../tt/tech/sky130A/def/tt_block_8x2_pg.def",
103+
"VDD_PIN": "VPWR",
104+
"GND_PIN": "VGND"
105+
}

info.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ project:
88
clock_hz: 0 # Clock frequency in Hz (or 0 if not applicable)
99

1010
# How many tiles your design occupies? A single tile is about 167x108 uM.
11-
tiles: "4x2" # Valid values: 1x1, 1x2, 2x2, 3x2, 4x2, 6x2 or 8x2
11+
tiles: "8x2" # Valid values: 1x1, 1x2, 2x2, 3x2, 4x2, 6x2 or 8x2
1212

1313
# Your top module name must start with "tt_um_". Make it unique by including your github username:
1414
top_module: "tt_um_utoss_riscv"
@@ -19,6 +19,7 @@ project:
1919
source_files:
2020
- "tt_um_utoss_riscv.sv"
2121
- "MA.sv"
22+
- "RAM32.sv"
2223
- "utoss-risc-v/src/ALU_ALUdecoder/ALU.v"
2324
- "utoss-risc-v/src/ALU_ALUdecoder/ALUdecoder.sv"
2425
- "utoss-risc-v/src/ControlFSM.sv"

odb_power.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
# Adapted from the official tt06-dffram-example
3+
4+
import odb
5+
import click
6+
from reader import click_odb
7+
8+
9+
@click.command()
10+
@click.option(
11+
"--macro-x-pos",
12+
default=0,
13+
type=int,
14+
help="X position of the RAM32 macro in microns (tile/grid coordinate used by config).",
15+
)
16+
@click_odb
17+
def power(reader, macro_x_pos: int):
18+
tech = reader.db.getTech()
19+
block = reader.block
20+
21+
vpwr_net = block.findNet("VPWR")
22+
vgnd_net = block.findNet("VGND")
23+
if vpwr_net is None or vgnd_net is None:
24+
raise RuntimeError("Could not find VPWR/VGND in top-level block.")
25+
26+
met4 = tech.findLayer("met4")
27+
if met4 is None:
28+
raise RuntimeError("Could not find met4 layer.")
29+
30+
vpwr_wire = vpwr_net.getSWires()[0]
31+
vgnd_wire = vgnd_net.getSWires()[0]
32+
33+
vpwr_bterm = vpwr_net.getBTerms()[0]
34+
vgnd_bterm = vgnd_net.getBTerms()[0]
35+
vpwr_bpin = vpwr_bterm.getBPins()[0]
36+
vgnd_bpin = vgnd_bterm.getBPins()[0]
37+
38+
# Stripe geometry as the official DFFRAM example.
39+
# VPWR stripes
40+
for i in range(3):
41+
x = macro_x_pos * 1000 + 18280 + i * 153600
42+
odb.dbSBox_create(vpwr_wire, met4, x, 11880, x + 1600, 144120, "STRIPE")
43+
odb.dbBox_create(vpwr_bpin, met4, x, 11880, x + 1600, 144120)
44+
45+
# VGND stripes
46+
for i in range(2):
47+
x = macro_x_pos * 1000 + 95080 + i * 153600
48+
odb.dbSBox_create(vgnd_wire, met4, x, 11880, x + 1600, 144120, "STRIPE")
49+
odb.dbBox_create(vgnd_bpin, met4, x, 11880, x + 1600, 144120)
50+
51+
52+
if __name__ == "__main__":
53+
power()

src/MA.sv

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
11
module MA #( parameter SIZE = 1024 )
2-
( input wire clk
2+
(
3+
`ifdef USE_POWER_PINS
4+
input VPWR,
5+
input VGND,
6+
`endif
7+
input wire clk
38
, input addr_t address
49
, input data_t write_data
510
, input wire [3:0] write_enable
611
, output data_t read_data
712
);
13+
`ifdef __pnr__
14+
15+
wire [4:0] ram_addr;
16+
assign ram_addr = {1'b0, address[5:2]};
817

18+
RAM32 ram_macro (
19+
`ifdef USE_POWER_PINS
20+
.VPWR(VPWR),
21+
.VGND(VGND),
22+
`endif
23+
.CLK(clk),
24+
.EN0(1'b1),
25+
.A0(ram_addr),
26+
.WE0(write_enable),
27+
.Di0(write_data),
28+
.Do0(read_data)
29+
);
30+
31+
`else
932
reg [31:0] M[0:SIZE -1];
1033

1134
`ifndef UTOSS_RISCV_HARDENING
@@ -28,5 +51,7 @@ module MA #( parameter SIZE = 1024 )
2851
if (write_enable[2]) M[address[31:2]][23:16] <= write_data[23:16];
2952
if (write_enable[3]) M[address[31:2]][31:24] <= write_data[31:24];
3053
end
54+
55+
`endif
3156

3257
endmodule

src/RAM32.sv

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
`default_nettype none
2+
3+
module RAM32 (
4+
`ifdef USE_POWER_PINS
5+
input wire VPWR,
6+
input wire VGND,
7+
`endif
8+
input wire CLK,
9+
input wire [3:0] WE0,
10+
input wire EN0,
11+
input wire [4:0] A0,
12+
input wire [31:0] Di0,
13+
output reg [31:0] Do0
14+
);
15+
16+
reg [31:0] mem [0:31];
17+
18+
always @(posedge CLK) begin
19+
if (EN0) begin
20+
Do0 <= mem[A0];
21+
if (WE0[0]) mem[A0][7:0] <= Di0[7:0];
22+
if (WE0[1]) mem[A0][15:8] <= Di0[15:8];
23+
if (WE0[2]) mem[A0][23:16] <= Di0[23:16];
24+
if (WE0[3]) mem[A0][31:24] <= Di0[31:24];
25+
end
26+
else begin
27+
Do0 <= 32'b0;
28+
end
29+
end
30+
31+
endmodule

0 commit comments

Comments
 (0)