Create sencha top level bitstream target
- Decouple ROM software target builds from matcha to top level targets
- Expose config attribute in rom scrambling rule and default to matcha
when no top level target is specified
- Split off sencha and matcha linker scripts for both test rom and
puppeteer
Bypass-Presubmit-Reason: tested manual bitstream in edacloud for both matcha and sencha with the file renaming
Change-Id: I00312226c6185530bbe358efde418b2ec745848d
diff --git a/hw/bitstream/vivado/BUILD b/hw/bitstream/vivado/BUILD
index 437241b..608baed 100644
--- a/hw/bitstream/vivado/BUILD
+++ b/hw/bitstream/vivado/BUILD
@@ -5,6 +5,7 @@
load("@lowrisc_opentitan//rules:fusesoc.bzl", "fusesoc_build")
load("@lowrisc_opentitan//rules:splice.bzl", "bitstream_splice")
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
+load("//rules:targets.bzl", "get_targets")
package(default_visibility = ["//visibility:public"])
@@ -16,147 +17,158 @@
# relative $(location ...) resolved labels is up 10 subdirectories.
_PREFIX = "../../../../../../../../../.."
-_FPGA_NEXUS_TESTROM = "//sw/device/lib/testing/test_rom:test_rom_fpga_nexus_scr_vmem"
+TARGETS = get_targets()
-_FPGA_NEXUS_OTP_RMA = "//hw/top_matcha/data:otp_img_rma"
+_FPGA_NEXUS_TESTROM = ["//sw/device/lib/testing/test_rom:{}_test_rom_fpga_nexus_scr_vmem".format(target) for target in TARGETS]
-_FPGA_NEXUS_TESTROM_PATH = "{}/$(location {})".format(_PREFIX, _FPGA_NEXUS_TESTROM)
+_FPGA_NEXUS_OTP_RMA = ["//hw/top_{}/data:otp_img_rma".format(target) for target in TARGETS]
-_FPGA_NEXUS_OTP_RMA_PATH = "{}/$(location {})".format(_PREFIX, _FPGA_NEXUS_OTP_RMA)
+_FPGA_NEXUS_TESTROM_PATHS = ["{}/$(location {})".format(_PREFIX, TESTROM) for TESTROM in _FPGA_NEXUS_TESTROM]
+
+_FPGA_NEXUS_OTP_RMA_PATHS = ["{}/$(location {})".format(_PREFIX, OTP_IMG) for OTP_IMG in _FPGA_NEXUS_OTP_RMA]
+
+_FPGA_NEXUS_TARGET_INFO = zip(
+ get_targets(),
+ _FPGA_NEXUS_TESTROM,
+ _FPGA_NEXUS_TESTROM_PATHS,
+ _FPGA_NEXUS_OTP_RMA,
+ _FPGA_NEXUS_OTP_RMA_PATHS,
+)
# Note: all of the targets are tagged with "manual" to prevent them from being
# matched by bazel wildcards like "//...". In order to build the bitstream,
# you need to ask for it directly or by dependency via another rule, such as
# a functest.
-fusesoc_build(
- name = "fpga_nexus",
+[fusesoc_build(
+ name = "{}_fpga_nexus".format(target),
testonly = True,
srcs = [
"//hw:all_files",
- _FPGA_NEXUS_TESTROM,
- _FPGA_NEXUS_OTP_RMA,
+ TESTROM,
+ OTP_IMG,
],
cores = [
"//:cores",
"//hw/ip:BUILD",
- "//hw/top_matcha:BUILD"
+ "//hw/top_{}:BUILD".format(target),
],
data = ["@lowrisc_opentitan//hw/ip/otbn:all_files"],
flags = [
- "--BootRomInitFile=" + _FPGA_NEXUS_TESTROM_PATH,
- "--OtpCtrlMemInitFile=" + _FPGA_NEXUS_OTP_RMA_PATH,
+ "--BootRomInitFile=" + TESTROM_PATH,
+ "--OtpCtrlMemInitFile=" + OTP_PATH,
],
output_groups = {
- "bitstream": ["synth-vivado/google_systems_chip_matcha_nexus_0.1.bit"],
+ "bitstream": ["synth-vivado/google_systems_chip_{}_nexus_0.1.bit".format(target)],
"rom_mmi": ["synth-vivado/rom.mmi"],
"otp_mmi": ["synth-vivado/otp.mmi"],
"logs": [
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/synth_1/runme.log",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/runme.log",
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/synth_1/runme.log".format(target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/runme.log".format(target),
"synth-vivado/vivado.log",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/synth_1/chip_matcha_nexus_utilization_synth.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_power_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_utilization_placed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_bus_skew_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_drc_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_io_placed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_timing_summary_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_control_sets_placed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_methodology_drc_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_drc_opted.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_clock_utilization_routed.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/chip_matcha_nexus_route_status.rpt",
- "synth-vivado/google_systems_chip_matcha_nexus_0.1.runs/impl_1/utilization_kelvin.rpt",
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/synth_1/chip_{}_nexus_utilization_synth.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_power_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_utilization_placed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_bus_skew_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_drc_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_io_placed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_timing_summary_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_control_sets_placed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_methodology_drc_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_drc_opted.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_clock_utilization_routed.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/chip_{}_nexus_route_status.rpt".format(target, target),
+ "synth-vivado/google_systems_chip_{}_nexus_0.1.runs/impl_1/utilization_kelvin.rpt".format(target, target),
],
},
- systems = ["google:systems:chip_matcha_nexus"],
+ systems = ["google:systems:chip_{}_nexus".format(target)],
tags = ["manual"],
target = "synth",
use_system_fusesoc = True,
-)
+) for target, TESTROM, TESTROM_PATH, OTP_IMG, OTP_PATH in _FPGA_NEXUS_TARGET_INFO]
-filegroup(
- name = "fpga_nexus_test_rom",
+[filegroup(
+ name = "{}_fpga_nexus_test_rom".format(target),
testonly = True,
- srcs = [":fpga_nexus"],
+ srcs = [":{}_fpga_nexus".format(target)],
output_group = "bitstream",
tags = ["manual"],
-)
+) for target in TARGETS]
-filegroup(
- name = "rom_mmi",
+[filegroup(
+ name = "{}_rom_mmi".format(target),
testonly = True,
- srcs = [":fpga_nexus"],
+ srcs = [":{}_fpga_nexus".format(target)],
output_group = "rom_mmi",
tags = ["manual"],
-)
+) for target in TARGETS]
-filegroup(
- name = "otp_mmi",
+[filegroup(
+ name = "{}_otp_mmi".format(target),
testonly = True,
- srcs = [":fpga_nexus"],
+ srcs = [":{}_fpga_nexus".format(target)],
output_group = "otp_mmi",
tags = ["manual"],
)
+for target in TARGETS]
-filegroup(
- name = "logs",
+[filegroup(
+ name = "{}.logs".format(target),
testonly = True,
- srcs = [":fpga_nexus"],
+ srcs = [":{}_fpga_nexus".format(target)],
output_group = "logs",
tags = ["manual"],
-)
+) for target in TARGETS]
-bitstream_splice(
- name = "fpga_nexus_mask_test_rom",
+[bitstream_splice(
+ name = "{}_fpga_nexus_mask_test_rom".format(target),
testonly = True,
- src = ":fpga_nexus_test_rom",
- data = "//sw/device/lib/testing/test_rom:test_rom_fpga_nexus_scr_vmem",
- meminfo = ":rom_mmi",
+ src = ":{}_fpga_nexus_test_rom".format(target),
+ data = "//sw/device/lib/testing/test_rom:{}_test_rom_fpga_nexus_scr_vmem".format(target),
+ meminfo = ":{}_rom_mmi".format(target),
tags = ["manual"],
-)
+) for target in TARGETS]
-bitstream_splice(
- name = "fpga_nexus_mask_puppeteer_rom",
+[bitstream_splice(
+ name = "{}_fpga_nexus_mask_puppeteer_rom".format(target),
testonly = True,
- src = ":fpga_nexus_test_rom",
- data = "//sw/device/lib/testing/test_rom:puppeteer_rom_fpga_nexus_scr_vmem",
- meminfo = ":rom_mmi",
+ src = ":{}_fpga_nexus_test_rom".format(target),
+ data = "//sw/device/lib/testing/test_rom:{}_puppeteer_rom_fpga_nexus_scr_vmem".format(target),
+ meminfo = ":{}_rom_mmi".format(target),
tags = ["manual"],
-)
+) for target in TARGETS]
-bitstream_splice(
- name = "fpga_nexus_mask_test_rom_no_otp",
+[bitstream_splice(
+ name = "{}_fpga_nexus_mask_test_rom_no_otp".format(target),
testonly = True,
- src = ":fpga_nexus_test_rom",
- data = "//sw/device/lib/testing/test_rom:test_rom_no_otp_fpga_nexus_scr_vmem",
- meminfo = ":rom_mmi",
+ src = ":{}_fpga_nexus_test_rom".format(target),
+ data = "//sw/device/lib/testing/test_rom:{}_test_rom_no_otp_fpga_nexus_scr_vmem".format(target),
+ meminfo = ":{}_rom_mmi".format(target),
tags = ["manual"],
-)
+) for target in TARGETS]
-bitstream_splice(
- name = "fpga_nexus_mask_test_rom_no_otp_empty",
+[bitstream_splice(
+ name = "{}_fpga_nexus_mask_test_rom_no_otp_empty".format(target),
testonly = True,
- src = ":fpga_nexus_mask_test_rom_no_otp",
- data = "//hw/top_matcha/data:otp_img_empty",
- meminfo = ":otp_mmi",
+ src = ":{}_fpga_nexus_mask_test_rom_no_otp".format(target),
+ data = "//hw/top_{}/data:otp_img_empty".format(target),
+ meminfo = ":{}_otp_mmi".format(target),
tags = ["manual"],
-)
+) for target in TARGETS]
-pkg_tar(
- name = "fpga_nexus_smoketest",
+[pkg_tar(
+ name = "{}_fpga_nexus_smoketest".format(target),
testonly = True,
srcs = [
- ":fpga_nexus_mask_test_rom",
- ":fpga_nexus_mask_test_rom_no_otp_empty",
- ":logs",
- ":otp_mmi",
- ":rom_mmi",
+ ":{}_fpga_nexus_mask_test_rom".format(target),
+ ":{}_fpga_nexus_mask_test_rom_no_otp_empty".format(target),
+ ":{}_logs".format(target),
+ ":{}_otp_mmi".format(target),
+ ":{}_rom_mmi".format(target),
"//sw/device/examples/hello_world_multicore:hello_world_multicore_sc_embedded_fpga_nexus_bin",
],
extension = "tar.gz",
mode = "0755",
strip_prefix = "/",
tags = ["manual"],
-)
+) for target in TARGETS]
diff --git a/hw/top_matcha/chip_matcha_nexus.core b/hw/top_matcha/chip_matcha_nexus.core
index 49153c9..099231e 100644
--- a/hw/top_matcha/chip_matcha_nexus.core
+++ b/hw/top_matcha/chip_matcha_nexus.core
@@ -44,7 +44,7 @@
BootRomInitFile:
datatype: str
description: Scrambled boot ROM initialization file in 40 bit vmem hex format
- default: "../../../../../../out/matcha/hw/rom_splices/test_rom_fpga_nexus.scr.39.vmem"
+ default: "../../../../../../out/matcha/hw/rom_splices/matcha_test_rom_fpga_nexus.scr.39.vmem"
paramtype: vlogparam
OtpCtrlMemInitFile:
datatype: str
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 740c38d..9429ba6 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -318,7 +318,7 @@
}
{
name: sw_test_mode_test_rom
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0"]
+ sw_images: ["//sw/device/lib/testing/test_rom:matcha_test_rom:0"]
en_run_modes: ["sw_test_mode_common"]
}
{
@@ -378,7 +378,7 @@
}
{
name: sw_test_mode_test_rom_with_smc
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0"]
+ sw_images: ["//sw/device/lib/testing/test_rom:matcha_test_rom:0"]
en_run_modes: ["sw_test_mode_common_with_smc"]
}
{
diff --git a/hw/top_matcha/dv/verilator/verilator_sim_cfg.hjson b/hw/top_matcha/dv/verilator/verilator_sim_cfg.hjson
index 65c4a27..c19c874 100644
--- a/hw/top_matcha/dv/verilator/verilator_sim_cfg.hjson
+++ b/hw/top_matcha/dv/verilator/verilator_sim_cfg.hjson
@@ -56,7 +56,7 @@
run_modes: [
{
name: sw_test_mode
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0",
+ sw_images: ["//sw/device/lib/testing/test_rom:matcha_test_rom:0",
"//hw/ip/otp_ctrl/data:img_rma:3"]
run_opts: [
// The following shell snippet converts the SW images specification to what's
diff --git a/hw/top_sencha/chip_sencha_nexus.core b/hw/top_sencha/chip_sencha_nexus.core
index fc0e7df..465b931 100644
--- a/hw/top_sencha/chip_sencha_nexus.core
+++ b/hw/top_sencha/chip_sencha_nexus.core
@@ -44,7 +44,7 @@
BootRomInitFile:
datatype: str
description: Scrambled boot ROM initialization file in 40 bit vmem hex format
- default: "../../../../../../out/sencha/hw/rom_splices/test_rom_fpga_nexus.scr.39.vmem"
+ default: "../../../../../../out/sencha/hw/rom_splices/sencha_test_rom_fpga_nexus.scr.39.vmem"
paramtype: vlogparam
OtpCtrlMemInitFile:
datatype: str
diff --git a/hw/top_sencha/dv/chip_sim_cfg.hjson b/hw/top_sencha/dv/chip_sim_cfg.hjson
index 8d65c94..7a35131 100644
--- a/hw/top_sencha/dv/chip_sim_cfg.hjson
+++ b/hw/top_sencha/dv/chip_sim_cfg.hjson
@@ -318,7 +318,7 @@
}
{
name: sw_test_mode_test_rom
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0"]
+ sw_images: ["//sw/device/lib/testing/test_rom:sencha_test_rom:0"]
en_run_modes: ["sw_test_mode_common"]
}
{
@@ -378,7 +378,7 @@
}
{
name: sw_test_mode_test_rom_with_smc
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0"]
+ sw_images: ["//sw/device/lib/testing/test_rom:sencha_test_rom:0"]
en_run_modes: ["sw_test_mode_common_with_smc"]
}
{
diff --git a/hw/top_sencha/dv/verilator/verilator_sim_cfg.hjson b/hw/top_sencha/dv/verilator/verilator_sim_cfg.hjson
index 46e0f73..b76a742 100644
--- a/hw/top_sencha/dv/verilator/verilator_sim_cfg.hjson
+++ b/hw/top_sencha/dv/verilator/verilator_sim_cfg.hjson
@@ -56,7 +56,7 @@
run_modes: [
{
name: sw_test_mode
- sw_images: ["//sw/device/lib/testing/test_rom:test_rom:0",
+ sw_images: ["//sw/device/lib/testing/test_rom:sencha_test_rom:0",
"//hw/ip/otp_ctrl/data:img_rma:3"]
run_opts: [
// The following shell snippet converts the SW images specification to what's
diff --git a/hw/top_sencha/physical_pads.core b/hw/top_sencha/physical_pads.core
new file mode 100644
index 0000000..f2c1a1e
--- /dev/null
+++ b/hw/top_sencha/physical_pads.core
@@ -0,0 +1,46 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:systems:physical_pads:0.1"
+description: "Open-source place-holder for physical pads"
+
+filesets:
+ files_rtl:
+ depend:
+ - lowrisc:prim:assert
+ files:
+ - rtl/physical_pads.sv
+ file_type: systemVerilogSource
+
+ files_verilator_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+ - lowrisc:lint:comportable
+ files:
+ # - lint/physical_pads.vlt
+ file_type: vlt
+
+ files_ascentlint_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+ - lowrisc:lint:comportable
+ files:
+ # - lint/physical_pads.waiver
+ file_type: waiver
+
+ files_veriblelint_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+ - lowrisc:lint:comportable
+
+targets:
+ default: &default_target
+ filesets:
+ - tool_verilator ? (files_verilator_waiver)
+ - tool_ascentlint ? (files_ascentlint_waiver)
+ - tool_veriblelint ? (files_veriblelint_waiver)
+ - files_rtl
diff --git a/hw/top_sencha/rtl/clkgen_xilultrascaleplus.sv b/hw/top_sencha/rtl/clkgen_xilultrascaleplus.sv
new file mode 100644
index 0000000..58ba16b
--- /dev/null
+++ b/hw/top_sencha/rtl/clkgen_xilultrascaleplus.sv
@@ -0,0 +1,147 @@
+// Copyright 2024 Google LLC
+// Copyright lowRISC contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+module clkgen_xilultrascaleplus # (
+ // Add BUFG if not done by downstream logic
+ parameter bit AddClkBuf = 1
+) (
+ input clk_i,
+ input clk_n_i,
+ input rst_ni,
+ input srst_ni,
+ output clk_main_o,
+ output clk_48MHz_o,
+ output clk_aon_o,
+ output rst_no
+);
+ logic locked_pll;
+ logic io_clk_buf;
+ logic io_rst_buf_n;
+ logic clk_10_buf;
+ logic clk_10_unbuf;
+ logic clk_fb_buf;
+ logic clk_fb_unbuf;
+ logic clk_48_buf;
+ logic clk_48_unbuf;
+ logic clk_aon_buf;
+ logic clk_aon_unbuf;
+ logic clk_ibufds_o;
+
+ // Input IBUFDS conver diff-pair to single-end
+ IBUFDS clk_ibufds (
+ .I (clk_i),
+ .IB (clk_n_i),
+ .O (clk_ibufds_o)
+ );
+
+ MMCME2_ADV #(
+ .BANDWIDTH ("OPTIMIZED"),
+ .COMPENSATION ("ZHOLD"),
+ .STARTUP_WAIT ("FALSE"),
+ .DIVCLK_DIVIDE (1),
+ .CLKFBOUT_MULT_F (12.000),
+ .CLKFBOUT_PHASE (0.000),
+ .CLKOUT0_DIVIDE_F (120.0),
+ .CLKOUT0_PHASE (0.000),
+ .CLKOUT0_DUTY_CYCLE (0.500),
+ .CLKOUT1_DIVIDE (25),
+ .CLKOUT1_PHASE (0.000),
+ .CLKOUT1_DUTY_CYCLE (0.500),
+ // With CLKOUT4_CASCADE, CLKOUT6's divider is an input to CLKOUT4's
+ // divider. The effective ratio is a multiplication of the two.
+ .CLKOUT4_DIVIDE (40),
+ .CLKOUT4_PHASE (0.000),
+ .CLKOUT4_DUTY_CYCLE (0.500),
+ .CLKOUT4_CASCADE ("TRUE"),
+ .CLKOUT6_DIVIDE (120),
+ .CLKIN1_PERIOD (10.000)
+ ) pll (
+ .CLKFBOUT (clk_fb_unbuf),
+ .CLKFBOUTB (),
+ .CLKOUT0 (clk_10_unbuf),
+ .CLKOUT0B (),
+ .CLKOUT1 (clk_48_unbuf),
+ .CLKOUT1B (),
+ .CLKOUT2 (),
+ .CLKOUT2B (),
+ .CLKOUT3 (),
+ .CLKOUT3B (),
+ .CLKOUT4 (clk_aon_unbuf),
+ .CLKOUT5 (),
+ .CLKOUT6 (),
+ // Input clock control
+ .CLKFBIN (clk_fb_buf),
+ .CLKIN1 (clk_ibufds_o),
+ .CLKIN2 (1'b0),
+ // Tied to always select the primary input clock
+ .CLKINSEL (1'b1),
+ // Ports for dynamic reconfiguration
+ .DADDR (7'h0),
+ .DCLK (1'b0),
+ .DEN (1'b0),
+ .DI (16'h0),
+ .DO (),
+ .DRDY (),
+ .DWE (1'b0),
+ // Phase shift signals
+ .PSCLK (1'b0),
+ .PSEN (1'b0),
+ .PSINCDEC (1'b0),
+ .PSDONE (),
+ // Other control and status signals
+ .CLKFBSTOPPED (),
+ .CLKINSTOPPED (),
+ .LOCKED (locked_pll),
+ .PWRDWN (1'b0),
+ // Do not reset MMCM on external reset, otherwise ILA disconnects at a reset
+ .RST (1'b0));
+
+ // output buffering
+ BUFGCE clk_fb_bufgce (
+ .I (clk_fb_unbuf),
+ .O (clk_fb_buf)
+ );
+
+ BUFGCE clk_aon_bufgce (
+ .I (clk_aon_unbuf),
+ .O (clk_aon_buf)
+ );
+
+ if (AddClkBuf == 1) begin : gen_clk_bufs
+ BUFGCE clk_10_bufgce (
+ .I (clk_10_unbuf),
+ .O (clk_10_buf)
+ );
+
+ BUFGCE clk_48_bufgce (
+ .I (clk_48_unbuf),
+ .O (clk_48_buf)
+ );
+ end else begin : gen_no_clk_bufs
+ // BUFGs added by downstream modules, no need to add here
+ assign clk_10_buf = clk_10_unbuf;
+ assign clk_48_buf = clk_48_unbuf;
+ end
+
+ // outputs
+ // clock
+ assign clk_main_o = clk_10_buf;
+ assign clk_48MHz_o = clk_48_buf;
+ assign clk_aon_o = clk_aon_buf;
+
+ // reset
+ assign rst_no = locked_pll & rst_ni & srst_ni;
+endmodule
diff --git a/hw/top_sencha/rtl/physical_pads.sv b/hw/top_sencha/rtl/physical_pads.sv
new file mode 100644
index 0000000..4d7cf8b
--- /dev/null
+++ b/hw/top_sencha/rtl/physical_pads.sv
@@ -0,0 +1,32 @@
+// Copyright 2024 Google LLC
+// Copyright lowRISC contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// This is a physical pads placeholder for the open-source views.
+// Special physical pad outputs and power sequencing signals are just tied off.
+
+`include "prim_assert.sv"
+
+module physical_pads
+ import prim_pad_wrapper_pkg::*;
+#(
+ parameter int NIoBanks = 4
+) (
+ output pad_pok_t [NIoBanks-1:0] pad_pok_o
+);
+
+ assign pad_pok_o = '0;
+
+endmodule : physical_pads
diff --git a/hw/top_sencha/util/vivado_hook_opt_design_post.tcl b/hw/top_sencha/util/vivado_hook_opt_design_post.tcl
new file mode 100644
index 0000000..98b7fad
--- /dev/null
+++ b/hw/top_sencha/util/vivado_hook_opt_design_post.tcl
@@ -0,0 +1,33 @@
+# Copyright 2024 Google LLC
+# Copyright 2023 lowRISC contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Hook to check BRAM implementation for Boot ROM. This is required for Boot ROM splicing.
+
+send_msg "Designcheck 2-1" INFO "Checking if Boot ROM is mapped to BRAM."
+
+if {[catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_0" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_1" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_2" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_3" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_4" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_5" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_6" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_7" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_8" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]]\
+ && [catch [get_cells -hierarchical -filter { NAME =~ "*u_rom_ctrl*u_rom*rdata_o_reg_9" && PRIMITIVE_TYPE =~ BLOCKRAM.*.* }]] } {
+ send_msg "Designcheck 2-2" INFO "BRAM implementation found for Boot ROM."
+} else {
+ send_msg "Designcheck 2-3" ERROR "BRAM implementation not found for Boot ROM."
+}
diff --git a/hw/top_sencha/util/vivado_hook_synth_design_pre.tcl b/hw/top_sencha/util/vivado_hook_synth_design_pre.tcl
new file mode 100644
index 0000000..c8cb74e
--- /dev/null
+++ b/hw/top_sencha/util/vivado_hook_synth_design_pre.tcl
@@ -0,0 +1,34 @@
+# Copyright 2024 Google LLC
+# Copyright lowRISC contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Change the severity of some messages.
+
+# Abort if the boot ROM init file cannot be found. This is normally just a critical warning
+# which is easily overlooked. The bitstream can still be generated but is not functional.
+set_msg_config -id {[Synth 8-4445]} -new_severity ERROR
+
+# Abort upon inferring latches. This is normally just a warning. We want to avoid that
+# code inferring latches ends up in the repo in the first place.
+set_msg_config -id {[Synth 8-327]} -new_severity ERROR
+
+# Abort if a create_clock command fails. This typically happens if anchor points for clock
+# constraints inside the design change. The failure is normally just reported as a critical
+# warning in batch mode which is easily overlooked. The design might still work but some clocks
+# will be unconstrained which can lead to other problems later on.
+set_msg_config -id {[Vivado 12-4739]} -new_severity ERROR
+
+# Abort if pblock constraints lose their target cells. This can happen if hierarchies change and
+# the constraint doesn't get updated.
+set_msg_config -id {[Vivado 12-1433]} -new_severity ERROR
diff --git a/hw/top_sencha/util/vivado_hook_write_bitstream_pre.tcl b/hw/top_sencha/util/vivado_hook_write_bitstream_pre.tcl
new file mode 100644
index 0000000..2f87a1f
--- /dev/null
+++ b/hw/top_sencha/util/vivado_hook_write_bitstream_pre.tcl
@@ -0,0 +1,197 @@
+# Copyright 2024 Google LLC
+# Copyright lowRISC contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+send_msg "Designcheck 1-1" INFO "Checking design"
+
+# Ensure the design meets timing
+set slack_ns [get_property SLACK [get_timing_paths -delay_type min_max]]
+send_msg "Designcheck 1-2" INFO "Slack is ${slack_ns} ns."
+
+if {
+ [info exists ::env(VIVADO_FAIL_ON_TIMING)]
+ && $::env(VIVADO_FAIL_ON_TIMING) != 0
+} then {
+ if [expr {$slack_ns < 0}] {
+ send_msg "Designcheck 1-3" ERROR "Timing failed. Slack is ${slack_ns} ns."
+ }
+}
+# Write additional reports
+report_utilization -cells [get_cells top_sencha/u_ml_top/u_kelvin] -file utilization_kelvin.rpt
+
+
+# Enable bitstream identification via USR_ACCESS register.
+set_property BITSTREAM.CONFIG.USR_ACCESS TIMESTAMP [current_design]
+
+# Generate an MMI file for the given BRAM cells.
+#
+# Args:
+# filename: Path to the output file.
+# brams: A list of BRAM cells.
+# mem_type: The BRAM type, e.g. "RAMB36".
+# fake_word_width: If non-zero, pretend that $brams covers
+# `fake_word_width` bits. Influences the values of the
+# MMI's <AddressSpace> and <DataWidth> tags.
+# addr_end_multiplier: A coefficient applied to the address space. Influences
+# the values of the MMI's <AddressSpace> and
+# <AddressRange> tags.
+# designtask_count: A number used for logging with `send_msg`.
+proc generate_mmi {filename brams mem_type fake_word_width addr_end_multiplier designtask_count} {
+ send_msg "${designtask_count}-1" INFO "Dumping MMI to ${filename}"
+
+ if {[llen $brams] == 0} {
+ send_msg "${designtask_count}-1" INFO "Cannot make MMI for zero BRAMs"
+ return
+ }
+
+ set workroot [file dirname [info script]]
+ set filepath "${workroot}/${filename}"
+ set fileout [open $filepath "w"]
+
+ set fake_slice_width [expr $fake_word_width / [llen $brams]]
+
+ # Calculate the overall address space.
+ set space 0
+ foreach inst [lsort -dictionary $brams] {
+ set slice_begin [get_property ram_slice_begin [get_cells $inst]]
+ set slice_end [get_property ram_slice_end [get_cells $inst]]
+ if {$slice_begin eq {} || $slice_end eq {}} {
+ send_msg "${designtask_count}-2" ERROR "Extraction of ${filename} information failed."
+ }
+ set slice_width [expr {$slice_end - $slice_begin + 1}]
+ if {$slice_width < $fake_slice_width} {
+ set slice_end [expr {$slice_begin + $fake_slice_width - 1}]
+ set slice_width $fake_slice_width
+ }
+ set addr_begin [get_property ram_addr_begin [get_cells $inst]]
+ set addr_end [get_property ram_addr_end [get_cells $inst]]
+ if {$addr_begin eq {} || $addr_end eq {}} {
+ send_msg "${designtask_count}-3" ERROR "Extraction of ${filename} MMI information failed."
+ }
+
+ # Calculate total number of bits.
+ set space [expr {$space + ($addr_end - $addr_begin + 1) * $slice_width}]
+ set last_slice_width $slice_width
+ }
+ set space [expr {($space * $addr_end_multiplier / 8) - 1}]
+
+ # Generate the MMI.
+ puts $fileout "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ puts $fileout "<MemInfo Version=\"1\" Minor=\"1\">"
+ puts $fileout " <Processor Endianness=\"Little\" InstPath=\"dummy\">"
+ puts $fileout " <AddressSpace Name=\"dummy_addrspace\" Begin=\"0\" End=\"$space\">"
+ puts $fileout " <BusBlock>"
+
+ set loc_prefix "${mem_type}_"
+
+ set part [get_property PART [current_design]]
+ foreach inst [lsort -dictionary $brams] {
+ set loc [get_property LOC [get_cells $inst]]
+ set loc [string trimleft $loc $loc_prefix]
+ set slice_begin [get_property ram_slice_begin [get_cells $inst]]
+ set slice_end [get_property ram_slice_end [get_cells $inst]]
+ set slice_width [expr {$slice_end - $slice_begin + 1}]
+ if {$slice_width < $fake_slice_width} {
+ set slice_end [expr {$slice_begin + $fake_slice_width - 1}]
+ set slice_width $fake_slice_width
+ }
+ set addr_begin [get_property ram_addr_begin [get_cells $inst]]
+ set addr_end [get_property ram_addr_end [get_cells $inst]]
+ set addr_end [expr {($addr_end + 1) * $addr_end_multiplier - 1}]
+ puts $fileout " <BitLane MemType=\"$mem_type\" Placement=\"$loc\">"
+ puts $fileout " <DataWidth MSB=\"$slice_end\" LSB=\"$slice_begin\"/>"
+ puts $fileout " <AddressRange Begin=\"$addr_begin\" End=\"$addr_end\"/>"
+ puts $fileout " <Parity ON=\"false\" NumBits=\"0\"/>"
+ puts $fileout " </BitLane>"
+ }
+ puts $fileout " </BusBlock>"
+ puts $fileout " </AddressSpace>"
+ puts $fileout " </Processor>"
+ puts $fileout "<Config>"
+ puts $fileout " <Option Name=\"Part\" Val=\"$part\"/>"
+ puts $fileout "</Config>"
+ puts $fileout "</MemInfo>"
+ close $fileout
+ send_msg "${designtask_count}-4" INFO "MMI dumped to ${filepath}"
+}
+
+# Dump INIT_XX strings for the given BRAMs to an output file.
+#
+# In the output file, the BRAMs and their INIT_XX strings will be sorted in
+# increasing order. This proc is a time-saver because the Vivado GUI's property
+# viewer does not sort the INIT_XX strings numerically.
+#
+# Args:
+# filename: Where to write
+# brams: A list of BRAM cells.
+# designtask_count: A number used for logging with `send_msg`.
+proc dump_init_strings {filename brams designtask_count} {
+ # For each OTP BRAM, dump all the INIT_XX strings.
+ send_msg "${designtask_count}-1" INFO "Dumping INIT_XX strings to ${filename}"
+
+ set workroot [file dirname [info script]]
+ set filepath "${workroot}/${filename}"
+ set fileout [open $filepath "w"]
+
+ foreach inst [lsort -dictionary $brams] {
+ set bram [get_cells $inst]
+
+ set loc [get_property LOC $bram]
+ puts $fileout "LOC: $loc"
+
+ set init_count 0
+ while 1 {
+ set key [format "INIT_%.2X" $init_count]
+ if { [llength [list_property $bram $key]] eq 0 } {
+ break
+ }
+ set val [get_property $key $bram]
+ puts $fileout "$key $val"
+ incr init_count
+ }
+
+ puts $fileout ""
+ }
+ close $fileout
+ send_msg "${designtask_count}-4" INFO "INIT_XX strings dumped to ${filepath}"
+}
+
+# The scrambled Boot ROM is actually 39 bits wide, but we need to pretend that
+# it's 40 bits, or else we will be unable to encode our ROM data in a MEM file
+# that updatemem will understand.
+#
+# Suppose we did not pad the width, leaving it at 39 bits. Now, if we encode a
+# word as a 10-digit hex string, updatemem would splice an additional zero bit
+# into the bitstream because each hex digit is strictly 4 bits. If we wrote four
+# words at a time, as a 39-digit hex string (39*4 is nicely divisible by 4),
+# updatemem would fail to parse the hex string, saying something like "Data
+# segment starting at 0x00000000, has exceeded data limits." The longest hex
+# string it will accept is 16 digits, or 64 bits.
+#
+# A hack that works is to pretend the data width is actually 40 bits. Updatemem
+# seems to write that extra zero bit into the ether without complaint.
+set rom_brams [split [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ BLOCKRAM.BRAM.* && NAME =~ *u_rom_ctrl*}] " "]
+generate_mmi "rom.mmi" $rom_brams "RAMB36" 40 1 1
+
+# OTP does not require faking the word width, but it has its own quirk. It seems
+# each 22-bit OTP word is followed by 15 zero words. The MMI's <AddressSpace>
+# and <AddressRange> tags need to account for this or else updatemem will think
+# that its data input overruns the address space. The workaround is to pretend
+# the address space is 16 times larger than we would normally compute.
+set otp_brams [split [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ BLOCKRAM.BRAM.* && NAME =~ *u_otp_ctrl*}] " "]
+generate_mmi "otp.mmi" $otp_brams "RAMB18" 0 16 2
+
+# For debugging purposes, dump the INIT_XX strings for ROM and OTP.
+dump_init_strings "rom_init_strings.txt" $rom_brams 3
+dump_init_strings "otp_init_strings.txt" $otp_brams 4
diff --git a/hw/top_sencha/util/vivado_setup_hooks.tcl b/hw/top_sencha/util/vivado_setup_hooks.tcl
new file mode 100644
index 0000000..cd51615
--- /dev/null
+++ b/hw/top_sencha/util/vivado_setup_hooks.tcl
@@ -0,0 +1,45 @@
+# Copyright 2024 Google LLC
+# Copyright lowRISC contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Setup hook scripts, to be called at various stages during the build process
+# See Xilinx UG 894 ("Using Tcl Scripting") for documentation.
+
+# fusesoc-generated workroot containing the Vivado project file
+set workroot [pwd]
+
+# Pre synthesize design hook
+set_property STEPS.SYNTH_DESIGN.TCL.PRE "${workroot}/vivado_hook_synth_design_pre.tcl" [get_runs synth_1]
+
+# add placer directive for SLL balance due to congestion detected on SLR crossing.
+set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE SSI_BalanceSLLs [get_runs impl_1]
+
+# Post opt design hook
+# Following directive ExploreWithAggressiveHoldFix" will increase compile time a lot,
+# comment out for now just for future hold time debug reference.
+#set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE ExploreWithAggressiveHoldFix [get_runs impl_1]
+set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
+set_property -name {STEPS.PHYS_OPT_DESIGN.ARGS.MORE OPTIONS} -value -hold_fix -objects [get_runs impl_1]
+set_property STEPS.OPT_DESIGN.TCL.POST "${workroot}/vivado_hook_opt_design_post.tcl" [get_runs impl_1]
+
+# TODO: This hook is not getting called by Vivado when running through our
+# fusesoc flow (it gets called when writing a bitstream through the GUI).
+# Requires an update to edalize, see https://github.com/olofk/edalize/pull/60.
+#set_property STEPS.WRITE_BITSTREAM.TCL.PRE "${workroot}/vivado_hook_write_bitstream_pre.tcl" [get_runs impl_1]
+
+# As workaround, we use the post route design hook, which gets called.
+set_property STEPS.ROUTE_DESIGN.TCL.POST "${workroot}/vivado_hook_write_bitstream_pre.tcl" [get_runs impl_1]
+
+# Set synth.xdc to only be used for synthesis (initial implementation is to force URAM instead of BRAM)
+set_property used_in_implementation false [filter -regexp [get_files -of [get_filesets constrs_1]] {NAME=~".*\/synth.xdc"}]
diff --git a/rules/matcha.bzl b/rules/matcha.bzl
index 49fac79..9e1c1d6 100644
--- a/rules/matcha.bzl
+++ b/rules/matcha.bzl
@@ -88,10 +88,10 @@
inputs = [
src,
ctx.executable._scramble_tool,
- ctx.file._config,
+ ctx.file.config,
],
arguments = [
- ctx.file._config.path,
+ ctx.file.config.path,
src.path,
scrambled.path,
],
@@ -111,7 +111,7 @@
executable = True,
cfg = "exec",
),
- "_config": attr.label(
+ "config": attr.label(
default = "@//hw/top_matcha:top_gen_rom_ctrl_hjson",
allow_single_file = True,
),
@@ -174,6 +174,7 @@
Containing all targets across all devices for the above generated rules.
"""
deps = kwargs.pop("deps", [])
+ top_target = kwargs.pop("top_target", "matcha")
# Place the default copts first to allow per-target override.
copts = MATCHA_COPTS + kwargs.pop("copts", [])
@@ -216,12 +217,14 @@
# Generate Scrambled ROM VMEM
scr_vmem_name = "{}_scr_vmem".format(devname)
dev_targets.append(":" + scr_vmem_name)
+ top_gen_hjson_target = "@//hw/top_{}:top_gen_rom_ctrl_hjson".format(top_target)
elf_to_scrambled_rom_vmem(
name = scr_vmem_name,
srcs = [elf_name],
platform = platform,
testonly = testonly,
tags = tags,
+ config = top_gen_hjson_target,
)
# Create a filegroup with just the current device's targets.
diff --git a/rules/matcha_test.bzl b/rules/matcha_test.bzl
index 115413b..94030f7 100644
--- a/rules/matcha_test.bzl
+++ b/rules/matcha_test.bzl
@@ -26,7 +26,7 @@
sec_flash_binary,
smc_flash_binary = "@//sw/device/tests/smc:simple_smc",
ml_flash_binary = None,
- rom_img = "@//sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem",
+ rom_img = "@//sw/device/lib/testing/test_rom:matcha_test_rom_sim_verilator_scr_vmem",
otp_img = "@//hw/top_matcha/data:otp_img_rma",
verilator_testbench = "@//hw:matcha_verilator",
timeout = "moderate",
@@ -96,7 +96,7 @@
data = [],
local = True,
otp = "//hw/top_matcha/data:otp_img_rma",
- rom = "//sw/device/lib/testing/test_rom:test_rom_sim_dv_scr_vmem",
+ rom = "//sw/device/lib/testing/test_rom:matcha_test_rom_sim_dv_scr_vmem",
tags = [],
timeout = "moderate",
test_runner = "//util:dvsim_matcha_test_runner.sh",
diff --git a/sw/device/examples/hello_world/BUILD b/sw/device/examples/hello_world/BUILD
index 95bb48f..6c69df8 100644
--- a/sw/device/examples/hello_world/BUILD
+++ b/sw/device/examples/hello_world/BUILD
@@ -3,6 +3,9 @@
# SPDX-License-Identifier: Apache-2.0
load("//rules:matcha.bzl", "OPENTITAN_CPU", "sec_flash_binary")
+load("//rules:targets.bzl", "get_targets")
+
+TARGETS = get_targets()
sec_flash_binary(
name = "hello_world",
@@ -43,47 +46,47 @@
)
# Use shell test to run the interactive verilator test on UART and GPIO
-sh_test(
- name = "verilator_hello_world_test",
+[sh_test(
+ name = "{}_verilator_hello_world_test".format(target),
timeout = "long",
srcs = [":run_verilator_hello_world.sh"],
args = [
- "$(location //hw:matcha_verilator)",
- "$(location //sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem)",
+ "$(location //hw:{}_verilator)".format(target),
+ "$(location //sw/device/lib/testing/test_rom:{}_test_rom_sim_verilator_scr_vmem)".format(target),
"$(location :hello_world_sim_verilator_vmem)",
- "$(location //hw/top_matcha/data:otp_img_rma)",
+ "$(location //hw/top_{}/data:otp_img_rma)".format(target),
],
data = [
":hello_world_sim_verilator_vmem",
":hello_world_test_expected_gpio.txt",
- "//hw:matcha_verilator",
- "//hw/top_matcha/data:otp_img_rma",
- "//sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem",
+ "//hw:{}_verilator".format(target),
+ "//hw/top_{}/data:otp_img_rma".format(target),
+ "//sw/device/lib/testing/test_rom:{}_test_rom_sim_verilator_scr_vmem".format(target),
],
tags = [
"verilator",
],
visibility = ["//sw/device/tests:sw_device_test_group"],
-)
+) for target in TARGETS]
-sh_test(
- name = "verilator_hello_world_gpio_test",
+[sh_test(
+ name = "{}_verilator_hello_world_gpio_test".format(target),
timeout = "long",
srcs = [":run_verilator_hello_world.sh"],
args = [
- "$(location //hw:matcha_verilator)",
- "$(location //sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem)",
+ "$(location //hw:{}_verilator)".format(target),
+ "$(location //sw/device/lib/testing/test_rom:{}_test_rom_sim_verilator_scr_vmem)".format(target),
"$(location :hello_world_sim_verilator_vmem)",
- "$(location //hw/top_matcha/data:otp_img_rma)",
+ "$(location //hw/top_{}/data:otp_img_rma)".format(target),
"gpio_test",
],
data = [
":hello_world_sim_verilator_vmem",
- "//hw:matcha_verilator",
- "//hw/top_matcha/data:otp_img_rma",
- "//sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem",
+ "//hw:{}_verilator".format(target),
+ "//hw/top_{}/data:otp_img_rma".format(target),
+ "//sw/device/lib/testing/test_rom:{}_test_rom_sim_verilator_scr_vmem".format(target),
],
tags = [
"verilator",
],
-)
+) for target in TARGETS]
diff --git a/sw/device/lib/testing/test_rom/BUILD b/sw/device/lib/testing/test_rom/BUILD
index 4458399..6474063 100644
--- a/sw/device/lib/testing/test_rom/BUILD
+++ b/sw/device/lib/testing/test_rom/BUILD
@@ -3,75 +3,80 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
-load("//rules:matcha.bzl", "NEXUS_CORE_TARGETS", "OPENTITAN_CPU", "opentitan_rom_binary")
load("@lowrisc_opentitan//rules:autogen.bzl", "autogen_chip_info")
load("@lowrisc_opentitan//rules:linker.bzl", "ld_library")
+load("//rules:matcha.bzl", "NEXUS_CORE_TARGETS", "OPENTITAN_CPU", "opentitan_rom_binary")
+load("//rules:targets.bzl", "get_targets")
package(default_visibility = ["//visibility:public"])
+TARGETS = get_targets()
+
autogen_chip_info(
name = "chip_info",
version = "//util:matcha_version_file",
)
-ld_library(
- name = "linker_script",
- script = "test_rom.ld",
+[ld_library(
+ name = "{}_linker_script".format(target),
+ script = "{}_test_rom.ld".format(target),
deps = [
- "//hw/top_matcha/sw/autogen:top_matcha_memory",
+ "//hw/top_{}/sw/autogen:top_{}_memory".format(target, target),
"@lowrisc_opentitan//sw/device:info_sections",
"@lowrisc_opentitan//sw/device/silicon_creator/lib/base:static_critical_sections",
],
-)
+) for target in TARGETS]
-opentitan_rom_binary(
- name = "test_rom",
+[opentitan_rom_binary(
+ name = "{}_test_rom".format(target),
+ top_target = target,
deps = [
- ":linker_script",
- ":test_rom_otp_lib",
+ ":{}_linker_script".format(target),
+ ":{}_test_rom_otp_lib".format(target),
],
-)
+) for target in TARGETS]
-opentitan_rom_binary(
- name = "test_rom_no_otp",
+[opentitan_rom_binary(
+ name = "{}_test_rom_no_otp".format(target),
srcs = [
"test_rom.c",
"test_rom_start.S",
],
defines = ["OTP_IS_RAM"],
+ top_target = target,
deps = [
- ":linker_script",
- ":test_rom_lib",
- "@lowrisc_opentitan//sw/device/lib/crt",
+ ":{}_linker_script".format(target),
+ ":{}_test_rom_lib".format(target),
"//sw/device/silicon_creator/rom:bootstrap_no_otp",
+ "@lowrisc_opentitan//sw/device/lib/crt",
],
-)
+) for target in TARGETS]
-cc_library(
- name = "test_rom_otp_lib",
+[cc_library(
+ name = "{}_test_rom_otp_lib".format(target),
srcs = [
"test_rom.c",
"test_rom_start.S",
],
deps = [
- ":test_rom_lib",
- "@lowrisc_opentitan//sw/device/lib/crt",
+ ":{}_test_rom_lib".format(target),
"//sw/device/silicon_creator/rom:bootstrap",
+ "@lowrisc_opentitan//sw/device/lib/crt",
],
-)
+) for target in TARGETS]
-cc_library(
- name = "test_rom_lib",
+[cc_library(
+ name = "{}_test_rom_lib".format(target),
srcs = [
],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":chip_info",
- "//hw/top_matcha:ast_regs",
- "//hw/top_matcha:clkmgr_regs",
- "//hw/top_matcha/sw:top_matcha",
- "//hw/top_matcha/ip/flash_ctrl/data/autogen:flash_ctrl_regs",
- "//hw/top_matcha/ip/sensor_ctrl/data:sensor_ctrl_regs",
+ "//hw/top_{}:ast_regs".format(target),
+ "//hw/top_{}:clkmgr_regs".format(target),
+ "//hw/top_{}/sw:top_{}".format(target, target),
+ "//hw/top_{}/ip/flash_ctrl/data/autogen:flash_ctrl_regs".format(target),
+ "//hw/top_{}/ip/sensor_ctrl/data:sensor_ctrl_regs".format(target),
"//sw/device/lib:spi_flash",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/testing:pinmux_testutils",
@@ -106,30 +111,31 @@
"@lowrisc_opentitan//sw/device/silicon_creator/lib/drivers:flash_ctrl",
"@lowrisc_opentitan//sw/device/silicon_creator/lib/drivers:retention_sram",
],
-)
+) for target in TARGETS]
-ld_library(
- name = "puppeteer_linker_script",
- script = "puppeteer_rom.ld",
+[ld_library(
+ name = "{}_puppeteer_linker_script".format(target),
+ script = "{}_puppeteer_rom.ld".format(target),
deps = [
- "//hw/top_matcha/sw/autogen:top_matcha_memory",
+ "//hw/top_{}/sw/autogen:top_{}_memory".format(target, target),
],
-)
+) for target in TARGETS]
# Only build for nexus FPGA.
-opentitan_rom_binary(
- name = "puppeteer_rom",
+[opentitan_rom_binary(
+ name = "{}_puppeteer_rom".format(target),
per_device_deps = {
"fpga_nexus": [NEXUS_CORE_TARGETS.get("secure_core")],
},
+ top_target = target,
deps = [
- ":puppeteer_linker_script",
- ":puppeteer_rom_lib",
+ ":{}_puppeteer_linker_script".format(target),
+ ":{}_puppeteer_rom_lib".format(target),
],
-)
+) for target in TARGETS]
-cc_library(
- name = "puppeteer_rom_lib",
+[cc_library(
+ name = "{}_puppeteer_rom_lib".format(target),
srcs = [
"puppeteer.cc",
"puppeteer_rom.cc",
@@ -145,11 +151,11 @@
],
target_compatible_with = [OPENTITAN_CPU],
deps = [
- "//hw/top_matcha:ast_regs",
- "//hw/top_matcha:clkmgr_regs",
- "//hw/top_matcha:pinmux_regs",
- "//hw/top_matcha/sw:top_matcha",
- "//hw/top_matcha/ip/sensor_ctrl/data:sensor_ctrl_regs",
+ "//hw/top_{}:ast_regs".format(target),
+ "//hw/top_{}:clkmgr_regs".format(target),
+ "//hw/top_{}:pinmux_regs".format(target),
+ "//hw/top_{}/sw:top_{}".format(target, target),
+ "//hw/top_{}/ip/sensor_ctrl/data:sensor_ctrl_regs".format(target),
"//sw/device/lib/testing/test_rom/puppeteer_utils",
"@lowrisc_opentitan//hw/ip/csrng/data:csrng_regs",
"@lowrisc_opentitan//hw/ip/edn/data:edn_regs",
@@ -163,18 +169,13 @@
"@lowrisc_opentitan//sw/device/silicon_creator/lib:manifest",
"@lowrisc_opentitan//sw/device/silicon_creator/lib/drivers:flash_ctrl",
],
-)
+) for target in TARGETS]
# Only build for CHERIoT targets. Requires that bazel be invoked with
# --config=cheriot-baremetal --copt=-D_CHERIOT_BAREMETAL_=1
# so that all dependencies use those options.
opentitan_rom_binary(
name = "test_rom_no_otp_cheri",
- visibility = ["//visibility:private"],
- # NB: fpga_nexus is used for renode sims
- per_device_deps = {
- "fpga_nexus": [NEXUS_CORE_TARGETS.get("secure_core")],
- },
srcs = [
"test_rom_cheri.c",
"test_rom_start_cheri.S",
@@ -182,15 +183,20 @@
"crt_cheri.S",
],
defines = ["OTP_IS_RAM"],
- deps = [
- ":linker_script_cheri",
- ":baremetal_lib",
- ":test_rom_lib",
- "//sw/device/silicon_creator/rom:bootstrap_no_otp",
- ],
+ # NB: fpga_nexus is used for renode sims
+ per_device_deps = {
+ "fpga_nexus": [NEXUS_CORE_TARGETS.get("secure_core")],
+ },
tags = [
"cheri",
],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":baremetal_lib",
+ ":linker_script_cheri",
+ ":sencha_test_rom_lib",
+ "//sw/device/silicon_creator/rom:bootstrap_no_otp",
+ ],
)
cc_library(
@@ -202,14 +208,14 @@
ld_library(
name = "linker_script_cheri",
- visibility = ["//visibility:private"],
script = "test_rom_cheri.ld",
+ tags = [
+ "cheri",
+ ],
+ visibility = ["//visibility:private"],
deps = [
"//hw/top_matcha/sw/autogen:top_matcha_memory_cheri",
"@lowrisc_opentitan//sw/device:info_sections",
"@lowrisc_opentitan//sw/device/silicon_creator/lib/base:static_critical_sections",
],
- tags = [
- "cheri",
- ],
)
diff --git a/sw/device/lib/testing/test_rom/puppeteer_rom.ld b/sw/device/lib/testing/test_rom/matcha_puppeteer_rom.ld
similarity index 100%
rename from sw/device/lib/testing/test_rom/puppeteer_rom.ld
rename to sw/device/lib/testing/test_rom/matcha_puppeteer_rom.ld
diff --git a/sw/device/lib/testing/test_rom/test_rom.ld b/sw/device/lib/testing/test_rom/matcha_test_rom.ld
similarity index 100%
rename from sw/device/lib/testing/test_rom/test_rom.ld
rename to sw/device/lib/testing/test_rom/matcha_test_rom.ld
diff --git a/sw/device/lib/testing/test_rom/sencha_puppeteer_rom.ld b/sw/device/lib/testing/test_rom/sencha_puppeteer_rom.ld
new file mode 100644
index 0000000..fab76a1
--- /dev/null
+++ b/sw/device/lib/testing/test_rom/sencha_puppeteer_rom.ld
@@ -0,0 +1,177 @@
+/* Copyright 2023 Google LLC */
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/**
+ * Linker script for an OpenTitan boot ROM.
+ *
+ * Portions of this file are Ibex-specific.
+ */
+
+OUTPUT_ARCH(riscv)
+/**
+ * Don't build with gcc.
+ * GROUP(-lgcc)
+*/
+
+/**
+ * Indicate that there are no dynamic libraries, whatsoever.
+ */
+__DYNAMIC = 0;
+
+INCLUDE hw/top_sencha/sw/autogen/top_sencha_memory.ld
+
+/**
+ * The boot address, which indicates the location of the initial interrupt
+ * vector.
+ */
+ ENTRY(_reset_start);
+_boot_address = ORIGIN(rom);
+
+_heap_size = 0xe000;
+_stack_size = LENGTH(ram_main) - _heap_size;
+_stack_end = ORIGIN(ram_main) + LENGTH(ram_main);
+_stack_start = _stack_end - _stack_size;
+_flash_start = ORIGIN(eflash);
+
+/**
+ * This symbol points at the header of the flash binary, which contains loading
+ * and signing information.
+ */
+_flash_header = _flash_start;
+
+_chip_info_size = 128;
+_chip_info_start = ORIGIN(rom) + LENGTH(rom) - _chip_info_size;
+
+/**
+ * NOTE: We have to align each section to word boundaries as our current
+ * s19->slm conversion scripts are not able to handle non-word aligned sections.
+ */
+SECTIONS {
+ /**
+ * Ibex interrupt vector. See test_rom_start.S for more information.
+ *
+ * This has to be set up at the boot address, so that execution jumps to the
+ * reset handler correctly.
+ */
+ .vectors _boot_address : ALIGN(4) {
+ KEEP(*(.vectors))
+ } > rom
+
+ /**
+ * C runtime (CRT) section, containing program initialization code.
+ */
+ .crt : ALIGN(4) {
+ KEEP(*(.crt))
+ } > rom
+
+ /**
+ * Standard text section, containing program code.
+ */
+ .text : ALIGN(4) {
+ *(.text)
+ *(.text.*)
+ } > rom
+
+ /**
+ * Read-only data section, containing all large compile-time constants, like
+ * strings.
+ */
+ .rodata : ALIGN(4) {
+ /* Small read-only data comes before regular read-only data for the same
+ * reasons as in the data section */
+ *(.srodata)
+ *(.srodata.*)
+ *(.rodata)
+ *(.rodata.*)
+ } > rom
+
+ /**
+ * "Intitial data" section, the initial values of the mutable data section
+ * initialized at runtime.
+ */
+ .idata : ALIGN(4) {
+ _data_init_start = .;
+ } > rom
+
+ /**
+ * Standard mutable data section, at the bottom of RAM. This will be
+ * initialized from the .idata section at runtime by the CRT.
+ */
+ .data ORIGIN(ram_main): AT(_data_init_start) ALIGN(4) {
+ _data_start = .;
+ __global_pointer$ = . + 2048;
+
+ /* Small data should come before larger data. This helps to ensure small
+ * globals are within 2048 bytes of the value of `gp`, making their accesses
+ * hopefully only take one instruction. */
+ *(.sdata)
+ *(.sdata.*)
+
+ /* Other data will likely need multiple instructions to load, so we're less
+ * concerned about address materialisation taking more than one instruction.
+ */
+ *(.data)
+ *(.data.*)
+ . = ALIGN(4);
+ _data_end = .;
+ } > ram_main
+
+ /**
+ * Immutable chip_info data, containing build-time-recorded information.
+ */
+ .chip_info _chip_info_start : ALIGN(4) {
+ *(.chip_info)
+ } > rom
+
+ /**
+ * Standard BSS section. This will be zeroed at runtime by the CRT.
+ */
+ .bss : ALIGN(4) {
+ _bss_start = .;
+ /* Small BSS comes before regular BSS for the same reasons as in the data
+ * section */
+ *(.sbss)
+ *(.sbss.*)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ _bss_end = .;
+ } > ram_main
+
+ /**
+ * STAB debug table.
+ */
+ .stab 0x0 (NOLOAD): {
+ [.stab]
+ }
+
+ /**
+ * STAB debug strings.
+ */
+ .stabstr 0x0 (NOLOAD): {
+ [.stabstr]
+ }
+
+ /**
+ * The following sections are used by DV to implement logging in an
+ * alternate way, which enables simulation speed up by completely avoiding
+ * any string format processing or even the actual transmission of log data
+ * to a real peripheral.
+ *
+ * These sections are marked as dummy so that they can still be extracted
+ * using readelf or similar utilities. As such, the content in these sections
+ * is not relevant for the actual SW code and can be safely discarded.
+ */
+
+ /**
+ * The following section contains log fields constructed from the logs using
+ * the log_fields_t struct defined in sw/device/lib/runtime/log.h. The size of
+ * each log field is fixed - 20 bytes, which is used as the delimiter.
+ */
+ .logs.fields 0x0 (DSECT): {
+ *(.logs.fields)
+ }
+}
diff --git a/sw/device/lib/testing/test_rom/sencha_test_rom.ld b/sw/device/lib/testing/test_rom/sencha_test_rom.ld
new file mode 100644
index 0000000..61fc735
--- /dev/null
+++ b/sw/device/lib/testing/test_rom/sencha_test_rom.ld
@@ -0,0 +1,165 @@
+/* Copyright 2024 Google LLC. */
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/**
+ * Linker script for an OpenTitan (test) boot ROM.
+ *
+ * Portions of this file are Ibex-specific.
+ */
+
+OUTPUT_ARCH(riscv)
+
+/**
+ * Indicate that there are no dynamic libraries, whatsoever.
+ */
+__DYNAMIC = 0;
+
+INCLUDE hw/top_sencha/sw/autogen/top_sencha_memory.ld
+
+/**
+ * The boot address, which indicates the location of the initial interrupt
+ * vector.
+ */
+_boot_address = ORIGIN(rom);
+
+/**
+ * Symbols to be used in the setup of the address translation for ROM_EXT.
+ */
+
+/**
+ * This symbol points at the manifest of the OTTF + test binary, which contains
+ * loading and signing information.
+ *
+ * See `sw/device/lib/testing/test_framework/ottf.ld`, under the
+ * .manifest section, which populates it.
+ */
+_rom_ext_virtual_start_address = ORIGIN(rom_ext_virtual);
+_rom_ext_virtual_size = LENGTH(rom_ext_virtual);
+ASSERT((_rom_ext_virtual_size <= (LENGTH(eflash) / 2)),
+ "Error: rom ext flash is bigger than slot.");
+
+_rom_digest_size = 32;
+_chip_info_start = ORIGIN(rom) + LENGTH(rom) - _rom_digest_size - _chip_info_size;
+
+/* DV Log offset (has to be different to other boot stages). */
+_dv_log_offset = 0x0;
+
+/**
+ * We define an entry point only for documentation purposes (and to stop LLD
+ * erroring). In reality, we don't use this information within the ROM image, as
+ * we start at a fixed offset.
+ */
+ENTRY(_reset_start);
+
+/**
+ * NOTE: We have to align each section to word boundaries as our current
+ * s19->slm conversion scripts are not able to handle non-word aligned sections.
+ */
+SECTIONS {
+ /**
+ * Ibex interrupt vector. See test_rom_start.S for more information.
+ *
+ * This has to be set up at the boot address, so that execution jumps to the
+ * reset handler correctly.
+ */
+ .vectors _boot_address : ALIGN(4) {
+ KEEP(*(.vectors))
+ } > rom
+
+ /**
+ * C runtime (CRT) section, containing program initialization code.
+ */
+ .crt : ALIGN(4) {
+ KEEP(*(.crt))
+ } > rom
+
+ /**
+ * Standard text section, containing program code.
+ */
+ .text : ALIGN(4) {
+ *(.text)
+ *(.text.*)
+ } > rom
+
+ /**
+ * Read-only data section, containing all large compile-time constants, like
+ * strings.
+ */
+ .rodata : ALIGN(4) {
+ /* Small read-only data comes before regular read-only data for the same
+ * reasons as in the data section */
+ *(.srodata)
+ *(.srodata.*)
+ *(.rodata)
+ *(.rodata.*)
+ } > rom
+
+ /**
+ * Critical static data that is accessible by both the ROM and the ROM
+ * extension.
+ */
+ INCLUDE external/lowrisc_opentitan/sw/device/silicon_creator/lib/base/static_critical.ld
+
+ /**
+ * Standard mutable data section, at the bottom of RAM. This will be
+ * initialized from the .idata section at runtime by the CRT.
+ */
+ .data : ALIGN(4) {
+ _data_start = .;
+ _data_init_start = LOADADDR(.data);
+
+ /* This will get loaded into `gp`, and the linker will use that register for
+ * accessing data within [-2048,2047] of `__global_pointer$`.
+ *
+ * This is much cheaper (for small data) than materializing the
+ * address and loading from that (which will take one extra instruction). */
+ __global_pointer$ = . + 2048;
+
+ /* Small data should come before larger data. This helps to ensure small
+ * globals are within 2048 bytes of the value of `gp`, making their accesses
+ * hopefully only take one instruction. */
+ *(.sdata)
+ *(.sdata.*)
+
+ /* Other data will likely need multiple instructions to load, so we're less
+ * concerned about address materialisation taking more than one instruction.
+ */
+ *(.data)
+ *(.data.*)
+
+ /* Ensure section end is word-aligned. */
+ . = ALIGN(4);
+ _data_end = .;
+ _data_init_end = LOADADDR(.data) + SIZEOF(.data);
+
+ /* This puts it in ram_main at runtime (for the VMA), but puts the section
+ * into rom for load time (for the LMA). This is why `_data_init_*` uses
+ * `LOADADDR`. */
+ } > ram_main AT> rom
+
+ /**
+ * Immutable chip_info data, containing build-time-recorded information.
+ */
+ .chip_info _chip_info_start : ALIGN(4) {
+ KEEP(*(.chip_info))
+ } > rom
+
+ /**
+ * Standard BSS section. This will be zeroed at runtime by the CRT.
+ */
+ .bss : ALIGN(4) {
+ _bss_start = .;
+ /* Small BSS comes before regular BSS for the same reasons as in the data
+ * section */
+ *(.sbss)
+ *(.sbss.*)
+ *(.bss)
+ *(.bss.*)
+ . = ALIGN(4);
+ _bss_end = .;
+ } > ram_main
+
+ INCLUDE external/lowrisc_opentitan/sw/device/info_sections.ld
+}
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 6316d7d..0f5d0f7 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -700,7 +700,7 @@
"verilator_supervisor_mode_test",
"verilator_tlul_mailbox_test",
"verilator_virtual_memory_test",
- "//sw/device/examples/hello_world:verilator_hello_world_test",
+ "//sw/device/examples/hello_world:matcha_verilator_hello_world_test",
"//sw/device/tests/smc:verilator_kelvin_checksum_test",
"//sw/device/tests/smc:verilator_kelvin_hello_test",
"//sw/device/tests/smc:verilator_ml_top_irq_test",
@@ -735,8 +735,8 @@
test_in_rom = True,
deps = [
":test_lib_base",
- "//sw/device/lib/testing/test_rom:linker_script",
- "//sw/device/lib/testing/test_rom:test_rom_otp_lib",
+ "//sw/device/lib/testing/test_rom:matcha_linker_script",
+ "//sw/device/lib/testing/test_rom:matcha_test_rom_otp_lib",
],
)