From 0dd047fa72cc30b4d3c4c0c336a1bdbef3acbc3b Mon Sep 17 00:00:00 2001 From: Nathanael Huffman Date: Tue, 19 Nov 2024 15:59:12 -0600 Subject: [PATCH] Git SHA gen and common info block --- .github/workflows/build.yml | 2 +- hdl/ip/vhd/espi/sys_regs/espi_regs.rdl | 2 +- hdl/ip/vhd/info/BUCK | 52 ++++++++ hdl/ip/vhd/info/info.vhd | 61 +++++++++ hdl/ip/vhd/info/info_2k8.vhd | 145 +++++++++++++++++++++ hdl/ip/vhd/info/info_regs.rdl | 70 ++++++++++ hdl/projects/grapefruit/BUCK | 1 + hdl/projects/grapefruit/grapefruit_top.vhd | 9 +- toolchains/BUCK | 6 + tools/vhdl-ls.bxl | 29 ++++- 10 files changed, 369 insertions(+), 8 deletions(-) create mode 100644 hdl/ip/vhd/info/BUCK create mode 100644 hdl/ip/vhd/info/info.vhd create mode 100644 hdl/ip/vhd/info/info_2k8.vhd create mode 100644 hdl/ip/vhd/info/info_regs.rdl diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb166619..62c7345b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: bsv-streams: needs: changes - if: ${{ needs.changes.outputs.buck2 == 'true' }} + if: ${{ needs.changes.outputs.cobble == 'true' }} runs-on: self-hosted steps: - run: echo "The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." diff --git a/hdl/ip/vhd/espi/sys_regs/espi_regs.rdl b/hdl/ip/vhd/espi/sys_regs/espi_regs.rdl index 9fbeca0c..221995d1 100644 --- a/hdl/ip/vhd/espi/sys_regs/espi_regs.rdl +++ b/hdl/ip/vhd/espi/sys_regs/espi_regs.rdl @@ -1,5 +1,5 @@ // Copyright 2024 Oxide Computer Company -// This is SystemRDL description of the sw-accesible registers in the Gimlet +// This is SystemRDL description of the sw-accessible registers in the Gimlet // Sequencer FPGA. addrmap espi_regs { diff --git a/hdl/ip/vhd/info/BUCK b/hdl/ip/vhd/info/BUCK new file mode 100644 index 00000000..3bc48b41 --- /dev/null +++ b/hdl/ip/vhd/info/BUCK @@ -0,0 +1,52 @@ +load("//tools:hdl.bzl", "vhdl_unit", "vunit_sim") +load("//tools:rdl.bzl", "rdl_file") + +rdl_file( + name = "info_regs_pkg", + src = "info_regs.rdl", + outputs = ["info_regs_pkg.vhd", "info_regs.html"], + visibility = ['PUBLIC'] +) + +# Janky generate git sha via genrule +# There are a lot of better ways this might be done, but this was the simplest. +# It does mean there's a re-build for any change to the git repo, but for now that's fine. +# Longer-term, we might evaluate backannotating ROMs or something with this build info +genrule( + name = "git_sha", + out = "git_sha_pkg.vhd", + default_outs = ["git_sha_pkg.vhd"], + cmd = '''echo "library ieee;\nuse ieee.std_logic_1164.all;\npackage git_sha_pkg is\n constant short_sha : std_logic_vector(31 downto 0) := X\\""`git rev-parse --short=8 HEAD`\\"";\nend package git_sha_pkg;\" > $OUT''', + +) + +vhdl_unit( + name = "git_sha_pkg", + srcs = [":git_sha"], + visibility = ['PUBLIC'] +) + +# 2008-based signals in the this block +vhdl_unit( + name = "info_2k8", + srcs = ["info_2k8.vhd"], + deps = [ + ":git_sha_pkg", + ":info_regs_pkg", + ], + standard = "2008", + visibility = ['PUBLIC'] +) + +# Wrapping previous block in a 2019-compatible block using +# axi interfaces +vhdl_unit( + name = "info", + srcs = ["info.vhd"], + deps = [ + ":info_2k8", + "//hdl/ip/vhd/axi_blocks:axilite_common_pkgs", + ], + standard = "2019", + visibility = ['PUBLIC'] +) \ No newline at end of file diff --git a/hdl/ip/vhd/info/info.vhd b/hdl/ip/vhd/info/info.vhd new file mode 100644 index 00000000..054cfaf8 --- /dev/null +++ b/hdl/ip/vhd/info/info.vhd @@ -0,0 +1,61 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +-- +-- Copyright 2024 Oxide Computer Company + +-- 2019-compatible wrapper for basic board information registers + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.numeric_std_unsigned.all; +use work.axil8x32_pkg.all; + +entity info is + generic( + hubris_compat_num_bits: positive range 1 to 31; + ); + port ( + clk : in std_logic; + reset : in std_logic; + -- System Interface + hubris_compat_pins: in std_logic_vector(hubris_compat_num_bits-1 downto 0); + -- axi interface. This is not using VHDL2019 views so that it's compatible with + -- GHDL/yosys based toolchains + axi_if : view axil_target; + + + ); +end entity; + +architecture rtl of info is + +begin + info_inst: entity work.info_2k8 + generic map( + hubris_compat_num_bits => hubris_compat_num_bits + ) + port map( + clk => clk, + reset => reset, + hubris_compat_pins => hubris_compat_pins, + awvalid => axi_if.write_address.valid, + awready => axi_if.write_address.ready, + awaddr => axi_if.write_address.addr, + wvalid => axi_if.write_data.valid, + wready => axi_if.write_data.ready, + wdata => axi_if.write_data.data, + wstrb => axi_if.write_data.strb, + bvalid => axi_if.write_response.valid, + bready => axi_if.write_response.ready, + bresp => axi_if.write_response.resp, + arvalid => axi_if.read_address.valid, + arready => axi_if.read_address.ready, + araddr => axi_if.read_address.addr, + rvalid => axi_if.read_data.valid, + rready => axi_if.read_data.ready, + rdata => axi_if.read_data.data, + rresp => axi_if.read_data.resp + ); +end rtl; diff --git a/hdl/ip/vhd/info/info_2k8.vhd b/hdl/ip/vhd/info/info_2k8.vhd new file mode 100644 index 00000000..8dcbd598 --- /dev/null +++ b/hdl/ip/vhd/info/info_2k8.vhd @@ -0,0 +1,145 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +-- +-- Copyright 2024 Oxide Computer Company + +-- Common register block for basic board information + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.numeric_std_unsigned.all; + +use work.info_regs_pkg.all; +use work.git_sha_pkg.all; + +entity info_2k8 is + generic( + hubris_compat_num_bits: positive range 1 to 31 + ); + port ( + clk : in std_logic; + reset : in std_logic; + -- System Interface + hubris_compat_pins: in std_logic_vector(hubris_compat_num_bits-1 downto 0); + -- axi interface. This is not using VHDL2019 views so that it's compatible with + -- GHDL/yosys based toolchains + -- write address channel + awvalid : in std_logic; + awready : out std_logic; + awaddr : in std_logic_vector(7 downto 0) ; + -- write data channel + wvalid : in std_logic; + wready : out std_logic; + wdata : in std_logic_vector(31 downto 0); + wstrb : in std_logic_vector(3 downto 0); -- un-used + -- write response channel + bvalid : out std_logic; + bready : in std_logic; + bresp : out std_logic_vector(1 downto 0); + -- read address channel + arvalid : in std_logic; + arready : out std_logic; + araddr : in std_logic_vector(7 downto 0); + -- read data channel + rvalid : out std_logic; + rready : in std_logic; + rdata : out std_logic_vector(31 downto 0); + rresp : out std_logic_vector(1 downto 0) + + + ); +end entity; + +architecture rtl of info_2k8 is + constant OKAY : std_logic_vector(1 downto 0) := "00"; + signal axi_int_read_ready : std_logic; + + constant identity : identity_type := rec_reset; + constant version : version_type := rec_reset; + constant git_info : git_info_type := (sha => short_sha); + signal checksum : fpga_checksum_type := rec_reset; + signal scratchpad : scratchpad_type := rec_reset; + signal hubris_compat: hubris_compat_type := rec_reset; + +begin + bresp <= OKAY; + rresp <= OKAY; + + wready <= awready; + arready <= not rvalid; + + axi_int_read_ready <= arvalid and arready; + + -- axi transaction mgmt + axi_txn: process(clk, reset) + begin + if reset then + awready <= '0'; + bvalid <= '0'; + rvalid <= '0'; + elsif rising_edge(clk) then + -- bvalid set on every write, + -- cleared after bvalid && bready + if awready then + bvalid <= '1'; + elsif bready then + bvalid <= '0'; + end if; + + if axi_int_read_ready then + rvalid <= '1'; + elsif rready then + rvalid <= '0'; + end if; + + -- can accept a new write if we're not + -- responding to write already or + -- the write is not in progress + awready <= not awready and + (awvalid and wvalid) and + (not bvalid or bready); + end if; + end process; + + write_logic: process(clk, reset) + begin + if reset then + hubris_compat <= rec_reset; + scratchpad <= rec_reset; + elsif rising_edge(clk) then + -- go ahead and flo this every cycle, it's external but not + -- changing + hubris_compat <= unpack(resize(hubris_compat_pins, 32)); + if wready then + case to_integer(awaddr) is + when FPGA_CHECKSUM_OFFSET => checksum <= unpack(wdata); + when SCRATCHPAD_OFFSET => scratchpad <= unpack(wdata); + when others => null; + end case; + end if; + end if; + end process; + + read_logic: process(clk, reset) + begin + if reset then + rdata <= (others => '0'); + elsif rising_edge(clk) then + if (not arvalid) or arready then + case to_integer(araddr) is + when IDENTITY_OFFSET => rdata <= pack(identity); + when HUBRIS_COMPAT_OFFSET => rdata <= pack(hubris_compat); + when VERSION_OFFSET => rdata <= pack(version); + when GIT_INFO_OFFSET => rdata <= pack(git_info); + when FPGA_CHECKSUM_OFFSET => rdata <= pack(checksum); + when SCRATCHPAD_OFFSET => rdata <= pack(scratchpad); + when others => + rdata <= (others => '0'); + end case; + end if; + end if; + end process; + +end rtl; \ No newline at end of file diff --git a/hdl/ip/vhd/info/info_regs.rdl b/hdl/ip/vhd/info/info_regs.rdl new file mode 100644 index 00000000..0272864c --- /dev/null +++ b/hdl/ip/vhd/info/info_regs.rdl @@ -0,0 +1,70 @@ +// Copyright 2024 Oxide Computer Company +// This is SystemRDL description of the sw-accessible common board-info registers + +addrmap info_regs { + name = "Board and Build info"; + desc = "Registers accessible on the Axi bus providing board and build info"; + + default regwidth = 32; + default sw = rw; + default hw = r; + + reg { + name = "Identity"; + desc = ""; + + field { + default sw = r; + desc = "Read-only bits showing 0x1de"; + } data[32] = 0x1de; + } identity; + + reg { + name = "Hubris Compatibility Straps"; + desc = ""; + + field { + default sw = r; + desc = "Read-only bits showing resistor strapping for hubris compatibility value"; + } data[32] = 0; + } hubris_compat; + + reg { + name = "Version"; + desc = ""; + + field { + default sw = r; + desc = "Read-only bits showing 0x1de"; + } data[32] = 0x1de; + } version; + + reg { + name = "GIT SHORT SHA"; + desc = ""; + + field { + default sw = r; + desc = "Read-only bits showing the 4byte short-sha of the git commit"; + } sha[32] = 0; + } git_info; + + reg { + name = "FPGA Checksum"; + desc = ""; + + field { + desc = "Scribble register, nominally intended to hold the FPGA checksum, + used for knowing if the FPGA needs to be re-programmed or not"; + } data[32] = 0; + } fpga_checksum; + + reg { + name = "Scratchpad"; + desc = ""; + + field { + desc = "Scribble register scratchpad suitable for any software purpose"; + } data[32] = 0; + } scratchpad; +}; \ No newline at end of file diff --git a/hdl/projects/grapefruit/BUCK b/hdl/projects/grapefruit/BUCK index a7a90e97..9295574b 100644 --- a/hdl/projects/grapefruit/BUCK +++ b/hdl/projects/grapefruit/BUCK @@ -71,6 +71,7 @@ vhdl_unit( ":gfruit_top_regs", ":gfruit_sgpio", ":reset_sync", + "//hdl/ip/vhd/info:info", "//hdl/ip/vhd/espi:espi_top", "//hdl/ip/vhd/uart:axi_fifo_uart", "//hdl/ip/vhd/axi_blocks:axilite_common_pkgs", diff --git a/hdl/projects/grapefruit/grapefruit_top.vhd b/hdl/projects/grapefruit/grapefruit_top.vhd index 00b51eed..6f186962 100644 --- a/hdl/projects/grapefruit/grapefruit_top.vhd +++ b/hdl/projects/grapefruit/grapefruit_top.vhd @@ -319,12 +319,15 @@ begin -- tristate control for the FMC data bus fmc_sp_to_fpga_da <= fmc_internal_data_out when fmc_data_out_enable = '1' else (others => 'Z'); - registers_inst: entity work.registers + info_regs: entity work.info + generic map( + hubris_compat_num_bits => 3 + ) port map( clk => clk_125m, reset => reset_125m, - axi_if => responders(0), - spi_nor_passthru => open + hubris_compat_pins => (others => '0'), + axi_if => responders(0) ); spi_nor_top_inst: entity work.spi_nor_top diff --git a/toolchains/BUCK b/toolchains/BUCK index 2099160c..185ef605 100644 --- a/toolchains/BUCK +++ b/toolchains/BUCK @@ -1,12 +1,18 @@ load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain", "system_python_toolchain") load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain") load("@prelude//toolchains:remote_test_execution.bzl", "remote_test_execution_toolchain") +load("@prelude//toolchains:genrule.bzl", "system_genrule_toolchain") load("vivado_toolchain.bzl", "vivado_toolchain") load("vsg_toolchain.bzl", "vsg_toolchain") load("yosys_toolchain.bzl", "icepack_toolchain", "nextpnr_ice40_toolchain") +system_genrule_toolchain( + name = "genrule", + visibility = ["PUBLIC"], +) + system_cxx_toolchain( name = "cxx", visibility = ["PUBLIC"], diff --git a/tools/vhdl-ls.bxl b/tools/vhdl-ls.bxl index 317f8de5..1ce4aada 100644 --- a/tools/vhdl-ls.bxl +++ b/tools/vhdl-ls.bxl @@ -24,7 +24,7 @@ def vhdl_toml_gen(ctx): # Right now, this assumes the default work library # Filter for rdl files in the project rdl_files = ctx.cquery().kind("rdl.*", targets) - gen_vhdl_from_rdl = [] + gen_vhdl = [] bld = ctx.build(rdl_files) for target, value in bld.items(): # Buck documentation appears to be incorrect here in that failures() can't be @@ -37,7 +37,26 @@ def vhdl_toml_gen(ctx): if art.extension == ".vhd": # Locally materialize this output since we want it local a = ctx.output.ensure(art) - gen_vhdl_from_rdl.append(a) + gen_vhdl.append(a) + + # Also probably janky but find any genrules, and locally materialize + # any .vhd files they would produce + # This is maybe a bit broad but it's working for now as it catches *any* + # rule that has a .vhd in the 'out' attribute + gen_vhdl_rules = ctx.cquery().attrregexfilter('out', '.*vhd', targets) + bld = ctx.build(gen_vhdl_rules) + for target, value in bld.items(): + # Buck documentation appears to be incorrect here in that failures() can't be + # evaluated without iterating for whatever reason (if `value.failures()` always + # trips) + for f in value.failures(): + fail_no_stacktrace("Failed to build {} file".format(target)) + + for art in value.artifacts(): + if art.extension == ".vhd": + # Locally materialize this output since we want it local + a = ctx.output.ensure(art) + gen_vhdl.append(a) # Eagerly analyze vhdl build tree targets ctx.analysis(vhdl_files) @@ -48,6 +67,8 @@ def vhdl_toml_gen(ctx): files_by_library_name = dict() for file in vhdl_files: + # Useful for debug, but messes the std_out for normal use + #ctx.output.print("Processing file: {}".format(file)) # For each target, we're going to need the attributes to figure # out if there are specified libraries or just the default lib attrs = file.attrs_eager() @@ -58,6 +79,8 @@ def vhdl_toml_gen(ctx): # we allow combination sims with no source files, so # if we find one of those, we'll just move on since # there's nothing to do + # Useful for debug, but messes the std_out for normal use + #ctx.output.print("No sources found for {}".format(file)) continue lib_name = attrs.library.value() # We allow empty library names, but need to dump them into a defaul @@ -76,7 +99,7 @@ def vhdl_toml_gen(ctx): # Now load the vhdl from RDL files into worklib worklib_files = files_by_library_name.get("worklib", {"files": []}).get("files") - worklib_files.extend(gen_vhdl_from_rdl) + worklib_files.extend(gen_vhdl) # VHDL-LS wants a specific structure that was annoying to work with above so