mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
feat: Chip ROM auto generation with OpenLane 2
So we can generate the ROM while building the shuttle's GDS
This commit is contained in:
+1
-1
@@ -244,7 +244,7 @@ if __name__ == '__main__':
|
||||
shuttle.configure_mux()
|
||||
if args.test:
|
||||
shuttle.write_gl_config()
|
||||
#rom.write_rom()
|
||||
rom.write_rom()
|
||||
if not args.test:
|
||||
docs.build_index()
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import git
|
||||
import os
|
||||
from urllib.parse import urlparse
|
||||
|
||||
MAX_ROM_TEXT_SIZE = 92
|
||||
|
||||
segment_font = {
|
||||
" ": 0b00000000,
|
||||
@@ -30,7 +34,8 @@ class ROMFile:
|
||||
self.config = config
|
||||
|
||||
def get_git_remote(self):
|
||||
return list(git.Repo(".").remotes[0].urls)[0]
|
||||
repo_url = list(git.Repo(".").remotes[0].urls)[0]
|
||||
return urlparse(repo_url).path[1:]
|
||||
|
||||
def get_git_commit_hash(self):
|
||||
return git.Repo(".").commit().hexsha
|
||||
@@ -39,18 +44,25 @@ class ROMFile:
|
||||
rom = bytearray(256)
|
||||
short_sha = self.get_git_commit_hash()[:8]
|
||||
|
||||
rom_text = f"shuttle={self.config['name']}\n"
|
||||
rom_text = f"shuttle={self.config['id']}\n"
|
||||
rom_text += f"repo={self.get_git_remote()}\n"
|
||||
rom_text += f"commit={short_sha}\n"
|
||||
|
||||
assert len(rom_text) < 96, "ROM text too long"
|
||||
print(f"\nROM text: {len(rom_text)} bytes (max={MAX_ROM_TEXT_SIZE})\n")
|
||||
print(" " + "\n ".join(rom_text.split("\n")))
|
||||
|
||||
rom[0:4] = map(segment_char, "tt04")
|
||||
assert len(rom_text) < MAX_ROM_TEXT_SIZE, "ROM text too long"
|
||||
|
||||
rom[0:4] = map(segment_char, self.config['id'])
|
||||
rom[8:16] = map(segment_char, short_sha.upper())
|
||||
rom[32 : 32 + len(rom_text)] = rom_text.encode("ascii")
|
||||
|
||||
# build complete list of filenames for sim
|
||||
with open("verilog/includes/rom_tile.vmem", "w") as fh:
|
||||
with open(os.path.join(os.path.dirname(__file__), "rom/rom.vmem"), "w") as fh:
|
||||
for line in rom_text.split("\n"):
|
||||
if len(line) == 0:
|
||||
continue
|
||||
fh.write(f"// {line}\n")
|
||||
fh.write("\n")
|
||||
for line in range(0, len(rom), 16):
|
||||
for byte in range(0, 16):
|
||||
fh.write("{:02x} ".format(rom[line + byte]))
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
runs
|
||||
rom.vmem
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"DESIGN_NAME": "tt_um_chip_rom",
|
||||
"VERILOG_FILES": "dir::tt_um_chip_rom.v",
|
||||
|
||||
"FP_SIZING": "absolute",
|
||||
"DIE_AREA": "0 0 168.36 111.52",
|
||||
"FP_DEF_TEMPLATE": "ref::$DESIGN_DIR/../def/tt_block_1x1.def",
|
||||
|
||||
"FP_IO_HLENGTH": 2,
|
||||
"FP_IO_VLENGTH": 2,
|
||||
|
||||
"//": "use alternative efabless decap cells to solve LI density issue",
|
||||
"DECAP_CELL": "sky130_fd_sc_hd__decap_3 sky130_fd_sc_hd__decap_4 sky130_fd_sc_hd__decap_6 sky130_fd_sc_hd__decap_8 sky130_ef_sc_hd__decap_12",
|
||||
|
||||
"//": "period is in ns, so 20ns == 50mHz",
|
||||
"CLOCK_PERIOD": 20,
|
||||
"CLOCK_PORT": "clk",
|
||||
|
||||
"//": "don't use power rings or met5",
|
||||
"DESIGN_IS_CORE": false,
|
||||
"RT_MAX_LAYER": "met4",
|
||||
|
||||
"//": "save some time",
|
||||
"RUN_KLAYOUT_XOR": false,
|
||||
|
||||
"//": "reduce wasted space",
|
||||
"TOP_MARGIN_MULT": 1,
|
||||
"BOTTOM_MARGIN_MULT": 1,
|
||||
"LEFT_MARGIN_MULT": 6,
|
||||
"RIGHT_MARGIN_MULT": 6
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* tt_um_chip_rom.v
|
||||
*
|
||||
* ROM module for Tiny Tapeout chips
|
||||
*
|
||||
* Author: Uri Shaked
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module tt_um_chip_rom (
|
||||
input wire [7:0] ui_in, // Dedicated inputs
|
||||
output wire [7:0] uo_out, // Dedicated outputs
|
||||
input wire [7:0] uio_in, // IOs: Input path
|
||||
output wire [7:0] uio_out,// IOs: Output path
|
||||
output wire [7:0] uio_oe, // IOs: Enable path (active high: 0=input, 1=output)
|
||||
input wire ena,
|
||||
input wire clk,
|
||||
input wire rst_n
|
||||
);
|
||||
|
||||
reg [7:0] rom_data [0:255];
|
||||
|
||||
initial begin
|
||||
$readmemh("rom.vmem", rom_data);
|
||||
end
|
||||
|
||||
assign uo_out = rom_data[ui_in];
|
||||
assign uio_out = 8'h00;
|
||||
assign uio_oe = 8'h00;
|
||||
|
||||
endmodule // tt_um_chip_rom
|
||||
+3
-1
@@ -100,6 +100,8 @@ class ShuttleConfig():
|
||||
|
||||
def find_last_run(self, macro: str):
|
||||
runs = f"tt-multiplexer/ol2/{macro}/runs/"
|
||||
if macro == "tt_um_chip_rom":
|
||||
runs = "tt/rom/runs/"
|
||||
runlist = sorted(
|
||||
[r for r in os.listdir(runs) if r.startswith("RUN_") and os.path.isdir(os.path.join(runs, r))]
|
||||
)
|
||||
@@ -115,7 +117,7 @@ class ShuttleConfig():
|
||||
copy_print_glob("projects/*/*.gds", "tt-multiplexer/ol2/tt_top/gds")
|
||||
copy_print_glob("projects/*/*.lef", "tt-multiplexer/ol2/tt_top/lef")
|
||||
copy_print_glob("projects/*/*.v", "tt-multiplexer/ol2/tt_top/verilog")
|
||||
macros = ["tt_ctrl", "tt_mux"]
|
||||
macros = ["tt_um_chip_rom", "tt_ctrl", "tt_mux"]
|
||||
for macro in macros:
|
||||
lastrun = self.find_last_run(macro)
|
||||
copy_print(f"{lastrun}/final/gds/{macro}.gds", f"tt-multiplexer/ol2/tt_top/gds/{macro}.gds")
|
||||
|
||||
Reference in New Issue
Block a user