From d9a03ba71a7615b0939fbd17674dd081fdf76ae0 Mon Sep 17 00:00:00 2001 From: Alexander Williams Date: Tue, 3 Dec 2024 19:32:30 -0800 Subject: [PATCH] [prim,earlgrey,fpga] Add specialized ram_1p prim Add a specialized ram_1p prim for the prim_xilinx library. This prim adds some prim_xilinx-specific parameters to enable selecting particular layouts for embedded memories. The intention is to have the top-level override the parameters with hierarchical assignment. This feature is intended for use with memories that are too wide to fit in updatemem's capabilities (where splicing is required). The flash info pages are one such type, since updatemem can only handle up to 64-bit wide items, and the info page array is 76 bits wide. Synthesis chooses the most efficient layout of the memories, but the layout is awkward for handling splices. Force earlgrey's flash info data and metadata into separate arrays for the FPGA. Signed-off-by: Alexander Williams (cherry picked from commit 9776162eb91b785d2dabc01021dda00e015edd96) --- doc/contributing/fpga/debugging_with_ila.md | 2 +- .../prim_xilinx/prim_xilinx_default_pkg.core | 19 +++ hw/ip/prim_xilinx/prim_xilinx_ram_1p.core | 44 +++++++ hw/ip/prim_xilinx/rtl/prim_xilinx_pkg.sv | 16 +++ hw/ip/prim_xilinx/rtl/prim_xilinx_ram_1p.sv | 77 ++++++++++++ .../prim_xilinx_ultrascale_ram_1p.core | 19 +++ .../rtl/prim_xilinx_ultrascale_ram_1p.sv | 35 ++++++ hw/top_earlgrey/chip_earlgrey_cw310.core | 2 +- .../chip_earlgrey_cw310_hyperdebug.core | 2 +- hw/top_earlgrey/chip_earlgrey_cw340.core | 2 +- hw/top_earlgrey/data/synth.xdc | 14 --- hw/top_earlgrey/earlgrey_xilinx_prim_pkg.core | 19 +++ hw/top_earlgrey/rtl/prim_xilinx_pkg.sv | 20 +++ .../util/vivado_hook_write_bitstream_pre.tcl | 118 +++++++++--------- .../chip_englishbreakfast_cw305.core | 1 + 15 files changed, 316 insertions(+), 74 deletions(-) create mode 100644 hw/ip/prim_xilinx/prim_xilinx_default_pkg.core create mode 100644 hw/ip/prim_xilinx/prim_xilinx_ram_1p.core create mode 100644 hw/ip/prim_xilinx/rtl/prim_xilinx_pkg.sv create mode 100644 hw/ip/prim_xilinx/rtl/prim_xilinx_ram_1p.sv create mode 100644 hw/ip/prim_xilinx_ultrascale/prim_xilinx_ultrascale_ram_1p.core create mode 100644 hw/ip/prim_xilinx_ultrascale/rtl/prim_xilinx_ultrascale_ram_1p.sv delete mode 100644 hw/top_earlgrey/data/synth.xdc create mode 100644 hw/top_earlgrey/earlgrey_xilinx_prim_pkg.core create mode 100644 hw/top_earlgrey/rtl/prim_xilinx_pkg.sv diff --git a/doc/contributing/fpga/debugging_with_ila.md b/doc/contributing/fpga/debugging_with_ila.md index 58a9bc1acec8c2..e02032798645d2 100644 --- a/doc/contributing/fpga/debugging_with_ila.md +++ b/doc/contributing/fpga/debugging_with_ila.md @@ -237,7 +237,7 @@ The path to the synthesis log file is usually `bazel-out/k8-fastbuild/bin/hw/bit Once Vivado has successfully generated a bitstream, locate its directory with `dirname $(./bazelisk.sh outquery-all //hw/bitstream:rom --define bitstream=vivado)` (it will usually be `bazel-out/k8-fastbuild/bin/hw/bitstream/vivado`). Append `/build.fpga_cw310/synth-vivado` to that path. -In the resulting directory, you should find `memories.mmi`, and `lowrisc_systems_chip_earlgrey_cw310_0.1.bit`. +In the resulting directory, you should find `memories.mmi` and `lowrisc_systems_chip_earlgrey_cw310_0.1.bit`. We will next copy those files into a local bitstream cache that Bazel can use. If you don't have a local bitstream cache yet, create one as follows: diff --git a/hw/ip/prim_xilinx/prim_xilinx_default_pkg.core b/hw/ip/prim_xilinx/prim_xilinx_default_pkg.core new file mode 100644 index 00000000000000..efcff71f05a703 --- /dev/null +++ b/hw/ip/prim_xilinx/prim_xilinx_default_pkg.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: "lowrisc:prim_xilinx:prim_xilinx_default_pkg" +description: "Single port RAM" +virtual: + - lowrisc:prim_xilinx:prim_xilinx_pkg +filesets: + files_rtl: + files: + - rtl/prim_xilinx_pkg.sv + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/ip/prim_xilinx/prim_xilinx_ram_1p.core b/hw/ip/prim_xilinx/prim_xilinx_ram_1p.core new file mode 100644 index 00000000000000..3ee8918a2bfa7c --- /dev/null +++ b/hw/ip/prim_xilinx/prim_xilinx_ram_1p.core @@ -0,0 +1,44 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: "lowrisc:prim_xilinx:ram_1p" +description: "Single port RAM" +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:prim:ram_1p_pkg + # Note that prim_xilinx_pkg is a virtual core that the top should provide. + # It maps parameters to instructions for how to split memories into + # logical groups of bits. See prim_xilinx_default_pkg for an example. + - lowrisc:prim_xilinx:prim_xilinx_pkg + - lowrisc:prim_generic:ram_1p + - lowrisc:prim:util_memload + files: + - rtl/prim_xilinx_ram_1p.sv + file_type: systemVerilogSource + + files_verilator_waiver: + depend: + # common waivers + - lowrisc:lint:common + + files_ascentlint_waiver: + depend: + # common waivers + - lowrisc:lint:common + + files_veriblelint_waiver: + depend: + # common waivers + - lowrisc:lint:common + +targets: + default: + filesets: + - tool_verilator ? (files_verilator_waiver) + - tool_ascentlint ? (files_ascentlint_waiver) + - tool_veriblelint ? (files_veriblelint_waiver) + - files_rtl diff --git a/hw/ip/prim_xilinx/rtl/prim_xilinx_pkg.sv b/hw/ip/prim_xilinx/rtl/prim_xilinx_pkg.sv new file mode 100644 index 00000000000000..cf46bc19512c45 --- /dev/null +++ b/hw/ip/prim_xilinx/rtl/prim_xilinx_pkg.sv @@ -0,0 +1,16 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package prim_xilinx_pkg; + + // Returns the maximum width of an individual xpm memory. Note that this API + // may evolve over time, but currently it uses the width and depth + // parameters to identify memories that may need to be broken up into + // separate groups. This can help work around updatemem's maximum width for + // words, which is 64 bits at the time of writing. + function automatic int get_ram_max_width(int width, int depth); + return 0; + endfunction + +endpackage : prim_xilinx_pkg diff --git a/hw/ip/prim_xilinx/rtl/prim_xilinx_ram_1p.sv b/hw/ip/prim_xilinx/rtl/prim_xilinx_ram_1p.sv new file mode 100644 index 00000000000000..582fa2a1f239bc --- /dev/null +++ b/hw/ip/prim_xilinx/rtl/prim_xilinx_ram_1p.sv @@ -0,0 +1,77 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Synchronous single-port SRAM model + +`include "prim_assert.sv" + +module prim_xilinx_ram_1p import prim_ram_1p_pkg::*; #( + parameter int Width = 32, // bit + parameter int Depth = 128, + parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask + parameter MemInitFile = "", // VMEM file to initialize the memory with + + localparam int Aw = $clog2(Depth) // derived parameter +) ( + input logic clk_i, + + input logic req_i, + input logic write_i, + input logic [Aw-1:0] addr_i, + input logic [Width-1:0] wdata_i, + input logic [Width-1:0] wmask_i, + output logic [Width-1:0] rdata_o, // Read data. Data is returned one cycle after req_i is high. + input ram_1p_cfg_t cfg_i +); + + localparam int PrimMaxWidth = prim_xilinx_pkg::get_ram_max_width(Width, Depth); + + if (PrimMaxWidth <= 0) begin : gen_generic + prim_generic_ram_1p #( + .Width(Width), + .Depth(Depth), + .DataBitsPerMask(DataBitsPerMask), + .MemInitFile(MemInitFile) + ) u_ram_1p ( + .* + ); + end else begin : gen_xpm + logic wr_en; + assign wr_en = write_i & wmask_i[0]; + + logic unused_cfg_i; + assign unused_cfg_i = cfg_i; + + for (genvar k = 0; k < Width; k = k + PrimMaxWidth) begin : gen_split + localparam int PrimWidth = ((Width - k) > PrimMaxWidth) ? PrimMaxWidth : Width - k; + localparam string PrimMemoryInitFile = (MemInitFile != "") ? MemInitFile : "none"; + + xpm_memory_spram #( + .ADDR_WIDTH_A(Aw), + .BYTE_WRITE_WIDTH_A(PrimWidth), // Masks are not supported + .MEMORY_INIT_FILE(PrimMemoryInitFile), + .MEMORY_SIZE(Depth * PrimWidth), + .READ_DATA_WIDTH_A(PrimWidth), + .READ_LATENCY_A(1), + .USE_MEM_INIT_MMI(1), + .WRITE_DATA_WIDTH_A(PrimWidth) + ) u_ram_1p ( + .clka(clk_i), + .addra(addr_i), + .dbiterra(), + .dina(wdata_i[k +: PrimWidth]), + .douta(rdata_o[k +: PrimWidth]), + .ena(req_i), + .injectdbiterra(1'b0), + .injectsbiterra(1'b0), + .regcea(1'b1), + .rsta(1'b0), + .sbiterra(), + .sleep(1'b0), + .wea(wr_en) + ); + end + end + +endmodule diff --git a/hw/ip/prim_xilinx_ultrascale/prim_xilinx_ultrascale_ram_1p.core b/hw/ip/prim_xilinx_ultrascale/prim_xilinx_ultrascale_ram_1p.core new file mode 100644 index 00000000000000..720fe34c26e520 --- /dev/null +++ b/hw/ip/prim_xilinx_ultrascale/prim_xilinx_ultrascale_ram_1p.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: "lowrisc:prim_xilinx_ultrascale:ram_1p" +description: "Single port RAM" +filesets: + files_rtl: + depend: + - lowrisc:prim_xilinx:ram_1p + files: + - rtl/prim_xilinx_ultrascale_ram_1p.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/ip/prim_xilinx_ultrascale/rtl/prim_xilinx_ultrascale_ram_1p.sv b/hw/ip/prim_xilinx_ultrascale/rtl/prim_xilinx_ultrascale_ram_1p.sv new file mode 100644 index 00000000000000..741a51ebc1fb56 --- /dev/null +++ b/hw/ip/prim_xilinx_ultrascale/rtl/prim_xilinx_ultrascale_ram_1p.sv @@ -0,0 +1,35 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Synchronous single-port SRAM model + +`include "prim_assert.sv" + +module prim_xilinx_ultrascale_ram_1p import prim_ram_1p_pkg::*; #( + parameter int Width = 32, // bit + parameter int Depth = 128, + parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask + parameter MemInitFile = "", // VMEM file to initialize the memory with + + localparam int Aw = $clog2(Depth) // derived parameter +) ( + input logic clk_i, + + input logic req_i, + input logic write_i, + input logic [Aw-1:0] addr_i, + input logic [Width-1:0] wdata_i, + input logic [Width-1:0] wmask_i, + output logic [Width-1:0] rdata_o, // Read data. Data is returned one cycle after req_i is high. + input ram_1p_cfg_t cfg_i +); + + prim_xilinx_ram_1p #( + .Width(Width), + .Depth(Depth), + .DataBitsPerMask(DataBitsPerMask), + .MemInitFile(MemInitFile) + ) u_inst (.*); + +endmodule diff --git a/hw/top_earlgrey/chip_earlgrey_cw310.core b/hw/top_earlgrey/chip_earlgrey_cw310.core index 5ed38b7e7d54ce..63a60d53d29409 100644 --- a/hw/top_earlgrey/chip_earlgrey_cw310.core +++ b/hw/top_earlgrey/chip_earlgrey_cw310.core @@ -7,6 +7,7 @@ description: "Earl Grey toplevel for the ChipWhisperer CW310 board" filesets: files_rtl_cw310: depend: + - lowrisc:prim_xilinx:earlgrey_xilinx_prim_pkg - lowrisc:systems:top_earlgrey:0.1 - lowrisc:systems:top_earlgrey_pkg - lowrisc:systems:ast @@ -23,7 +24,6 @@ filesets: - data/clocks.xdc - data/pins_cw310.xdc - data/placement.xdc - - data/synth.xdc file_type: xdc files_tcl: diff --git a/hw/top_earlgrey/chip_earlgrey_cw310_hyperdebug.core b/hw/top_earlgrey/chip_earlgrey_cw310_hyperdebug.core index 74f8ae3c9e96f3..2b9d8a98b19830 100644 --- a/hw/top_earlgrey/chip_earlgrey_cw310_hyperdebug.core +++ b/hw/top_earlgrey/chip_earlgrey_cw310_hyperdebug.core @@ -7,6 +7,7 @@ description: "Earl Grey toplevel for the ChipWhisperer CW310 board's hyperdebug filesets: files_rtl_cw310: depend: + - lowrisc:prim_xilinx:earlgrey_xilinx_prim_pkg - lowrisc:systems:top_earlgrey:0.1 - lowrisc:systems:top_earlgrey_pkg - lowrisc:systems:ast @@ -25,7 +26,6 @@ filesets: # same as lowrisc:systems:chip_earlgrey_cw310. - data/pins_cw310_hyperdebug.xdc - data/placement.xdc - - data/synth.xdc file_type: xdc files_tcl: diff --git a/hw/top_earlgrey/chip_earlgrey_cw340.core b/hw/top_earlgrey/chip_earlgrey_cw340.core index 462f42f771417a..9aa63ad4ea0ab9 100644 --- a/hw/top_earlgrey/chip_earlgrey_cw340.core +++ b/hw/top_earlgrey/chip_earlgrey_cw340.core @@ -7,6 +7,7 @@ description: "Earl Grey toplevel for the ChipWhisperer CW340 board" filesets: files_rtl_cw340: depend: + - lowrisc:prim_xilinx:earlgrey_xilinx_prim_pkg - lowrisc:systems:top_earlgrey:0.1 - lowrisc:systems:top_earlgrey_pkg - lowrisc:systems:ast @@ -22,7 +23,6 @@ filesets: files: - data/clocks_cw341.xdc - data/pins_cw341.xdc - - data/synth.xdc file_type: xdc files_tcl: diff --git a/hw/top_earlgrey/data/synth.xdc b/hw/top_earlgrey/data/synth.xdc deleted file mode 100644 index 2615f456d1e63b..00000000000000 --- a/hw/top_earlgrey/data/synth.xdc +++ /dev/null @@ -1,14 +0,0 @@ -## Copyright lowRISC contributors (OpenTitan project). -## Licensed under the Apache License, Version 2.0, see LICENSE for details. -## SPDX-License-Identifier: Apache-2.0 - -## Synthesis constraints - -# Prevent Vivado from combining these BRAMs, so the memories can be readily -# spliced with updatemem. -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[0].u_prim_flash_bank/gen_info_types[0].u_info_mem"] -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[0].u_prim_flash_bank/gen_info_types[1].u_info_mem"] -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[0].u_prim_flash_bank/gen_info_types[2].u_info_mem"] -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[1].u_prim_flash_bank/gen_info_types[0].u_info_mem"] -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[1].u_prim_flash_bank/gen_info_types[1].u_info_mem"] -set_property KEEP_HIERARCHY TRUE [get_cells "top_earlgrey/u_flash_ctrl/u_eflash/u_flash/gen_generic.u_impl_generic/gen_prim_flash_banks[1].u_prim_flash_bank/gen_info_types[2].u_info_mem"] diff --git a/hw/top_earlgrey/earlgrey_xilinx_prim_pkg.core b/hw/top_earlgrey/earlgrey_xilinx_prim_pkg.core new file mode 100644 index 00000000000000..2284fd3ba0b9a3 --- /dev/null +++ b/hw/top_earlgrey/earlgrey_xilinx_prim_pkg.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: "lowrisc:prim_xilinx:earlgrey_xilinx_prim_pkg" +description: "Single port RAM" +virtual: + - lowrisc:prim_xilinx:prim_xilinx_pkg +filesets: + files_rtl: + files: + - rtl/prim_xilinx_pkg.sv + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/top_earlgrey/rtl/prim_xilinx_pkg.sv b/hw/top_earlgrey/rtl/prim_xilinx_pkg.sv new file mode 100644 index 00000000000000..aa1a2b0b8f6c49 --- /dev/null +++ b/hw/top_earlgrey/rtl/prim_xilinx_pkg.sv @@ -0,0 +1,20 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package prim_xilinx_pkg; + + // Accommodates updatemem by breaking up flash info arrays into data and + // metadata subarrays. The 76-bit width and 1 BRAM depth identifies these + // memories in earlgrey, and we limit the subarray size to 64 bits, which is + // the size of the data portion. The leftover 12 bits get placed into their + // own memory with a unique hierarchical path. See prim_xilinx_ram_1p.sv to + // see how this works. + function automatic int get_ram_max_width(int width, int depth); + if (width == 76 && depth < 4096) begin + return 64; + end + return 0; + endfunction + +endpackage : prim_xilinx_pkg diff --git a/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl b/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl index 26a832965ca8a7..e0138e072edf0d 100644 --- a/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl +++ b/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl @@ -28,6 +28,7 @@ set_property BITSTREAM.CONFIG.USR_ACCESS TIMESTAMP [current_design] # addr_end_multiplier: A coefficient applied to the address space. Influences # the values of the MMI's and # tags. +# schema: Either "Processor" or "MemoryArray" # designtask_count: A number used for logging with `send_msg`. proc generate_mmi {filename mem_infos designtask_count} { send_msg "${designtask_count}-1" INFO "Dumping MMI to ${filename}" @@ -50,6 +51,7 @@ proc generate_mmi {filename mem_infos designtask_count} { # Calculate the overall address space. set space 0 + set width 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]] @@ -69,14 +71,22 @@ proc generate_mmi {filename mem_infos designtask_count} { # Calculate total number of bits. set space [expr {$space + ($addr_end - $addr_begin + 1) * $slice_width}] + set width [expr {$width + $slice_width}] set last_slice_width $slice_width } set space [expr {($space * $addr_end_multiplier / 8) - 1}] # Generate the MMI. - puts $fileout " " - puts $fileout " " - puts $fileout " " + if { $schema eq "Processor" } { + puts $fileout " " + puts $fileout " " + puts $fileout " " + } else { + puts $fileout " " + # Memory type could be retrieved from the RTL_RAM_TYPE property, if desired, + # but we hard-code it here for now. + puts $fileout " " + } foreach inst [lsort -dictionary $brams] { set loc [get_property LOC [get_cells $inst]] @@ -94,15 +104,36 @@ proc generate_mmi {filename mem_infos designtask_count} { 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 " " - puts $fileout " " - puts $fileout " " - puts $fileout " " - puts $fileout " " + set bit_layout [get_property "MEM.PORTA.DATA_BIT_LAYOUT" [get_cells $inst]] + set read_width_a [get_property "READ_WIDTH_A" [get_cells $inst]] + set read_width_b [get_property "READ_WIDTH_B" [get_cells $inst]] + set slr_index [get_property "SLR_INDEX" [get_cells $inst]] + if {$schema eq "Processor"} { + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + } else { + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + puts $fileout " " + } + } + if {$schema eq "Processor"} { + puts $fileout " " + puts $fileout " " + puts $fileout " " + } else { + puts $fileout " " + puts $fileout " " } - puts $fileout " " - puts $fileout " " - puts $fileout " " } } @@ -170,6 +201,14 @@ switch ${fpga_family} { } set mem_type_regex {(RAMB\d+)_(\w+)} +set gen_mem_info {{brams mem_type_regex fake_word_width addr_end_multiplier schema} { + dict set mem_info brams $brams + dict set mem_info mem_type_regex $mem_type_regex + dict set mem_info fake_word_width $fake_word_width + dict set mem_info addr_end_multiplier $addr_end_multiplier + return [dict set mem_info schema $schema] +}} + # 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. @@ -185,10 +224,7 @@ set mem_type_regex {(RAMB\d+)_(\w+)} # 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 =~ ${bram_regex} && NAME =~ *u_rom_ctrl*"] " "] -dict set memInfo rom brams $rom_brams -dict set memInfo rom mem_type_regex $mem_type_regex -dict set memInfo rom fake_word_width 40 -dict set memInfo rom addr_end_multiplier 1 +dict set memInfo rom [apply $gen_mem_info $rom_brams $mem_type_regex 40 1 "Processor"] # 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 @@ -196,47 +232,17 @@ dict set memInfo rom addr_end_multiplier 1 # 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 =~ ${bram_regex} && NAME =~ *u_otp_ctrl*"] " "] -dict set memInfo otp brams $otp_brams -dict set memInfo otp mem_type_regex $mem_type_regex -dict set memInfo otp fake_word_width 0 -dict set memInfo otp addr_end_multiplier 16 - -# The flash banks have 76-bit wide words. 64 bits are data, and 12 bits are metadata. -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[0]*gen_info_types[0].u_info_mem*"] " "] -dict set memInfo flash0_info0 brams $flash_info_brams -dict set memInfo flash0_info0 mem_type_regex $mem_type_regex -dict set memInfo flash0_info0 fake_word_width 0 -dict set memInfo flash0_info0 addr_end_multiplier 1 - -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[0]*gen_info_types[1].u_info_mem*"] " "] -dict set memInfo flash0_info1 brams $flash_info_brams -dict set memInfo flash0_info1 mem_type_regex $mem_type_regex -dict set memInfo flash0_info1 fake_word_width 0 -dict set memInfo flash0_info1 addr_end_multiplier 1 - -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[0]*gen_info_types[2].u_info_mem*"] " "] -dict set memInfo flash0_info2 brams $flash_info_brams -dict set memInfo flash0_info2 mem_type_regex $mem_type_regex -dict set memInfo flash0_info2 fake_word_width 0 -dict set memInfo flash0_info2 addr_end_multiplier 1 - -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[1]*gen_info_types[0].u_info_mem*"] " "] -dict set memInfo flash1_info0 brams $flash_info_brams -dict set memInfo flash1_info0 mem_type_regex $mem_type_regex -dict set memInfo flash1_info0 fake_word_width 0 -dict set memInfo flash1_info0 addr_end_multiplier 1 - -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[1]*gen_info_types[1].u_info_mem*"] " "] -dict set memInfo flash1_info1 brams $flash_info_brams -dict set memInfo flash1_info1 mem_type_regex $mem_type_regex -dict set memInfo flash1_info1 fake_word_width 0 -dict set memInfo flash1_info1 addr_end_multiplier 1 - -set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[1]*gen_info_types[2].u_info_mem*"] " "] -dict set memInfo flash1_info2 brams $flash_info_brams -dict set memInfo flash1_info2 mem_type_regex $mem_type_regex -dict set memInfo flash1_info2 fake_word_width 0 -dict set memInfo flash1_info2 addr_end_multiplier 1 +dict set memInfo otp [apply $gen_mem_info $otp_brams $mem_type_regex 0 16 "Processor"] + +# The flash banks have 76-bit wide words. 64 bits are data, and 12 bits are metadata / integrity. +for {set bank 0} {$bank < 2} {incr bank} { + for {set partition 0} {$partition < 3} {incr partition} { + set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[${bank}]*gen_info_types[${partition}].u_info_mem*gen_xpm.gen_split[0].*"] " "] + dict set memInfo "flash${bank}_info${partition}_data" [apply $gen_mem_info $flash_info_brams $mem_type_regex 0 1 "MemoryArray"] + set flash_info_brams [split [get_cells -hierarchical -filter " PRIMITIVE_TYPE =~ ${bram_regex} && NAME =~ *u_flash_ctrl*gen_prim_flash_banks[${bank}]*gen_info_types[${partition}].u_info_mem*gen_xpm.gen_split[64].*"] " "] + dict set memInfo "flash${bank}_info${partition}_intg" [apply $gen_mem_info $flash_info_brams $mem_type_regex 0 1 "MemoryArray"] + } +} generate_mmi "memories.mmi" $memInfo 1 diff --git a/hw/top_englishbreakfast/chip_englishbreakfast_cw305.core b/hw/top_englishbreakfast/chip_englishbreakfast_cw305.core index edacf154d38571..22b0e1d6d588a6 100644 --- a/hw/top_englishbreakfast/chip_englishbreakfast_cw305.core +++ b/hw/top_englishbreakfast/chip_englishbreakfast_cw305.core @@ -8,6 +8,7 @@ description: "English Breakfast toplevel for the ChipWhisperer CW305 board" filesets: files_rtl_cw305: depend: + - lowrisc:prim_xilinx:prim_xilinx_default_pkg - lowrisc:systems:top_englishbreakfast:0.1 - lowrisc:systems:ast - lowrisc:systems:topgen