mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
feat(fpga): initial implementation
Adds a new `tt_tool.py --create-fpga-bitstream` flag that creates a TT Sim FPGA bitstream from the user's project.
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
#
|
||||||
|
# Pinmap for the TT ASIC SIMULATOR version 1.0
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Clock
|
||||||
|
set_io -nowarn clk_fpga 37 # IOT_45a_G1
|
||||||
|
|
||||||
|
|
||||||
|
# SPI
|
||||||
|
set_io -nowarn spi_mosi 14
|
||||||
|
set_io -nowarn spi_miso 17
|
||||||
|
set_io -nowarn spi_clk 15
|
||||||
|
set_io -nowarn spi_cs_n 16
|
||||||
|
|
||||||
|
# USB
|
||||||
|
set_io -nowarn usb_dp 32 # IOT_43A
|
||||||
|
set_io -nowarn usb_dn 31 # IOT_42B
|
||||||
|
set_io -nowarn usb_pu 34 # IOT_44B
|
||||||
|
|
||||||
|
|
||||||
|
# Button
|
||||||
|
set_io -nowarn -pullup yes btn 13 # IOB_24A / boot button
|
||||||
|
|
||||||
|
|
||||||
|
# Leds
|
||||||
|
set_io -nowarn rgb[0] 39
|
||||||
|
set_io -nowarn rgb[1] 40
|
||||||
|
set_io -nowarn rgb[2] 41
|
||||||
|
|
||||||
|
|
||||||
|
# "project clock"
|
||||||
|
set_io -nowarn clk 35 # IOT_46B_G0
|
||||||
|
set_io -nowarn rst_n 38 # IOT_50B
|
||||||
|
set_io -nowarn gpio_led 36 # IOT_48B
|
||||||
|
|
||||||
|
|
||||||
|
# I/O
|
||||||
|
# pmod buttons
|
||||||
|
set_io -nowarn ui_in[0] 2
|
||||||
|
set_io -nowarn ui_in[1] 3
|
||||||
|
set_io -nowarn ui_in[2] 4
|
||||||
|
set_io -nowarn ui_in[3] 6
|
||||||
|
set_io -nowarn ui_in[4] 9
|
||||||
|
set_io -nowarn ui_in[5] 10
|
||||||
|
set_io -nowarn ui_in[6] 11
|
||||||
|
set_io -nowarn ui_in[7] 12
|
||||||
|
|
||||||
|
|
||||||
|
set_io -nowarn uo_out[0] 18
|
||||||
|
set_io -nowarn uo_out[1] 20
|
||||||
|
set_io -nowarn uo_out[2] 19
|
||||||
|
set_io -nowarn uo_out[3] 21
|
||||||
|
set_io -nowarn uo_out[4] 23
|
||||||
|
set_io -nowarn uo_out[5] 26
|
||||||
|
set_io -nowarn uo_out[6] 25
|
||||||
|
set_io -nowarn uo_out[7] 28
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set_io -nowarn uio[0] 27
|
||||||
|
set_io -nowarn uio[1] 42
|
||||||
|
set_io -nowarn uio[2] 44
|
||||||
|
set_io -nowarn uio[3] 43
|
||||||
|
set_io -nowarn uio[4] 46
|
||||||
|
set_io -nowarn uio[5] 45
|
||||||
|
set_io -nowarn uio[6] 48
|
||||||
|
set_io -nowarn uio[7] 47
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-License-Identifier: Apache 2.0
|
||||||
|
// Copyright (C) 2024, Tiny Tapeout LTD
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module tt_fpga_top (
|
||||||
|
input wire [7:0] ui_in,
|
||||||
|
output wire [7:0] uo_out,
|
||||||
|
inout wire [7:0] uio,
|
||||||
|
input wire clk,
|
||||||
|
input wire rst_n
|
||||||
|
);
|
||||||
|
wire [7:0] uio_in;
|
||||||
|
wire [7:0] uio_out;
|
||||||
|
wire [7:0] uio_oe;
|
||||||
|
|
||||||
|
SB_IO #(
|
||||||
|
.PIN_TYPE(6'b1010_01)
|
||||||
|
) uio_pin[7:0] (
|
||||||
|
.PACKAGE_PIN(uio),
|
||||||
|
.OUTPUT_ENABLE(uio_oe),
|
||||||
|
.D_OUT_0(uio_out),
|
||||||
|
.D_IN_0(uio_in),
|
||||||
|
);
|
||||||
|
|
||||||
|
__tt_um_placeholder user_project (
|
||||||
|
.ui_in(ui_in),
|
||||||
|
.uo_out(uo_out),
|
||||||
|
.uio_in(uio_in),
|
||||||
|
.uio_out(uio_out),
|
||||||
|
.uio_oe(uio_oe),
|
||||||
|
.ena(1'b1),
|
||||||
|
.clk(clk),
|
||||||
|
.rst_n(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
+45
-5
@@ -48,6 +48,8 @@ PINOUT_KEYS = [
|
|||||||
"uio[7]",
|
"uio[7]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
|
||||||
with open(os.path.join(os.path.dirname(__file__), "tile_sizes.yaml"), "r") as stream:
|
with open(os.path.join(os.path.dirname(__file__), "tile_sizes.yaml"), "r") as stream:
|
||||||
tile_sizes = yaml.safe_load(stream)
|
tile_sizes = yaml.safe_load(stream)
|
||||||
@@ -504,6 +506,46 @@ class Project:
|
|||||||
|
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
def create_fpga_bitstream(self):
|
||||||
|
logging.info(f"Creating FPGA bitstream for {self}")
|
||||||
|
|
||||||
|
with open(os.path.join(SCRIPT_DIR, "fpga/tt_fpga_top.v"), "r") as f:
|
||||||
|
top_module_template = f.read()
|
||||||
|
|
||||||
|
with open(os.path.join(self.src_dir, "_tt_fpga_top.v"), "w") as f:
|
||||||
|
f.write(
|
||||||
|
top_module_template.replace("__tt_um_placeholder", self.info.top_module)
|
||||||
|
)
|
||||||
|
|
||||||
|
build_dir = os.path.join(self.local_dir, "build")
|
||||||
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
|
|
||||||
|
sources = [os.path.join(self.src_dir, src) for src in self.sources]
|
||||||
|
source_list = " ".join(sources)
|
||||||
|
|
||||||
|
yosys_cmd = f"yosys -l {build_dir}/01-synth.log -DSYNTH -p 'synth_ice40 -top tt_fpga_top -json {build_dir}/tt_fpga.json' src/_tt_fpga_top.v {source_list}"
|
||||||
|
logging.debug(yosys_cmd)
|
||||||
|
p = subprocess.run(yosys_cmd, shell=True)
|
||||||
|
if p.returncode != 0:
|
||||||
|
logging.error("synthesis failed")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
nextpnr_cmd = f"nextpnr-ice40 -l {build_dir}/02-nextpnr.log --pcf-allow-unconstrained --seed 10 --freq 48 --package sg48 --up5k --asc {build_dir}/tt_fpga.asc --pcf {SCRIPT_DIR}/fpga/tt_fpga_top.pcf --json {build_dir}/tt_fpga.json"
|
||||||
|
logging.debug(nextpnr_cmd)
|
||||||
|
p = subprocess.run(nextpnr_cmd, shell=True)
|
||||||
|
if p.returncode != 0:
|
||||||
|
logging.error("placement failed")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
icepack_cmd = f"icepack {build_dir}/tt_fpga.asc {build_dir}/tt_fpga.bin"
|
||||||
|
logging.debug(icepack_cmd)
|
||||||
|
p = subprocess.run(icepack_cmd, shell=True)
|
||||||
|
if p.returncode != 0:
|
||||||
|
logging.error("bitstream creation failed failed")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
logging.info(f"Bitstream created successfully: {build_dir}/tt_fpga.bin")
|
||||||
|
|
||||||
# doc check
|
# doc check
|
||||||
# makes sure that the basic info is present
|
# makes sure that the basic info is present
|
||||||
def check_docs(self):
|
def check_docs(self):
|
||||||
@@ -531,10 +573,9 @@ class Project:
|
|||||||
template_args["uio"] = self.info.pinout.uio
|
template_args["uio"] = self.info.pinout.uio
|
||||||
|
|
||||||
logging.info("Creating PDF")
|
logging.info("Creating PDF")
|
||||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
with open(os.path.join(SCRIPT_DIR, "docs/project_header.md")) as fh:
|
||||||
with open(os.path.join(script_dir, "docs/project_header.md")) as fh:
|
|
||||||
doc_header = fh.read()
|
doc_header = fh.read()
|
||||||
with open(os.path.join(script_dir, "docs/project_preview.md")) as fh:
|
with open(os.path.join(SCRIPT_DIR, "docs/project_preview.md")) as fh:
|
||||||
doc_template = fh.read()
|
doc_template = fh.read()
|
||||||
info_md = os.path.join(self.local_dir, "docs/info.md")
|
info_md = os.path.join(self.local_dir, "docs/info.md")
|
||||||
with open(info_md) as fh:
|
with open(info_md) as fh:
|
||||||
@@ -743,12 +784,11 @@ class Project:
|
|||||||
# Print the summaries
|
# Print the summaries
|
||||||
def summarize(self):
|
def summarize(self):
|
||||||
cell_count = self.get_cell_counts_from_gl()
|
cell_count = self.get_cell_counts_from_gl()
|
||||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
|
|
||||||
Categories = typing.TypedDict(
|
Categories = typing.TypedDict(
|
||||||
"Categories", {"categories": typing.List[str], "map": typing.Dict[str, int]}
|
"Categories", {"categories": typing.List[str], "map": typing.Dict[str, int]}
|
||||||
)
|
)
|
||||||
with open(os.path.join(script_dir, "categories.json")) as fh:
|
with open(os.path.join(SCRIPT_DIR, "categories.json")) as fh:
|
||||||
categories: Categories = json.load(fh)
|
categories: Categories = json.load(fh)
|
||||||
|
|
||||||
defs = load_cells()
|
defs = load_cells()
|
||||||
|
|||||||
+11
@@ -104,6 +104,14 @@ if __name__ == "__main__":
|
|||||||
const=True,
|
const=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# FPGA
|
||||||
|
parser.add_argument(
|
||||||
|
"--create-fpga-bitstream",
|
||||||
|
help="create the FPGA bitstream",
|
||||||
|
action="store_const",
|
||||||
|
const=True,
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# setup log
|
# setup log
|
||||||
@@ -157,3 +165,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
if args.create_svg:
|
if args.create_svg:
|
||||||
project.create_svg()
|
project.create_svg()
|
||||||
|
|
||||||
|
if args.create_fpga_bitstream:
|
||||||
|
project.create_fpga_bitstream()
|
||||||
|
|||||||
Reference in New Issue
Block a user