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", ], )