mirror of
https://github.com/lowRISC/ibex.git
synced 2025-06-27 17:00:41 -04:00
Update lowrisc_ip to lowRISC/opentitan@1ae03937f
Update code from upstream repository https://github.com/lowRISC/opentitan to revision 1ae03937f0bb4b146bb6e736bccb4821bfda556b * [prim/fifo_async] Add assertions on pointers (Tom Roberts) * [prim/fifo_async] Add support for Depth <= 2 (Tom Roberts) * [prim/fifo_async] Code tidy-up (Tom Roberts) * [top / ast] Continued ast integration (Timothy Chen) * [dvsim] Use bash when running make underneath (Srikrishna Iyer) * [prim] Increase maximum width for prim_util_memload to 312 (Greg Chadwick) * [sram_ctrl] Fix potential back-to-back partial write bug (Michael Schaffner) * [dvsim] Fix for lowRISC/opentitan#5527 (Srikrishna Iyer) * [lint] Waive Verilator UNUSED warnings for packages (Rupert Swarbrick) * [uvmdvgen] Update DV doc path and terminology (Srikrishna Iyer) * [clkmgr] Fix dft issues (Timothy Chen) * [util] add `dec` types to prim_secded_pkg (Udi Jonnalagadda) * [util] minor updates to secded_gen (Udi Jonnalagadda) * [lint] Fix a bunch of lint warnings related to long lines (>100 chars) (Michael Schaffner) * [dv] Update common intr_test seq (Weicai Yang) * [util] Slight refactor of secded_gen.py (Timothy Chen) * [tlul] Add memory transmission integrity checks (Timothy Chen) * [dvsim] Move clean_odirs to `util.py` (Srikrishna Iyer) * [dvsim] Split Deploy into Deploy and Launcher (Srikrishna Iyer) * [dvsim] Add utils.TS_FORMAT* vars (Srikrishna Iyer) * [dv/lock_reg] Update IPs to adopt the lock_reg changes (Cindy Chen) * [dv/enable_regs] Support enable registers have more than one field (Cindy Chen) * [dv/base_reg] use m_field instead of accessing field (Cindy Chen) * [dv/sram] add SRAM scrambling model for DV (Udi Jonnalagadda) * [dv/tools] Updated Coverage flow for xcelium (Rasmus Madsen) Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
parent
50f09b71a9
commit
2c75c2b2ec
86 changed files with 2471 additions and 1178 deletions
|
@ -33,6 +33,7 @@ Instantiation Template
|
|||
.clk_i (),
|
||||
.rst_ni (),
|
||||
.test_en_i (),
|
||||
.ram_cfg_i (),
|
||||
|
||||
// Configuration
|
||||
.hart_id_i (),
|
||||
|
@ -158,6 +159,9 @@ Interfaces
|
|||
+-------------------------+-------------------------+-----+----------------------------------------+
|
||||
| ``test_en_i`` | 1 | in | Test input, enables clock |
|
||||
+-------------------------+-------------------------+-----+----------------------------------------+
|
||||
| ``ram_cfg_i`` | 10 | in | RAM configuration inputs, routed to |
|
||||
| | | | the icache RAMs |
|
||||
+-------------------------+-------------------------+-----+----------------------------------------+
|
||||
| ``hart_id_i`` | 32 | in | Hart ID, usually static, can be read |
|
||||
| | | | from :ref:`csr-mhartid` CSR |
|
||||
+-------------------------+-------------------------+-----+----------------------------------------+
|
||||
|
|
|
@ -132,6 +132,7 @@ module ibex_riscv_compliance (
|
|||
.rst_ni (rst_sys_n ),
|
||||
|
||||
.test_en_i ('b0 ),
|
||||
.ram_cfg_i ('b0 ),
|
||||
|
||||
.hart_id_i (32'b0 ),
|
||||
// First instruction executed is at 0x0 + 0x80
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// Its contents are taken from the file which would be generated by FuseSoC.
|
||||
// https://github.com/lowRISC/ibex/issues/893
|
||||
|
||||
module prim_ram_1p
|
||||
module prim_ram_1p import prim_ram_1p_pkg::*;
|
||||
|
||||
#(
|
||||
|
||||
|
@ -21,6 +21,7 @@ module prim_ram_1p
|
|||
|
||||
) (
|
||||
input logic clk_i,
|
||||
input ram_1p_cfg_t cfg_i,
|
||||
|
||||
input logic req_i,
|
||||
input logic write_i,
|
||||
|
|
|
@ -28,6 +28,7 @@ ${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_dec.sv
|
|||
// wrappers around the prim_* modules to instantiate the prim_generic_* ones,
|
||||
// see https://github.com/lowRISC/ibex/issues/893.
|
||||
${PRJ_DIR}/dv/uvm/core_ibex/common/prim/prim_pkg.sv
|
||||
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv
|
||||
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim_generic/rtl/prim_generic_ram_1p.sv
|
||||
${PRJ_DIR}/dv/uvm/core_ibex/common/prim/prim_ram_1p.sv
|
||||
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim_generic/rtl/prim_generic_clock_gating.sv
|
||||
|
|
|
@ -78,6 +78,7 @@ module core_ibex_tb_top;
|
|||
.rst_ni (rst_n ),
|
||||
|
||||
.test_en_i (1'b0 ),
|
||||
.ram_cfg_i (1'b0 ),
|
||||
|
||||
.hart_id_i (32'b0 ),
|
||||
.boot_addr_i (32'h`BOOT_ADDR ), // align with spike boot address
|
||||
|
|
|
@ -38,6 +38,7 @@ module prim_badbit_ram_1p #(
|
|||
) u_mem (
|
||||
.clk_i (clk_i),
|
||||
|
||||
.cfg_i ('0),
|
||||
.req_i (req_i),
|
||||
.write_i (write_i),
|
||||
.addr_i (addr_i),
|
||||
|
|
|
@ -41,6 +41,7 @@ module tb #(parameter bit ICacheECC = 1'b0);
|
|||
.addr_o (core_if.addr),
|
||||
.err_o (core_if.err),
|
||||
.err_plus2_o (core_if.err_plus2),
|
||||
.ram_cfg_i ('0),
|
||||
.icache_enable_i (core_if.enable),
|
||||
.icache_inval_i (core_if.invalidate),
|
||||
.busy_o (core_if.busy),
|
||||
|
|
|
@ -51,6 +51,7 @@ module top_artya7 (
|
|||
.rst_ni (rst_sys_n),
|
||||
|
||||
.test_en_i ('b0),
|
||||
.ram_cfg_i ('b0),
|
||||
|
||||
.hart_id_i (32'b0),
|
||||
// First instruction executed is at 0x0 + 0x80
|
||||
|
|
|
@ -183,6 +183,7 @@ module ibex_simple_system (
|
|||
.rst_ni (rst_sys_n),
|
||||
|
||||
.test_en_i ('b0),
|
||||
.ram_cfg_i ('b0),
|
||||
|
||||
.hart_id_i (32'b0),
|
||||
// First instruction executed is at 0x0 + 0x80
|
||||
|
|
110
rtl/ibex_core.sv
110
rtl/ibex_core.sv
|
@ -34,78 +34,79 @@ module ibex_core #(
|
|||
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||
) (
|
||||
// Clock and Reset
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
|
||||
input logic [31:0] hart_id_i,
|
||||
input logic [31:0] boot_addr_i,
|
||||
input logic [31:0] hart_id_i,
|
||||
input logic [31:0] boot_addr_i,
|
||||
|
||||
// Instruction memory interface
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
|
||||
// Data memory interface
|
||||
output logic data_req_o,
|
||||
input logic data_gnt_i,
|
||||
input logic data_rvalid_i,
|
||||
output logic data_we_o,
|
||||
output logic [3:0] data_be_o,
|
||||
output logic [31:0] data_addr_o,
|
||||
output logic [31:0] data_wdata_o,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_err_i,
|
||||
output logic data_req_o,
|
||||
input logic data_gnt_i,
|
||||
input logic data_rvalid_i,
|
||||
output logic data_we_o,
|
||||
output logic [3:0] data_be_o,
|
||||
output logic [31:0] data_addr_o,
|
||||
output logic [31:0] data_wdata_o,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_err_i,
|
||||
|
||||
// Interrupt inputs
|
||||
input logic irq_software_i,
|
||||
input logic irq_timer_i,
|
||||
input logic irq_external_i,
|
||||
input logic [14:0] irq_fast_i,
|
||||
input logic irq_nm_i, // non-maskeable interrupt
|
||||
input logic irq_software_i,
|
||||
input logic irq_timer_i,
|
||||
input logic irq_external_i,
|
||||
input logic [14:0] irq_fast_i,
|
||||
input logic irq_nm_i, // non-maskeable interrupt
|
||||
|
||||
// Debug Interface
|
||||
input logic debug_req_i,
|
||||
output ibex_pkg::crash_dump_t crash_dump_o,
|
||||
input logic debug_req_i,
|
||||
output ibex_pkg::crash_dump_t crash_dump_o,
|
||||
|
||||
// RISC-V Formal Interface
|
||||
// Does not comply with the coding standards of _i/_o suffixes, but follows
|
||||
// the convention of RISC-V Formal Interface Specification.
|
||||
`ifdef RVFI
|
||||
output logic rvfi_valid,
|
||||
output logic [63:0] rvfi_order,
|
||||
output logic [31:0] rvfi_insn,
|
||||
output logic rvfi_trap,
|
||||
output logic rvfi_halt,
|
||||
output logic rvfi_intr,
|
||||
output logic [ 1:0] rvfi_mode,
|
||||
output logic [ 1:0] rvfi_ixl,
|
||||
output logic [ 4:0] rvfi_rs1_addr,
|
||||
output logic [ 4:0] rvfi_rs2_addr,
|
||||
output logic [ 4:0] rvfi_rs3_addr,
|
||||
output logic [31:0] rvfi_rs1_rdata,
|
||||
output logic [31:0] rvfi_rs2_rdata,
|
||||
output logic [31:0] rvfi_rs3_rdata,
|
||||
output logic [ 4:0] rvfi_rd_addr,
|
||||
output logic [31:0] rvfi_rd_wdata,
|
||||
output logic [31:0] rvfi_pc_rdata,
|
||||
output logic [31:0] rvfi_pc_wdata,
|
||||
output logic [31:0] rvfi_mem_addr,
|
||||
output logic [ 3:0] rvfi_mem_rmask,
|
||||
output logic [ 3:0] rvfi_mem_wmask,
|
||||
output logic [31:0] rvfi_mem_rdata,
|
||||
output logic [31:0] rvfi_mem_wdata,
|
||||
output logic rvfi_valid,
|
||||
output logic [63:0] rvfi_order,
|
||||
output logic [31:0] rvfi_insn,
|
||||
output logic rvfi_trap,
|
||||
output logic rvfi_halt,
|
||||
output logic rvfi_intr,
|
||||
output logic [ 1:0] rvfi_mode,
|
||||
output logic [ 1:0] rvfi_ixl,
|
||||
output logic [ 4:0] rvfi_rs1_addr,
|
||||
output logic [ 4:0] rvfi_rs2_addr,
|
||||
output logic [ 4:0] rvfi_rs3_addr,
|
||||
output logic [31:0] rvfi_rs1_rdata,
|
||||
output logic [31:0] rvfi_rs2_rdata,
|
||||
output logic [31:0] rvfi_rs3_rdata,
|
||||
output logic [ 4:0] rvfi_rd_addr,
|
||||
output logic [31:0] rvfi_rd_wdata,
|
||||
output logic [31:0] rvfi_pc_rdata,
|
||||
output logic [31:0] rvfi_pc_wdata,
|
||||
output logic [31:0] rvfi_mem_addr,
|
||||
output logic [ 3:0] rvfi_mem_rmask,
|
||||
output logic [ 3:0] rvfi_mem_wmask,
|
||||
output logic [31:0] rvfi_mem_rdata,
|
||||
output logic [31:0] rvfi_mem_wdata,
|
||||
`endif
|
||||
|
||||
// CPU Control Signals
|
||||
input logic fetch_enable_i,
|
||||
output logic alert_minor_o,
|
||||
output logic alert_major_o,
|
||||
output logic core_sleep_o
|
||||
input logic fetch_enable_i,
|
||||
output logic alert_minor_o,
|
||||
output logic alert_major_o,
|
||||
output logic core_sleep_o
|
||||
);
|
||||
|
||||
import ibex_pkg::*;
|
||||
|
@ -411,6 +412,7 @@ module ibex_core #(
|
|||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
||||
.ram_cfg_i ( ram_cfg_i ),
|
||||
.boot_addr_i ( boot_addr_i ),
|
||||
.req_i ( instr_req_int ), // instruction request control
|
||||
|
||||
|
|
|
@ -28,49 +28,51 @@ module ibex_core_tracing #(
|
|||
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||
) (
|
||||
// Clock and Reset
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
|
||||
input logic [31:0] hart_id_i,
|
||||
input logic [31:0] boot_addr_i,
|
||||
|
||||
input logic [31:0] hart_id_i,
|
||||
input logic [31:0] boot_addr_i,
|
||||
|
||||
// Instruction memory interface
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
|
||||
// Data memory interface
|
||||
output logic data_req_o,
|
||||
input logic data_gnt_i,
|
||||
input logic data_rvalid_i,
|
||||
output logic data_we_o,
|
||||
output logic [3:0] data_be_o,
|
||||
output logic [31:0] data_addr_o,
|
||||
output logic [31:0] data_wdata_o,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_err_i,
|
||||
output logic data_req_o,
|
||||
input logic data_gnt_i,
|
||||
input logic data_rvalid_i,
|
||||
output logic data_we_o,
|
||||
output logic [3:0] data_be_o,
|
||||
output logic [31:0] data_addr_o,
|
||||
output logic [31:0] data_wdata_o,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_err_i,
|
||||
|
||||
// Interrupt inputs
|
||||
input logic irq_software_i,
|
||||
input logic irq_timer_i,
|
||||
input logic irq_external_i,
|
||||
input logic [14:0] irq_fast_i,
|
||||
input logic irq_nm_i, // non-maskeable interrupt
|
||||
input logic irq_software_i,
|
||||
input logic irq_timer_i,
|
||||
input logic irq_external_i,
|
||||
input logic [14:0] irq_fast_i,
|
||||
input logic irq_nm_i, // non-maskeable interrupt
|
||||
|
||||
// Debug Interface
|
||||
input logic debug_req_i,
|
||||
output ibex_pkg::crash_dump_t crash_dump_o,
|
||||
input logic debug_req_i,
|
||||
output ibex_pkg::crash_dump_t crash_dump_o,
|
||||
|
||||
// CPU Control Signals
|
||||
input logic fetch_enable_i,
|
||||
output logic alert_minor_o,
|
||||
output logic alert_major_o,
|
||||
output logic core_sleep_o
|
||||
input logic fetch_enable_i,
|
||||
output logic alert_minor_o,
|
||||
output logic alert_major_o,
|
||||
output logic core_sleep_o
|
||||
|
||||
);
|
||||
|
||||
|
@ -130,6 +132,7 @@ module ibex_core_tracing #(
|
|||
.rst_ni,
|
||||
|
||||
.test_en_i,
|
||||
.ram_cfg_i,
|
||||
|
||||
.hart_id_i,
|
||||
.boot_addr_i,
|
||||
|
|
|
@ -22,40 +22,41 @@ module ibex_icache #(
|
|||
parameter bit BranchCache = 1'b0
|
||||
) (
|
||||
// Clock and reset
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
// Signal that the core would like instructions
|
||||
input logic req_i,
|
||||
input logic req_i,
|
||||
|
||||
// Set the cache's address counter
|
||||
input logic branch_i,
|
||||
input logic branch_spec_i,
|
||||
input logic predicted_branch_i,
|
||||
input logic branch_mispredict_i,
|
||||
input logic [31:0] addr_i,
|
||||
input logic branch_i,
|
||||
input logic branch_spec_i,
|
||||
input logic predicted_branch_i,
|
||||
input logic branch_mispredict_i,
|
||||
input logic [31:0] addr_i,
|
||||
|
||||
// IF stage interface: Pass fetched instructions to the core
|
||||
input logic ready_i,
|
||||
output logic valid_o,
|
||||
output logic [31:0] rdata_o,
|
||||
output logic [31:0] addr_o,
|
||||
output logic err_o,
|
||||
output logic err_plus2_o,
|
||||
input logic ready_i,
|
||||
output logic valid_o,
|
||||
output logic [31:0] rdata_o,
|
||||
output logic [31:0] addr_o,
|
||||
output logic err_o,
|
||||
output logic err_plus2_o,
|
||||
|
||||
// Instruction memory / interconnect interface: Fetch instruction data from memory
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [BusWidth-1:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [BusWidth-1:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
input logic instr_rvalid_i,
|
||||
|
||||
// Cache status
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
output logic busy_o
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
output logic busy_o
|
||||
);
|
||||
// Local constants
|
||||
localparam int unsigned ADDR_W = 32;
|
||||
|
@ -338,6 +339,7 @@ module ibex_icache #(
|
|||
) tag_bank (
|
||||
.clk_i (clk_i),
|
||||
.req_i (tag_req_ic0 & tag_banks_ic0[way]),
|
||||
.cfg_i (ram_cfg_i),
|
||||
.write_i (tag_write_ic0),
|
||||
.wmask_i ({TAG_SIZE_ECC{1'b1}}),
|
||||
.addr_i (tag_index_ic0),
|
||||
|
@ -352,6 +354,7 @@ module ibex_icache #(
|
|||
) data_bank (
|
||||
.clk_i (clk_i),
|
||||
.req_i (data_req_ic0 & data_banks_ic0[way]),
|
||||
.cfg_i (ram_cfg_i),
|
||||
.write_i (data_write_ic0),
|
||||
.wmask_i ({LINE_SIZE_ECC{1'b1}}),
|
||||
.addr_i (data_index_ic0),
|
||||
|
|
|
@ -21,76 +21,77 @@ module ibex_if_stage #(
|
|||
parameter bit PCIncrCheck = 1'b0,
|
||||
parameter bit BranchPredictor = 1'b0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic [31:0] boot_addr_i, // also used for mtvec
|
||||
input logic req_i, // instruction request control
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
input logic [31:0] boot_addr_i, // also used for mtvec
|
||||
input logic req_i, // instruction request control
|
||||
|
||||
// instruction cache interface
|
||||
output logic instr_req_o,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
output logic instr_req_o,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
|
||||
// output of ID stage
|
||||
output logic instr_valid_id_o, // instr in IF-ID is valid
|
||||
output logic instr_new_id_o, // instr in IF-ID is new
|
||||
output logic [31:0] instr_rdata_id_o, // instr for ID stage
|
||||
output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage
|
||||
// to reduce fan-out
|
||||
output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
|
||||
// (mtval), meaningful only if
|
||||
// instr_is_compressed_id_o = 1'b1
|
||||
output logic instr_is_compressed_id_o, // compressed decoder thinks this
|
||||
// is a compressed instr
|
||||
output logic instr_bp_taken_o, // instruction was predicted to be
|
||||
// a taken branch
|
||||
output logic instr_fetch_err_o, // bus error on fetch
|
||||
output logic instr_fetch_err_plus2_o, // bus error misaligned
|
||||
output logic illegal_c_insn_id_o, // compressed decoder thinks this
|
||||
// is an invalid instr
|
||||
output logic dummy_instr_id_o, // Instruction is a dummy
|
||||
output logic [31:0] pc_if_o,
|
||||
output logic [31:0] pc_id_o,
|
||||
output logic instr_valid_id_o, // instr in IF-ID is valid
|
||||
output logic instr_new_id_o, // instr in IF-ID is new
|
||||
output logic [31:0] instr_rdata_id_o, // instr for ID stage
|
||||
output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage
|
||||
// to reduce fan-out
|
||||
output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
|
||||
// (mtval), meaningful only if
|
||||
// instr_is_compressed_id_o = 1'b1
|
||||
output logic instr_is_compressed_id_o, // compressed decoder thinks this
|
||||
// is a compressed instr
|
||||
output logic instr_bp_taken_o, // instruction was predicted to be
|
||||
// a taken branch
|
||||
output logic instr_fetch_err_o, // bus error on fetch
|
||||
output logic instr_fetch_err_plus2_o, // bus error misaligned
|
||||
output logic illegal_c_insn_id_o, // compressed decoder thinks this
|
||||
// is an invalid instr
|
||||
output logic dummy_instr_id_o, // Instruction is a dummy
|
||||
output logic [31:0] pc_if_o,
|
||||
output logic [31:0] pc_id_o,
|
||||
|
||||
// control signals
|
||||
input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
|
||||
input logic pc_set_i, // set the PC to a new value
|
||||
input logic pc_set_spec_i,
|
||||
input ibex_pkg::pc_sel_e pc_mux_i, // selector for PC multiplexer
|
||||
input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was
|
||||
// mispredicted (predicted taken)
|
||||
input ibex_pkg::exc_pc_sel_e exc_pc_mux_i, // selects ISR address
|
||||
input ibex_pkg::exc_cause_e exc_cause, // selects ISR address for
|
||||
// vectorized interrupt lines
|
||||
input logic dummy_instr_en_i,
|
||||
input logic [2:0] dummy_instr_mask_i,
|
||||
input logic dummy_instr_seed_en_i,
|
||||
input logic [31:0] dummy_instr_seed_i,
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
|
||||
input logic pc_set_i, // set the PC to a new value
|
||||
input logic pc_set_spec_i,
|
||||
input ibex_pkg::pc_sel_e pc_mux_i, // selector for PC multiplexer
|
||||
input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was
|
||||
// mispredicted (predicted taken)
|
||||
input ibex_pkg::exc_pc_sel_e exc_pc_mux_i, // selects ISR address
|
||||
input ibex_pkg::exc_cause_e exc_cause, // selects ISR address for
|
||||
// vectorized interrupt lines
|
||||
input logic dummy_instr_en_i,
|
||||
input logic [2:0] dummy_instr_mask_i,
|
||||
input logic dummy_instr_seed_en_i,
|
||||
input logic [31:0] dummy_instr_seed_i,
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
|
||||
// jump and branch target
|
||||
input logic [31:0] branch_target_ex_i, // branch/jump target address
|
||||
input logic [31:0] branch_target_ex_i, // branch/jump target address
|
||||
|
||||
// CSRs
|
||||
input logic [31:0] csr_mepc_i, // PC to restore after handling
|
||||
// the interrupt/exception
|
||||
input logic [31:0] csr_depc_i, // PC to restore after handling
|
||||
// the debug request
|
||||
input logic [31:0] csr_mtvec_i, // base PC to jump to on exception
|
||||
output logic csr_mtvec_init_o, // tell CS regfile to init mtvec
|
||||
input logic [31:0] csr_mepc_i, // PC to restore after handling
|
||||
// the interrupt/exception
|
||||
input logic [31:0] csr_depc_i, // PC to restore after handling
|
||||
// the debug request
|
||||
input logic [31:0] csr_mtvec_i, // base PC to jump to on exception
|
||||
output logic csr_mtvec_init_o, // tell CS regfile to init mtvec
|
||||
|
||||
// pipeline stall
|
||||
input logic id_in_ready_i, // ID stage is ready for new instr
|
||||
input logic id_in_ready_i, // ID stage is ready for new instr
|
||||
|
||||
// misc signals
|
||||
output logic pc_mismatch_alert_o,
|
||||
output logic if_busy_o // IF stage is busy fetching instr
|
||||
output logic pc_mismatch_alert_o,
|
||||
output logic if_busy_o // IF stage is busy fetching instr
|
||||
);
|
||||
|
||||
import ibex_pkg::*;
|
||||
|
@ -213,6 +214,7 @@ module ibex_if_stage #(
|
|||
.instr_err_i ( instr_err_i ),
|
||||
.instr_pmp_err_i ( instr_pmp_err_i ),
|
||||
|
||||
.ram_cfg_i ( ram_cfg_i ),
|
||||
.icache_enable_i ( icache_enable_i ),
|
||||
.icache_inval_i ( icache_inval_i ),
|
||||
.busy_o ( prefetch_busy )
|
||||
|
@ -252,8 +254,10 @@ module ibex_if_stage #(
|
|||
);
|
||||
// ICache tieoffs
|
||||
logic unused_icen, unused_icinv;
|
||||
assign unused_icen = icache_enable_i;
|
||||
assign unused_icinv = icache_inval_i;
|
||||
prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg;
|
||||
assign unused_icen = icache_enable_i;
|
||||
assign unused_icinv = icache_inval_i;
|
||||
assign unused_ram_cfg = ram_cfg_i;
|
||||
end
|
||||
|
||||
assign unused_fetch_addr_n0 = fetch_addr_n[0];
|
||||
|
|
|
@ -58,6 +58,7 @@ module ram_1p #(
|
|||
.MemInitFile(MemInitFile)
|
||||
) u_ram (
|
||||
.clk_i (clk_i),
|
||||
.cfg_i ('0),
|
||||
.req_i (req_i),
|
||||
.write_i (we_i),
|
||||
.wmask_i (wmask),
|
||||
|
|
|
@ -72,6 +72,7 @@ module ram_2p #(
|
|||
) u_ram (
|
||||
.clk_a_i (clk_i),
|
||||
.clk_b_i (clk_i),
|
||||
.cfg_i ('0),
|
||||
.a_req_i (a_req_i),
|
||||
.a_write_i (a_we_i),
|
||||
.a_addr_i (a_addr_idx),
|
||||
|
|
2
vendor/lowrisc_ip.lock.hjson
vendored
2
vendor/lowrisc_ip.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/lowRISC/opentitan
|
||||
rev: 6cc5c164ba96d339f06cbcede0d17d2c96ce3c05
|
||||
rev: 1ae03937f0bb4b146bb6e736bccb4821bfda556b
|
||||
}
|
||||
}
|
||||
|
|
139
vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg.sv
vendored
139
vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg.sv
vendored
|
@ -8,7 +8,6 @@ class dv_base_reg extends uvm_reg;
|
|||
// hence, backdoor write isn't available
|
||||
local bit is_ext_reg;
|
||||
|
||||
local dv_base_reg locked_regs[$];
|
||||
local uvm_reg_data_t staged_shadow_val, committed_val, shadowed_val;
|
||||
local bit is_shadowed;
|
||||
local bit shadow_wr_staged; // stage the first shadow reg write
|
||||
|
@ -36,61 +35,103 @@ class dv_base_reg extends uvm_reg;
|
|||
endfunction : new
|
||||
|
||||
function void get_dv_base_reg_fields(ref dv_base_reg_field dv_fields[$]);
|
||||
uvm_reg_field ral_fields[$];
|
||||
get_fields(ral_fields);
|
||||
foreach (ral_fields[i]) `downcast(dv_fields[i], ral_fields[i])
|
||||
foreach (m_fields[i]) `downcast(dv_fields[i], m_fields[i])
|
||||
endfunction
|
||||
|
||||
// get_n_bits will return number of all the bits in the csr
|
||||
// while this function will return actual number of bits used in reg field
|
||||
function uint get_n_used_bits();
|
||||
uvm_reg_field fields[$];
|
||||
get_fields(fields);
|
||||
foreach (fields[i]) get_n_used_bits += fields[i].get_n_bits();
|
||||
foreach (m_fields[i]) get_n_used_bits += m_fields[i].get_n_bits();
|
||||
endfunction
|
||||
|
||||
// loop all the fields to find the msb position of this reg
|
||||
function uint get_msb_pos();
|
||||
uvm_reg_field fields[$];
|
||||
get_fields(fields);
|
||||
foreach (fields[i]) begin
|
||||
uint field_msb_pos = fields[i].get_lsb_pos() + fields[i].get_n_bits() - 1;
|
||||
foreach (m_fields[i]) begin
|
||||
uint field_msb_pos = m_fields[i].get_lsb_pos() + m_fields[i].get_n_bits() - 1;
|
||||
if (field_msb_pos > get_msb_pos) get_msb_pos = field_msb_pos;
|
||||
end
|
||||
endfunction
|
||||
|
||||
// if the register is an enable reg, it will add controlled registers in the queue
|
||||
function void add_locked_reg(dv_base_reg locked_reg);
|
||||
locked_regs.push_back(locked_reg);
|
||||
virtual function dv_base_reg_field get_dv_base_reg_field_by_name(string fld_name,
|
||||
bit check_fld_exist = 1'b1);
|
||||
uvm_reg_field fld = get_field_by_name(fld_name);
|
||||
dv_base_reg_field dv_fld;
|
||||
|
||||
`downcast(dv_fld, fld)
|
||||
if (check_fld_exist) begin
|
||||
`DV_CHECK_NE_FATAL(dv_fld, null,
|
||||
$sformatf("%0s does not exist in reg %0s", fld_name, get_full_name()))
|
||||
end
|
||||
return dv_fld;
|
||||
endfunction
|
||||
|
||||
function bit is_inside_locked_regs(dv_base_reg csr);
|
||||
if (csr inside {locked_regs}) return 1;
|
||||
else return 0;
|
||||
// this function can only be called when this reg is intr_state reg
|
||||
// Example: ral.intr_state.get_intr_pins_exp_value(). And it returns value of
|
||||
// intr_state & intr_enable, which represents value of interrupt pins
|
||||
virtual function uvm_reg_data_t get_intr_pins_exp_value();
|
||||
uvm_reg_block blk = get_parent();
|
||||
uvm_reg intr_enable_csr;
|
||||
string intr_enable_csr_name;
|
||||
bit is_intr_state_csr = !(uvm_re_match("intr_state*", get_name()));
|
||||
|
||||
`DV_CHECK_EQ_FATAL(is_intr_state_csr, 1)
|
||||
|
||||
// intr_enable and intr_state have the same suffix
|
||||
intr_enable_csr_name = str_utils_pkg::str_replace(get_name(), "state", "enable");
|
||||
|
||||
intr_enable_csr = blk.get_reg_by_name(intr_enable_csr_name);
|
||||
|
||||
// some interrupts may not have intr_enable
|
||||
if (intr_enable_csr != null) begin
|
||||
return get_mirrored_value() & intr_enable_csr.get_mirrored_value();
|
||||
end else begin
|
||||
return get_mirrored_value();
|
||||
end
|
||||
endfunction
|
||||
|
||||
function bit is_enable_reg();
|
||||
return (locked_regs.size() > 0);
|
||||
// Wen reg/fld can lock specific groups of fields' write acces. The lockable fields are called
|
||||
// lockable flds.
|
||||
function void add_lockable_reg_or_fld(uvm_object lockable_obj);
|
||||
dv_base_reg_field wen_fld;
|
||||
`DV_CHECK_FATAL(m_fields.size(), 1, "This register has more than one field.\
|
||||
Please use register field's add_lockable_reg_or_fld() method instead.")
|
||||
`downcast(wen_fld, m_fields[0])
|
||||
wen_fld.add_lockable_reg_or_fld(lockable_obj);
|
||||
endfunction
|
||||
|
||||
// Returns true if this register/field can lock the specified register/field, else return false.
|
||||
function bit locks_reg_or_fld(uvm_object obj);
|
||||
dv_base_reg_field wen_fld;
|
||||
`DV_CHECK_FATAL(m_fields.size(), 1, "This register has more than one field.\
|
||||
Please use register field's locks_reg_or_fld() method instead.")
|
||||
`downcast(wen_fld, m_fields[0])
|
||||
return wen_fld.locks_reg_or_fld(obj);
|
||||
endfunction
|
||||
|
||||
// Even though user can add lockable register or field via `add_lockable_reg_or_fld` method, the
|
||||
// get_lockable_flds function will always return a queue of lockable fields.
|
||||
function void get_lockable_flds(ref dv_base_reg_field lockable_flds_q[$]);
|
||||
dv_base_reg_field wen_fld;
|
||||
`DV_CHECK_FATAL(m_fields.size(), 1, "This register has more than one field.\
|
||||
Please use register field's get_lockable_flds() method instead.")
|
||||
`downcast(wen_fld, m_fields[0])
|
||||
wen_fld.get_lockable_flds(lockable_flds_q);
|
||||
endfunction
|
||||
|
||||
// The register is a write enable register (wen_reg) if its fields are wen_flds.
|
||||
function bit is_wen_reg();
|
||||
foreach (m_fields[i]) begin
|
||||
dv_base_reg_field fld;
|
||||
`downcast(fld, m_fields[i])
|
||||
if (fld.is_wen_fld()) return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
|
||||
function bit is_staged();
|
||||
return shadow_wr_staged;
|
||||
endfunction
|
||||
|
||||
// if enable register is set to 1, the locked registers will be set to RO access
|
||||
// once enable register is reset to 0, the locked registers will be set back to original access
|
||||
function void set_locked_regs_access(string access = "original_access");
|
||||
foreach (locked_regs[i]) begin
|
||||
dv_base_reg_field locked_fields[$];
|
||||
locked_regs[i].get_dv_base_reg_fields(locked_fields);
|
||||
foreach (locked_fields[i]) locked_fields[i].set_locked_fields_access(access);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void get_locked_regs(ref dv_base_reg locked_regs_q[$]);
|
||||
locked_regs_q = locked_regs;
|
||||
endfunction
|
||||
|
||||
// is_shadowed bit is only one-time programmable
|
||||
// once this function is called in RAL auto-generated class, it cannot be changed
|
||||
function void set_is_shadowed();
|
||||
|
@ -134,8 +175,8 @@ class dv_base_reg extends uvm_reg;
|
|||
endfunction
|
||||
|
||||
// post_write callback to handle special regs:
|
||||
// - shadow register, enable reg won't be updated until the second write has no error
|
||||
// - enable register, if enable_reg is disabled, change access policy to all the locked_regs
|
||||
// - shadow register: shadow reg won't be updated until the second write has no error
|
||||
// - lock register: if wen_fld is set to 0, change access policy to all the lockable_flds
|
||||
// TODO: create an `enable_field_access_policy` variable and set the template code during
|
||||
// automation.
|
||||
virtual task post_write(uvm_reg_item rw);
|
||||
|
@ -162,17 +203,23 @@ class dv_base_reg extends uvm_reg;
|
|||
shadowed_val = ~committed_val;
|
||||
end
|
||||
end
|
||||
if (is_enable_reg()) begin
|
||||
get_dv_base_reg_fields(fields);
|
||||
field_access = fields[0].get_access();
|
||||
case (field_access)
|
||||
// rw.value is a dynamic array
|
||||
// discussed in issue #1922: enable register is standarized to W0C or RO (if HW has write
|
||||
// access).
|
||||
"W0C": if (rw.value[0][0] == 1'b0) set_locked_regs_access("RO");
|
||||
"RO": ; // if RO, it's updated by design, need to predict in scb
|
||||
default:`uvm_fatal(`gfn, $sformatf("enable register invalid access %s", field_access))
|
||||
endcase
|
||||
if (is_wen_reg()) begin
|
||||
foreach (m_fields[i]) begin
|
||||
dv_base_reg_field fld;
|
||||
`downcast(fld, m_fields[i])
|
||||
if (fld.is_wen_fld()) begin
|
||||
// rw.value is a dynamic array
|
||||
uvm_reg_data_t field_val = rw.value[0] & fld.get_field_mask();
|
||||
field_access = fld.get_access();
|
||||
case (field_access)
|
||||
// discussed in issue #1922: enable register is standarized to W0C or RO (if HW has
|
||||
// write access).
|
||||
"W0C": if (field_val == 1'b0) fld.set_lockable_flds_access(1);
|
||||
"RO": ; // if RO, it's updated by design, need to predict in scb
|
||||
default:`uvm_fatal(`gfn, $sformatf("lock register invalid access %s", field_access))
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
|
|
|
@ -48,14 +48,6 @@ class dv_base_reg_block extends uvm_reg_block;
|
|||
end
|
||||
endfunction
|
||||
|
||||
function void get_enable_regs(ref dv_base_reg enable_regs[$]);
|
||||
dv_base_reg all_regs[$];
|
||||
this.get_dv_base_regs(all_regs);
|
||||
foreach (all_regs[i]) begin
|
||||
if (all_regs[i].is_enable_reg()) enable_regs.push_back(all_regs[i]);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void get_shadowed_regs(ref dv_base_reg shadowed_regs[$]);
|
||||
dv_base_reg all_regs[$];
|
||||
this.get_dv_base_regs(all_regs);
|
||||
|
@ -64,16 +56,6 @@ class dv_base_reg_block extends uvm_reg_block;
|
|||
end
|
||||
endfunction
|
||||
|
||||
// override RAL's reset function to support enable registers
|
||||
// when reset issued - the locked registers' access will be reset to original access
|
||||
virtual function void reset(string kind = "HARD");
|
||||
dv_base_reg enable_regs[$];
|
||||
`uvm_info(`gfn, "Resetting RAL reg block", UVM_MEDIUM)
|
||||
super.reset(kind);
|
||||
get_enable_regs(enable_regs);
|
||||
foreach (enable_regs[i]) enable_regs[i].set_locked_regs_access();
|
||||
endfunction
|
||||
|
||||
// Internal function, used to compute the address mask for this register block.
|
||||
//
|
||||
// This is quite an expensive computation, so we memoize the results in addr_mask[map].
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
// base register reg class which will be used to generate the reg field
|
||||
class dv_base_reg_field extends uvm_reg_field;
|
||||
local string m_original_access;
|
||||
local dv_base_reg_field lockable_flds[$];
|
||||
local bit is_intr_test_fld;
|
||||
|
||||
`uvm_object_utils(dv_base_reg_field)
|
||||
`uvm_object_new
|
||||
|
@ -30,8 +32,30 @@ class dv_base_reg_field extends uvm_reg_field;
|
|||
.is_rand (is_rand),
|
||||
.individually_accessible(individually_accessible));
|
||||
value.rand_mode(is_rand);
|
||||
|
||||
is_intr_test_fld = !(uvm_re_match("intr_test*", get_parent().get_name()));
|
||||
endfunction
|
||||
|
||||
virtual function dv_base_reg get_dv_base_reg_parent();
|
||||
uvm_reg csr = get_parent();
|
||||
`downcast(get_dv_base_reg_parent, csr)
|
||||
endfunction
|
||||
|
||||
virtual function void do_predict (uvm_reg_item rw,
|
||||
uvm_predict_e kind = UVM_PREDICT_DIRECT,
|
||||
uvm_reg_byte_en_t be = -1);
|
||||
uvm_reg_data_t field_val = rw.value[0] & ((1 << get_n_bits())-1);
|
||||
|
||||
// update intr_state mirrored value if this is an intr_test reg
|
||||
if (is_intr_test_fld) begin
|
||||
uvm_reg_field intr_state_fld = get_intr_state_field();
|
||||
// use UVM_PREDICT_READ to avoid uvm_warning due to UVM_PREDICT_DIRECT
|
||||
intr_state_fld.predict(field_val | `gmv(intr_state_fld), .kind(UVM_PREDICT_READ));
|
||||
end
|
||||
|
||||
super.do_predict(rw, kind, be);
|
||||
endfunction
|
||||
|
||||
// when use UVM_PREDICT_WRITE and the CSR access is WO, this function will return the default
|
||||
// val of the register, rather than the written value
|
||||
virtual function uvm_reg_data_t XpredictX(uvm_reg_data_t cur_val,
|
||||
|
@ -46,6 +70,11 @@ class dv_base_reg_field extends uvm_reg_field;
|
|||
return m_original_access;
|
||||
endfunction
|
||||
|
||||
virtual function uvm_reg_data_t get_field_mask();
|
||||
get_field_mask = (1'b1 << this.get_n_bits()) - 1;
|
||||
get_field_mask = get_field_mask << this.get_lsb_pos();
|
||||
endfunction
|
||||
|
||||
virtual function void set_original_access(string access);
|
||||
if (m_original_access == "") begin
|
||||
m_original_access = access;
|
||||
|
@ -54,12 +83,76 @@ class dv_base_reg_field extends uvm_reg_field;
|
|||
end
|
||||
endfunction
|
||||
|
||||
virtual function void set_locked_fields_access(string access = "original_access");
|
||||
case (access)
|
||||
"RO": void'(this.set_access(access));
|
||||
"original_access": void'(this.set_access(m_original_access));
|
||||
default: `uvm_fatal(`gfn, $sformatf("attempt to set access to %s", access))
|
||||
endcase
|
||||
// Lock the write access to this field.
|
||||
// This only pertains to a lockable field. It is invoked in the `set_lockable_flds_access()`
|
||||
// method of its corresponding lock (wen) field.
|
||||
local function void set_fld_access(bit lock);
|
||||
if (lock) void'(this.set_access("RO"));
|
||||
else void'(this.set_access(m_original_access));
|
||||
endfunction
|
||||
|
||||
// If input is a reg, add all fields under the reg; if input is a field, add the specific field.
|
||||
function void add_lockable_reg_or_fld(uvm_object lockable_obj);
|
||||
dv_base_reg_field flds[$];
|
||||
uvm_reg_block ral = this.get_parent().get_parent();
|
||||
`DV_CHECK_EQ_FATAL(ral.is_locked(), 0, "RAL is locked, cannot add lockable reg or fld!")
|
||||
get_flds_from_uvm_object(lockable_obj, `gfn, flds);
|
||||
foreach (flds[i]) lockable_flds.push_back(flds[i]);
|
||||
endfunction
|
||||
|
||||
// Returns true if this field can lock the specified register/field, else return false.
|
||||
// If lockable register is partially lockable (only certain field is lockable), this method will
|
||||
// still return true.
|
||||
function bit locks_reg_or_fld(uvm_object obj);
|
||||
dv_base_reg_field flds[$];
|
||||
get_flds_from_uvm_object(obj, `gfn, flds);
|
||||
foreach (flds[i]) begin
|
||||
if (flds[i] inside {lockable_flds}) return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
|
||||
function bit is_wen_fld();
|
||||
return (lockable_flds.size() > 0);
|
||||
endfunction
|
||||
|
||||
// If lock is set to 1, lockable fields access policy will be set to RO access.
|
||||
// If lock resets to 0, lockable fields will be set back to their original accesses.
|
||||
function void set_lockable_flds_access(bit lock);
|
||||
foreach (lockable_flds[i]) lockable_flds[i].set_fld_access(lock);
|
||||
endfunction
|
||||
|
||||
function void get_lockable_flds(ref dv_base_reg_field lockable_flds_q[$]);
|
||||
lockable_flds_q = lockable_flds;
|
||||
endfunction
|
||||
|
||||
// override RAL's reset function to support enable registers
|
||||
// when reset issued - the lockable field's access will be reset to original access
|
||||
virtual function void reset(string kind = "HARD");
|
||||
super.reset(kind);
|
||||
set_fld_access(0);
|
||||
endfunction
|
||||
|
||||
// this function can only be called when this reg is intr_test reg
|
||||
// Example: ral.intr_test.get_intr_state_field()
|
||||
local function uvm_reg_field get_intr_state_field();
|
||||
uvm_reg_block blk = get_parent().get_parent();
|
||||
uvm_reg intr_state_csr;
|
||||
uvm_reg_field fields[$];
|
||||
string intr_state_csr_name;
|
||||
string intr_test_csr_name = get_parent().get_name();
|
||||
bit is_intr_state_csr = !(uvm_re_match("intr_test*", intr_test_csr_name));
|
||||
|
||||
`DV_CHECK_EQ_FATAL(is_intr_state_csr, 1)
|
||||
|
||||
// intr_enable and intr_state have the same suffix
|
||||
intr_state_csr_name = str_utils_pkg::str_replace(intr_test_csr_name, "test", "state");
|
||||
|
||||
intr_state_csr = blk.get_reg_by_name(intr_state_csr_name);
|
||||
intr_state_csr.get_fields(fields);
|
||||
|
||||
// the field location for intr_state and intr_test should be the same
|
||||
return fields[get_lsb_pos()];
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
|
@ -46,8 +46,9 @@ package dv_base_reg_pkg;
|
|||
BkdrRegPathGlsShdow // backdoor path for shadow reg's shadow val in GLS
|
||||
} bkdr_reg_path_e;
|
||||
|
||||
// package sources
|
||||
// base ral
|
||||
typedef class dv_base_reg_block;
|
||||
typedef class dv_base_reg;
|
||||
|
||||
`include "csr_excl_item.sv"
|
||||
`include "dv_base_reg_field.sv"
|
||||
`include "dv_base_reg.sv"
|
||||
|
@ -55,4 +56,21 @@ package dv_base_reg_pkg;
|
|||
`include "dv_base_reg_block.sv"
|
||||
`include "dv_base_reg_map.sv"
|
||||
|
||||
function automatic void get_flds_from_uvm_object(input uvm_object obj,
|
||||
input string msg = "dv_base_reg_pkg",
|
||||
ref dv_base_reg_field flds[$]);
|
||||
dv_base_reg csr;
|
||||
dv_base_reg_field fld;
|
||||
|
||||
flds.delete();
|
||||
if ($cast(csr, obj)) begin
|
||||
csr.get_dv_base_reg_fields(flds);
|
||||
end else if ($cast(fld, obj)) begin
|
||||
flds.push_back(fld);
|
||||
end else begin
|
||||
`uvm_fatal(msg, $sformatf("obj %0s is not of type uvm_reg or uvm_reg_field",
|
||||
obj.get_full_name()))
|
||||
end
|
||||
endfunction
|
||||
|
||||
endpackage
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
package str_utils_pkg;
|
||||
`include "dv_macros.svh"
|
||||
|
||||
string msg_id = "str_utils_pkg";
|
||||
|
||||
// Returns 1 if string 's' has substring 'sub' within the given index range. 0 Otherwise.
|
||||
function automatic bit str_has_substr(string s, string sub, int range_lo = 0, int range_hi = -1);
|
||||
if (range_hi < 0 || range_hi >= s.len()) range_hi = s.len() - 1;
|
||||
|
@ -40,6 +42,22 @@ package str_utils_pkg;
|
|||
return -1;
|
||||
endfunction : str_rfind
|
||||
|
||||
// Find the first match string 'sub' in 's' and replace it with 'new_sub'.
|
||||
// TODO: Add support for global replacement.
|
||||
function automatic string str_replace(string s, string sub, string new_sub);
|
||||
string str_before_sub, str_after_sub;
|
||||
int lo_idx = str_find(s, sub);
|
||||
|
||||
// check sub string exists
|
||||
`DV_CHECK_NE_FATAL(lo_idx, -1, $sformatf("sub string %s doesn't exist in %s", sub, s), msg_id)
|
||||
|
||||
// the new_str contains 3 portions {str_before_sub, new_sub, str_after_sub}
|
||||
if (lo_idx > 0) str_before_sub = s.substr(0, lo_idx - 1);
|
||||
if (lo_idx + sub.len() < s.len()) str_after_sub = s.substr(lo_idx + sub.len(), s.len() - 1);
|
||||
|
||||
return {str_before_sub, new_sub, str_after_sub};
|
||||
endfunction : str_replace
|
||||
|
||||
// Strips a given set of characters in string 's'.
|
||||
//
|
||||
// The set of characters to strip is provided as a string. If not set, all whitespace characters
|
||||
|
|
|
@ -140,8 +140,9 @@
|
|||
cover_reg_top_vcs_cov_cfg_file: "-cm_hier {dv_root}/tools/vcs/cover_reg_top.cfg"
|
||||
|
||||
// Project defaults for Xcelium
|
||||
// xcelium_cov_cfg_file: "{{build_mode}_xcelium_cov_cfg_file}"
|
||||
// xcelium_cov_refine_files: ["{dv_root}/tools/xcelium/common_cov.vRefine"]
|
||||
xcelium_cov_cfg_file: "{dv_root}/tools/xcelium/xcelium.ccf"
|
||||
xcelium_cov_refine_files: []
|
||||
xcelium_common_excl_file: ["{dv_root}/tools/xcelium/exclude.tcl"]
|
||||
|
||||
// Build-specific coverage cfg files for Xcelium.
|
||||
// default_xcelium_cov_cfg_file: "-covfile {dv_root}/tools/xcelium/cover.ccf"
|
||||
|
|
3
vendor/lowrisc_ip/dv/tools/dvsim/sim.mk
vendored
3
vendor/lowrisc_ip/dv/tools/dvsim/sim.mk
vendored
|
@ -2,6 +2,7 @@
|
|||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export SHELL := /bin/bash
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
LOCK_SW_BUILD_DIR ?= flock --timeout 3600 ${sw_build_dir} --command
|
||||
|
@ -56,7 +57,7 @@ ifneq (${sw_images},)
|
|||
mkdir -p ${sw_build_dir}
|
||||
# Initialize meson build system.
|
||||
${LOCK_SW_BUILD_DIR} "cd ${proj_root} && \
|
||||
BUILD_ROOT=${sw_build_dir} ${proj_root}/meson_init.sh"
|
||||
env BUILD_ROOT=${sw_build_dir} ${proj_root}/meson_init.sh"
|
||||
|
||||
# Loop through the list of sw_images and invoke meson on each item.
|
||||
# `sw_images` is a space-separated list of tests to be built into an image.
|
||||
|
|
|
@ -116,7 +116,8 @@
|
|||
"-64bit",
|
||||
"-licqueue",
|
||||
"-load {cov_merge_db_dir}",
|
||||
"{xcelium_cov_refine_files}"]
|
||||
"-init {xcelium_common_excl_file}",
|
||||
" {eval_cmd} echo {xcelium_cov_refine_files} | sed -E 's/(\\S+)/-load_refinement \\1/g' "]
|
||||
|
||||
// pass and fail patterns
|
||||
build_fail_patterns: ["\\*E.*$"]
|
||||
|
@ -134,8 +135,8 @@
|
|||
"-coverage {cov_metrics}",
|
||||
// Limit the scope of coverage collection to the DUT.
|
||||
"-covdut {dut}",
|
||||
// Set the coverage configuration file.
|
||||
"{xcelium_cov_cfg_file}"]
|
||||
// Set the coverage configuration file
|
||||
"-covfile {xcelium_cov_cfg_file}"]
|
||||
run_opts: [// Coverage database output location.
|
||||
"-covworkdir {cov_work_dir}",
|
||||
// Set the scope to the build mode name.
|
||||
|
|
11
vendor/lowrisc_ip/dv/tools/xcelium/exclude.tcl
vendored
Normal file
11
vendor/lowrisc_ip/dv/tools/xcelium/exclude.tcl
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.parity'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.parity_en'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_param'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_param'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_sink'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_user'
|
||||
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.rsvd1'
|
18
vendor/lowrisc_ip/dv/tools/xcelium/xcelium.ccf
vendored
Normal file
18
vendor/lowrisc_ip/dv/tools/xcelium/xcelium.ccf
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// only collect toggle coverage on dut
|
||||
deselect_coverage -toggle -instance tb.dut.*...
|
||||
|
||||
// only collect toggle coverage on ports
|
||||
set_toggle_portsonly
|
||||
|
||||
// enable toggle scoring of structs and multidim arrays + MDA structs
|
||||
set_toggle_scoring -sv_mda -sv_mda_of_struct
|
||||
|
||||
// filter glitches
|
||||
set_toggle_strobe 0ps
|
||||
|
||||
// Filter unreachable/statically constant blocks
|
||||
set_com -log
|
|
@ -245,12 +245,13 @@ static void WriteSegment(const MemArea &m, uint32_t offset,
|
|||
// be caught at this function's callsite.
|
||||
SVScoped scoped(m.location.data());
|
||||
|
||||
// This "mini buffer" is used to transfer each write to SystemVerilog. It's
|
||||
// not massively efficient, but doing so ensures that we pass 256 bits (32
|
||||
// bytes) of initialised data each time. This is for simutil_set_mem (defined
|
||||
// in prim_util_memload.svh), whose "val" argument has SystemVerilog type bit
|
||||
// [255:0].
|
||||
uint8_t minibuf[32];
|
||||
// This "mini buffer" is used to transfer each write to SystemVerilog.
|
||||
// `simutil_set_mem` takes a fixed 312 bit vector but it will only use the
|
||||
// bits required for the RAM width. For example for a 32-bit wide RAM only
|
||||
// elements 3 - 0 of `minibuf` will be written to memory. The simulator may
|
||||
// still read bits from minibuf it does not use so we must use a fixed
|
||||
// allocation of the full bit vector size to avoid out of bounds access.
|
||||
uint8_t minibuf[39];
|
||||
memset(minibuf, 0, sizeof minibuf);
|
||||
assert(m.width_byte <= sizeof minibuf);
|
||||
|
||||
|
|
2
vendor/lowrisc_ip/ip/prim/prim.core
vendored
2
vendor/lowrisc_ip/ip/prim/prim.core
vendored
|
@ -18,6 +18,7 @@ filesets:
|
|||
- lowrisc:prim:buf
|
||||
- lowrisc:prim:flop
|
||||
- lowrisc:prim:flop_2sync
|
||||
- lowrisc:prim:cipher_pkg:0.1
|
||||
files:
|
||||
- rtl/prim_clock_gating_sync.sv
|
||||
- rtl/prim_alert_pkg.sv
|
||||
|
@ -39,7 +40,6 @@ filesets:
|
|||
- rtl/prim_keccak.sv
|
||||
- rtl/prim_packer.sv
|
||||
- rtl/prim_packer_fifo.sv
|
||||
- rtl/prim_cipher_pkg.sv
|
||||
- rtl/prim_present.sv
|
||||
- rtl/prim_prince.sv
|
||||
- rtl/prim_subst_perm.sv
|
||||
|
|
17
vendor/lowrisc_ip/ip/prim/prim_cipher_pkg.core
vendored
Normal file
17
vendor/lowrisc_ip/ip/prim/prim_cipher_pkg.core
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
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:prim:cipher_pkg:0.1"
|
||||
description: "PRINCE and PRESENT block cipher package"
|
||||
filesets:
|
||||
files_dv:
|
||||
files:
|
||||
- rtl/prim_cipher_pkg.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_dv
|
1
vendor/lowrisc_ip/ip/prim/prim_ram_1p.core
vendored
1
vendor/lowrisc_ip/ip/prim/prim_ram_1p.core
vendored
|
@ -9,6 +9,7 @@ filesets:
|
|||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:ram_1p_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
|
||||
|
|
18
vendor/lowrisc_ip/ip/prim/prim_ram_1p_pkg.core
vendored
Normal file
18
vendor/lowrisc_ip/ip/prim/prim_ram_1p_pkg.core
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
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:prim:ram_1p_pkg"
|
||||
description: "Ram 1p package"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
files:
|
||||
- rtl/prim_ram_1p_pkg.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
1
vendor/lowrisc_ip/ip/prim/prim_ram_2p.core
vendored
1
vendor/lowrisc_ip/ip/prim/prim_ram_2p.core
vendored
|
@ -9,6 +9,7 @@ filesets:
|
|||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:ram_2p_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
|
||||
|
|
18
vendor/lowrisc_ip/ip/prim/prim_ram_2p_pkg.core
vendored
Normal file
18
vendor/lowrisc_ip/ip/prim/prim_ram_2p_pkg.core
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
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:prim:ram_2p_pkg"
|
||||
description: "Ram 2p package"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
files:
|
||||
- rtl/prim_ram_2p_pkg.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
1
vendor/lowrisc_ip/ip/prim/prim_rom.core
vendored
1
vendor/lowrisc_ip/ip/prim/prim_rom.core
vendored
|
@ -9,6 +9,7 @@ filesets:
|
|||
primgen_dep:
|
||||
depend:
|
||||
- lowrisc:prim:prim_pkg
|
||||
- lowrisc:prim:rom_pkg
|
||||
- lowrisc:prim:primgen
|
||||
|
||||
|
||||
|
|
18
vendor/lowrisc_ip/ip/prim/prim_rom_pkg.core
vendored
Normal file
18
vendor/lowrisc_ip/ip/prim/prim_rom_pkg.core
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
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:prim:rom_pkg"
|
||||
description: "Rom package"
|
||||
filesets:
|
||||
files_rtl:
|
||||
depend:
|
||||
files:
|
||||
- rtl/prim_rom_pkg.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
1
vendor/lowrisc_ip/ip/prim/prim_secded.core
vendored
1
vendor/lowrisc_ip/ip/prim/prim_secded.core
vendored
|
@ -8,6 +8,7 @@ description: "SECDED ECC primitives"
|
|||
filesets:
|
||||
files_rtl:
|
||||
files:
|
||||
- rtl/prim_secded_pkg.sv
|
||||
- rtl/prim_secded_22_16_dec.sv
|
||||
- rtl/prim_secded_22_16_enc.sv
|
||||
- rtl/prim_secded_28_22_dec.sv
|
||||
|
|
18
vendor/lowrisc_ip/ip/prim/rtl/prim_clock_div.sv
vendored
18
vendor/lowrisc_ip/ip/prim/rtl/prim_clock_div.sv
vendored
|
@ -21,6 +21,11 @@ module prim_clock_div #(
|
|||
// For odd divide we need to introduce more parameters to control duty cycle
|
||||
`ASSERT_INIT(DivEven_A, (Divisor % 2) == 0)
|
||||
|
||||
// It is assumed the flops in this module are NOT on the scan-chain, as a result only
|
||||
// the input values are guarded
|
||||
logic step_down_req;
|
||||
assign step_down_req = test_en_i ? '0 : step_down_req_i;
|
||||
|
||||
logic clk_int;
|
||||
|
||||
if (Divisor == 2) begin : gen_div2
|
||||
|
@ -49,7 +54,7 @@ module prim_clock_div #(
|
|||
if (!rst_ni) begin
|
||||
step_down_nq <= 1'b0;
|
||||
end else begin
|
||||
step_down_nq <= step_down_req_i;
|
||||
step_down_nq <= step_down_req;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -72,7 +77,7 @@ module prim_clock_div #(
|
|||
logic [CntWidth-1:0] cnt;
|
||||
logic [CntWidth-1:0] limit;
|
||||
|
||||
assign limit = !step_down_req_i ? ToggleCnt - 1 :
|
||||
assign limit = !step_down_req ? ToggleCnt - 1 :
|
||||
(ToggleCnt / 2) == 2 ? '0 : (ToggleCnt / 2) - 1;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
@ -91,25 +96,22 @@ module prim_clock_div #(
|
|||
if (!rst_ni) begin
|
||||
step_down_ack_o <= 1'b0;
|
||||
end else begin
|
||||
step_down_ack_o <= step_down_req_i;
|
||||
step_down_ack_o <= step_down_req;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// when in scanmode, bypass the dividers completely
|
||||
// also anchor point for constraints
|
||||
// anchor points for constraints
|
||||
logic clk_muxed;
|
||||
|
||||
prim_clock_mux2 #(
|
||||
.NoFpgaBufG(1'b1)
|
||||
) u_clk_mux (
|
||||
.clk0_i(clk_int),
|
||||
.clk1_i(clk_i),
|
||||
.sel_i(test_en_i),
|
||||
.sel_i('0),
|
||||
.clk_o(clk_muxed)
|
||||
);
|
||||
|
||||
// anchor point for constraints
|
||||
prim_clock_buf u_clk_div_buf (
|
||||
.clk_i(clk_muxed),
|
||||
.clk_o
|
||||
|
|
296
vendor/lowrisc_ip/ip/prim/rtl/prim_fifo_async.sv
vendored
296
vendor/lowrisc_ip/ip/prim/rtl/prim_fifo_async.sv
vendored
|
@ -8,185 +8,259 @@
|
|||
|
||||
module prim_fifo_async #(
|
||||
parameter int unsigned Width = 16,
|
||||
parameter int unsigned Depth = 3,
|
||||
parameter int unsigned Depth = 4,
|
||||
localparam int unsigned DepthW = $clog2(Depth+1) // derived parameter representing [0..Depth]
|
||||
) (
|
||||
// write port
|
||||
input clk_wr_i,
|
||||
input rst_wr_ni,
|
||||
input wvalid_i,
|
||||
output wready_o,
|
||||
input [Width-1:0] wdata_i,
|
||||
output [DepthW-1:0] wdepth_o,
|
||||
input logic clk_wr_i,
|
||||
input logic rst_wr_ni,
|
||||
input logic wvalid_i,
|
||||
output logic wready_o,
|
||||
input logic [Width-1:0] wdata_i,
|
||||
output logic [DepthW-1:0] wdepth_o,
|
||||
|
||||
// read port
|
||||
input clk_rd_i,
|
||||
input rst_rd_ni,
|
||||
output rvalid_o,
|
||||
input rready_i,
|
||||
output [Width-1:0] rdata_o,
|
||||
output [DepthW-1:0] rdepth_o
|
||||
input logic clk_rd_i,
|
||||
input logic rst_rd_ni,
|
||||
output logic rvalid_o,
|
||||
input logic rready_i,
|
||||
output logic [Width-1:0] rdata_o,
|
||||
output logic [DepthW-1:0] rdepth_o
|
||||
);
|
||||
|
||||
// Depth must be a power of 2 for the gray code pointers to work
|
||||
`ASSERT_INIT(ParamCheckDepth_A, (Depth > 2) && (Depth == 2**$clog2(Depth)))
|
||||
`ASSERT_INIT(ParamCheckDepth_A, (Depth == 2**$clog2(Depth)))
|
||||
|
||||
localparam int unsigned PTRV_W = $clog2(Depth);
|
||||
localparam int unsigned PTR_WIDTH = PTRV_W+1;
|
||||
localparam int unsigned PTRV_W = (Depth == 1) ? 1 : $clog2(Depth);
|
||||
localparam int unsigned PTR_WIDTH = (Depth == 1) ? 1 : PTRV_W+1;
|
||||
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr, fifo_rptr;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_sync_combi, fifo_rptr_sync;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_gray_sync, fifo_rptr_gray_sync;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_gray, fifo_rptr_gray;
|
||||
logic fifo_incr_wptr, fifo_incr_rptr, empty;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_q, fifo_wptr_d;
|
||||
logic [PTR_WIDTH-1:0] fifo_rptr_q, fifo_rptr_d;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_sync_combi, fifo_rptr_sync_combi;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_gray_sync, fifo_rptr_gray_sync, fifo_rptr_sync_q;
|
||||
logic [PTR_WIDTH-1:0] fifo_wptr_gray_q, fifo_wptr_gray_d;
|
||||
logic [PTR_WIDTH-1:0] fifo_rptr_gray_q, fifo_rptr_gray_d;
|
||||
logic fifo_incr_wptr, fifo_incr_rptr;
|
||||
logic full_wclk, full_rclk, empty_rclk;
|
||||
logic [Width-1:0] storage [Depth];
|
||||
|
||||
logic full_wclk, full_rclk;
|
||||
|
||||
assign wready_o = !full_wclk;
|
||||
assign rvalid_o = !empty;
|
||||
|
||||
// create the write and read pointers
|
||||
///////////////////
|
||||
// Write Pointer //
|
||||
///////////////////
|
||||
|
||||
assign fifo_incr_wptr = wvalid_i & wready_o;
|
||||
assign fifo_incr_rptr = rvalid_o & rready_i;
|
||||
|
||||
///////////////////
|
||||
// write pointer //
|
||||
///////////////////
|
||||
// decimal version
|
||||
assign fifo_wptr_d = fifo_wptr_q + PTR_WIDTH'(1);
|
||||
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni)
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni) begin
|
||||
if (!rst_wr_ni) begin
|
||||
fifo_wptr <= {(PTR_WIDTH){1'b0}};
|
||||
fifo_wptr_q <= '0;
|
||||
end else if (fifo_incr_wptr) begin
|
||||
fifo_wptr <= fifo_wptr + PTR_WIDTH'(1);
|
||||
fifo_wptr_q <= fifo_wptr_d;
|
||||
end
|
||||
end
|
||||
|
||||
// gray-coded version
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni)
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni) begin
|
||||
if (!rst_wr_ni) begin
|
||||
fifo_wptr_gray <= {(PTR_WIDTH){1'b0}};
|
||||
fifo_wptr_gray_q <= '0;
|
||||
end else if (fifo_incr_wptr) begin
|
||||
fifo_wptr_gray <= dec2gray(fifo_wptr + PTR_WIDTH'(1));
|
||||
fifo_wptr_gray_q <= fifo_wptr_gray_d;
|
||||
end
|
||||
end
|
||||
|
||||
// sync gray-coded pointer to read clk
|
||||
prim_flop_2sync #(.Width(PTR_WIDTH)) sync_wptr (
|
||||
.clk_i (clk_rd_i),
|
||||
.rst_ni (rst_rd_ni),
|
||||
.d_i (fifo_wptr_gray),
|
||||
.d_i (fifo_wptr_gray_q),
|
||||
.q_o (fifo_wptr_gray_sync));
|
||||
|
||||
assign fifo_wptr_sync_combi = gray2dec(fifo_wptr_gray_sync);
|
||||
|
||||
//////////////////
|
||||
// read pointer //
|
||||
// Read Pointer //
|
||||
//////////////////
|
||||
|
||||
always_ff @(posedge clk_rd_i or negedge rst_rd_ni)
|
||||
assign fifo_incr_rptr = rvalid_o & rready_i;
|
||||
|
||||
// decimal version
|
||||
assign fifo_rptr_d = fifo_rptr_q + PTR_WIDTH'(1);
|
||||
|
||||
always_ff @(posedge clk_rd_i or negedge rst_rd_ni) begin
|
||||
if (!rst_rd_ni) begin
|
||||
fifo_rptr <= {(PTR_WIDTH){1'b0}};
|
||||
fifo_rptr_q <= '0;
|
||||
end else if (fifo_incr_rptr) begin
|
||||
fifo_rptr <= fifo_rptr + PTR_WIDTH'(1);
|
||||
fifo_rptr_q <= fifo_rptr_d;
|
||||
end
|
||||
end
|
||||
|
||||
// gray-coded version
|
||||
always_ff @(posedge clk_rd_i or negedge rst_rd_ni)
|
||||
always_ff @(posedge clk_rd_i or negedge rst_rd_ni) begin
|
||||
if (!rst_rd_ni) begin
|
||||
fifo_rptr_gray <= {(PTR_WIDTH){1'b0}};
|
||||
fifo_rptr_gray_q <= '0;
|
||||
end else if (fifo_incr_rptr) begin
|
||||
fifo_rptr_gray <= dec2gray(fifo_rptr + PTR_WIDTH'(1));
|
||||
fifo_rptr_gray_q <= fifo_rptr_gray_d;
|
||||
end
|
||||
end
|
||||
|
||||
// sync gray-coded pointer to write clk
|
||||
prim_flop_2sync #(.Width(PTR_WIDTH)) sync_rptr (
|
||||
.clk_i (clk_wr_i),
|
||||
.rst_ni (rst_wr_ni),
|
||||
.d_i (fifo_rptr_gray),
|
||||
.d_i (fifo_rptr_gray_q),
|
||||
.q_o (fifo_rptr_gray_sync));
|
||||
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni)
|
||||
// Registered version of synced read pointer
|
||||
always_ff @(posedge clk_wr_i or negedge rst_wr_ni) begin
|
||||
if (!rst_wr_ni) begin
|
||||
fifo_rptr_sync <= {PTR_WIDTH{1'b0}};
|
||||
fifo_rptr_sync_q <= '0;
|
||||
end else begin
|
||||
fifo_rptr_sync <= gray2dec(fifo_rptr_gray_sync);
|
||||
fifo_rptr_sync_q <= fifo_rptr_sync_combi;
|
||||
end
|
||||
end
|
||||
|
||||
//////////////////
|
||||
// empty / full //
|
||||
// Empty / Full //
|
||||
//////////////////
|
||||
|
||||
assign full_wclk = (fifo_wptr == (fifo_rptr_sync ^ {1'b1,{(PTR_WIDTH-1){1'b0}}}));
|
||||
assign full_rclk = (fifo_wptr_sync_combi == (fifo_rptr ^ {1'b1,{(PTR_WIDTH-1){1'b0}}}));
|
||||
assign full_wclk = (fifo_wptr_q == (fifo_rptr_sync_q ^ {1'b1,{(PTR_WIDTH-1){1'b0}}}));
|
||||
assign full_rclk = (fifo_wptr_sync_combi == (fifo_rptr_q ^ {1'b1,{(PTR_WIDTH-1){1'b0}}}));
|
||||
assign empty_rclk = (fifo_wptr_sync_combi == fifo_rptr_q);
|
||||
|
||||
// Current depth in the write clock side
|
||||
logic wptr_msb;
|
||||
logic rptr_sync_msb;
|
||||
logic [PTRV_W-1:0] wptr_value;
|
||||
logic [PTRV_W-1:0] rptr_sync_value;
|
||||
assign wptr_msb = fifo_wptr[PTR_WIDTH-1];
|
||||
assign rptr_sync_msb = fifo_rptr_sync[PTR_WIDTH-1];
|
||||
assign wptr_value = fifo_wptr[0+:PTRV_W];
|
||||
assign rptr_sync_value = fifo_rptr_sync[0+:PTRV_W];
|
||||
assign wdepth_o = (full_wclk) ? DepthW'(Depth) :
|
||||
(wptr_msb == rptr_sync_msb) ? DepthW'(wptr_value) - DepthW'(rptr_sync_value) :
|
||||
(DepthW'(Depth) - DepthW'(rptr_sync_value) + DepthW'(wptr_value)) ;
|
||||
if (Depth > 1) begin : g_depth_calc
|
||||
|
||||
// Same again in the read clock side
|
||||
assign empty = (fifo_wptr_sync_combi == fifo_rptr);
|
||||
logic rptr_msb;
|
||||
logic wptr_sync_msb;
|
||||
logic [PTRV_W-1:0] rptr_value;
|
||||
logic [PTRV_W-1:0] wptr_sync_value;
|
||||
assign wptr_sync_msb = fifo_wptr_sync_combi[PTR_WIDTH-1];
|
||||
assign rptr_msb = fifo_rptr[PTR_WIDTH-1];
|
||||
assign wptr_sync_value = fifo_wptr_sync_combi[0+:PTRV_W];
|
||||
assign rptr_value = fifo_rptr[0+:PTRV_W];
|
||||
assign rdepth_o = (full_rclk) ? DepthW'(Depth) :
|
||||
(wptr_sync_msb == rptr_msb) ? DepthW'(wptr_sync_value) - DepthW'(rptr_value) :
|
||||
(DepthW'(Depth) - DepthW'(rptr_value) + DepthW'(wptr_sync_value)) ;
|
||||
// Current depth in the write clock side
|
||||
logic wptr_msb;
|
||||
logic rptr_sync_msb;
|
||||
logic [PTRV_W-1:0] wptr_value;
|
||||
logic [PTRV_W-1:0] rptr_sync_value;
|
||||
|
||||
assign wptr_msb = fifo_wptr_q[PTR_WIDTH-1];
|
||||
assign rptr_sync_msb = fifo_rptr_sync_q[PTR_WIDTH-1];
|
||||
assign wptr_value = fifo_wptr_q[0+:PTRV_W];
|
||||
assign rptr_sync_value = fifo_rptr_sync_q[0+:PTRV_W];
|
||||
assign wdepth_o = (full_wclk) ? DepthW'(Depth) :
|
||||
(wptr_msb == rptr_sync_msb) ? DepthW'(wptr_value) - DepthW'(rptr_sync_value) :
|
||||
(DepthW'(Depth) - DepthW'(rptr_sync_value) + DepthW'(wptr_value)) ;
|
||||
|
||||
// Current depth in the read clock side
|
||||
logic rptr_msb;
|
||||
logic wptr_sync_msb;
|
||||
logic [PTRV_W-1:0] rptr_value;
|
||||
logic [PTRV_W-1:0] wptr_sync_value;
|
||||
|
||||
assign wptr_sync_msb = fifo_wptr_sync_combi[PTR_WIDTH-1];
|
||||
assign rptr_msb = fifo_rptr_q[PTR_WIDTH-1];
|
||||
assign wptr_sync_value = fifo_wptr_sync_combi[0+:PTRV_W];
|
||||
assign rptr_value = fifo_rptr_q[0+:PTRV_W];
|
||||
assign rdepth_o = (full_rclk) ? DepthW'(Depth) :
|
||||
(wptr_sync_msb == rptr_msb) ? DepthW'(wptr_sync_value) - DepthW'(rptr_value) :
|
||||
(DepthW'(Depth) - DepthW'(rptr_value) + DepthW'(wptr_sync_value)) ;
|
||||
|
||||
end else begin : g_no_depth_calc
|
||||
|
||||
assign rdepth_o = full_rclk;
|
||||
assign wdepth_o = full_wclk;
|
||||
|
||||
end
|
||||
|
||||
assign wready_o = !full_wclk;
|
||||
assign rvalid_o = !empty_rclk;
|
||||
|
||||
/////////////
|
||||
// storage //
|
||||
// Storage //
|
||||
/////////////
|
||||
|
||||
logic [Width-1:0] storage [Depth];
|
||||
if (Depth > 1) begin : g_storage_mux
|
||||
|
||||
always_ff @(posedge clk_wr_i)
|
||||
if (fifo_incr_wptr) begin
|
||||
storage[fifo_wptr[PTR_WIDTH-2:0]] <= wdata_i;
|
||||
always_ff @(posedge clk_wr_i) begin
|
||||
if (fifo_incr_wptr) begin
|
||||
storage[fifo_wptr_q[PTRV_W-1:0]] <= wdata_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign rdata_o = storage[fifo_rptr[PTR_WIDTH-2:0]];
|
||||
assign rdata_o = storage[fifo_rptr_q[PTRV_W-1:0]];
|
||||
|
||||
// gray code conversion functions. algorithm walks up from 0..N-1
|
||||
// then flips the upper bit and walks down from N-1 to 0.
|
||||
end else begin : g_storage_simple
|
||||
|
||||
function automatic [PTR_WIDTH-1:0] dec2gray(input logic [PTR_WIDTH-1:0] decval);
|
||||
logic [PTR_WIDTH-1:0] decval_sub;
|
||||
logic [PTR_WIDTH-2:0] decval_in;
|
||||
logic unused_decval_msb;
|
||||
always_ff @(posedge clk_wr_i) begin
|
||||
if (fifo_incr_wptr) begin
|
||||
storage[0] <= wdata_i;
|
||||
end
|
||||
end
|
||||
|
||||
decval_sub = (PTR_WIDTH)'(Depth) - {1'b0, decval[PTR_WIDTH-2:0]} - 1'b1;
|
||||
assign rdata_o = storage[0];
|
||||
|
||||
{unused_decval_msb, decval_in} = decval[PTR_WIDTH-1] ? decval_sub : decval;
|
||||
// Was done in two assigns for low bits and top bit
|
||||
// but that generates a (bogus) verilator warning, so do in one assign
|
||||
dec2gray = {decval[PTR_WIDTH-1],
|
||||
{1'b0,decval_in[PTR_WIDTH-2:1]} ^ decval_in[PTR_WIDTH-2:0]};
|
||||
endfunction
|
||||
end
|
||||
|
||||
function automatic [PTR_WIDTH-1:0] gray2dec(input logic [PTR_WIDTH-1:0] grayval);
|
||||
logic [PTR_WIDTH-2:0] dec_tmp, dec_tmp_sub;
|
||||
logic unused_decsub_msb;
|
||||
//////////////////////////////////////
|
||||
// Decimal <-> Gray-code Conversion //
|
||||
//////////////////////////////////////
|
||||
|
||||
dec_tmp[PTR_WIDTH-2] = grayval[PTR_WIDTH-2];
|
||||
for (int i = PTR_WIDTH-3; i >= 0; i--)
|
||||
dec_tmp[i] = dec_tmp[i+1]^grayval[i];
|
||||
{unused_decsub_msb, dec_tmp_sub} = (PTR_WIDTH-1)'(Depth) - {1'b0, dec_tmp} - 1'b1;
|
||||
if (grayval[PTR_WIDTH-1])
|
||||
gray2dec = {1'b1,dec_tmp_sub};
|
||||
else
|
||||
gray2dec = {1'b0,dec_tmp};
|
||||
endfunction
|
||||
// This code is all in a generate context to avoid lint errors when Depth <= 2
|
||||
if (Depth > 2) begin : g_full_gray_conversion
|
||||
|
||||
// TODO: assertions on full, empty, gray transitions
|
||||
function automatic [PTR_WIDTH-1:0] dec2gray(input logic [PTR_WIDTH-1:0] decval);
|
||||
logic [PTR_WIDTH-1:0] decval_sub;
|
||||
logic [PTR_WIDTH-2:0] decval_in;
|
||||
logic unused_decval_msb;
|
||||
|
||||
decval_sub = (PTR_WIDTH)'(Depth) - {1'b0, decval[PTR_WIDTH-2:0]} - 1'b1;
|
||||
|
||||
{unused_decval_msb, decval_in} = decval[PTR_WIDTH-1] ? decval_sub : decval;
|
||||
// Was done in two assigns for low bits and top bit
|
||||
// but that generates a (bogus) verilator warning, so do in one assign
|
||||
dec2gray = {decval[PTR_WIDTH-1],
|
||||
{1'b0,decval_in[PTR_WIDTH-2:1]} ^ decval_in[PTR_WIDTH-2:0]};
|
||||
endfunction
|
||||
|
||||
// Algorithm walks up from 0..N-1 then flips the upper bit and walks down from N-1 to 0.
|
||||
function automatic [PTR_WIDTH-1:0] gray2dec(input logic [PTR_WIDTH-1:0] grayval);
|
||||
logic [PTR_WIDTH-2:0] dec_tmp, dec_tmp_sub;
|
||||
logic unused_decsub_msb;
|
||||
|
||||
dec_tmp[PTR_WIDTH-2] = grayval[PTR_WIDTH-2];
|
||||
for (int i = PTR_WIDTH-3; i >= 0; i--) begin
|
||||
dec_tmp[i] = dec_tmp[i+1] ^ grayval[i];
|
||||
end
|
||||
{unused_decsub_msb, dec_tmp_sub} = (PTR_WIDTH-1)'(Depth) - {1'b0, dec_tmp} - 1'b1;
|
||||
if (grayval[PTR_WIDTH-1]) begin
|
||||
gray2dec = {1'b1, dec_tmp_sub};
|
||||
end else begin
|
||||
gray2dec = {1'b0, dec_tmp};
|
||||
end
|
||||
endfunction
|
||||
|
||||
// decimal version of read pointer in write domain
|
||||
assign fifo_rptr_sync_combi = gray2dec(fifo_rptr_gray_sync);
|
||||
// decimal version of write pointer in read domain
|
||||
assign fifo_wptr_sync_combi = gray2dec(fifo_wptr_gray_sync);
|
||||
|
||||
assign fifo_rptr_gray_d = dec2gray(fifo_rptr_d);
|
||||
assign fifo_wptr_gray_d = dec2gray(fifo_wptr_d);
|
||||
|
||||
end else if (Depth == 2) begin : g_simple_gray_conversion
|
||||
|
||||
assign fifo_rptr_sync_combi = {fifo_rptr_gray_sync[PTR_WIDTH-1], ^fifo_rptr_gray_sync};
|
||||
assign fifo_wptr_sync_combi = {fifo_wptr_gray_sync[PTR_WIDTH-1], ^fifo_rptr_gray_sync};
|
||||
|
||||
assign fifo_rptr_gray_d = {fifo_rptr_d[PTR_WIDTH-1], ^fifo_rptr_d};
|
||||
assign fifo_wptr_gray_d = {fifo_wptr_d[PTR_WIDTH-1], ^fifo_rptr_d};
|
||||
|
||||
end else begin : g_no_gray_conversion
|
||||
|
||||
assign fifo_rptr_sync_combi = fifo_rptr_gray_sync;
|
||||
assign fifo_wptr_sync_combi = fifo_wptr_gray_sync;
|
||||
|
||||
assign fifo_rptr_gray_d = fifo_rptr_d;
|
||||
assign fifo_wptr_gray_d = fifo_rptr_d;
|
||||
|
||||
end
|
||||
|
||||
// TODO: assertions on full, empty
|
||||
`ASSERT(GrayWptr_A, $countones(fifo_wptr_gray_q ^ $past(fifo_wptr_gray_q)) <= 1,
|
||||
clk_wr_i, !rst_wr_ni)
|
||||
`ASSERT(GrayRptr_A, $countones(fifo_rptr_gray_q ^ $past(fifo_rptr_gray_q)) <= 1,
|
||||
clk_rd_i, !rst_rd_ni)
|
||||
|
||||
endmodule
|
||||
|
|
10
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_adv.sv
vendored
10
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_adv.sv
vendored
|
@ -15,11 +15,10 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_ram_1p_adv #(
|
||||
module prim_ram_1p_adv import prim_ram_1p_pkg::*; #(
|
||||
parameter int Depth = 512,
|
||||
parameter int Width = 32,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
parameter int CfgW = 8, // WTC, RTC, etc
|
||||
parameter MemInitFile = "", // VMEM file to initialize the memory with
|
||||
|
||||
// Configurations
|
||||
|
@ -48,11 +47,9 @@ module prim_ram_1p_adv #(
|
|||
output logic [1:0] rerror_o, // Bit1: Uncorrectable, Bit0: Correctable
|
||||
|
||||
// config
|
||||
input [CfgW-1:0] cfg_i
|
||||
input ram_1p_cfg_t cfg_i
|
||||
);
|
||||
|
||||
logic [CfgW-1:0] unused_cfg;
|
||||
assign unused_cfg = cfg_i;
|
||||
|
||||
`ASSERT_INIT(CannotHaveEccAndParity_A, !(EnableParity && EnableECC))
|
||||
|
||||
|
@ -101,7 +98,8 @@ module prim_ram_1p_adv #(
|
|||
.addr_i (addr_q),
|
||||
.wdata_i (wdata_q),
|
||||
.wmask_i (wmask_q),
|
||||
.rdata_o (rdata_sram)
|
||||
.rdata_o (rdata_sram),
|
||||
.cfg_i
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
|
20
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv
vendored
Normal file
20
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package prim_ram_1p_pkg;
|
||||
|
||||
typedef struct packed {
|
||||
logic cfg_en;
|
||||
logic [3:0] cfg;
|
||||
} cfg_t;
|
||||
|
||||
typedef struct packed {
|
||||
cfg_t ram_cfg; // configuration for ram
|
||||
cfg_t rf_cfg; // configuration for regfile
|
||||
} ram_1p_cfg_t;
|
||||
|
||||
parameter ram_1p_cfg_t RAM_1P_CFG_DEFAULT = '0;
|
||||
|
||||
endpackage // prim_ram_1p_pkg
|
107
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_scr.sv
vendored
107
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_scr.sv
vendored
|
@ -23,12 +23,11 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_ram_1p_scr #(
|
||||
module prim_ram_1p_scr import prim_ram_1p_pkg::*; #(
|
||||
parameter int Depth = 16*1024, // Needs to be a power of 2 if NumAddrScrRounds > 0.
|
||||
parameter int Width = 32, // Needs to be byte aligned if byte parity is enabled.
|
||||
parameter int DataBitsPerMask = 8, // Needs to be set to 8 in case of byte parity.
|
||||
parameter bit EnableParity = 1, // Enable byte parity.
|
||||
parameter int CfgWidth = 8, // WTC, RTC, etc
|
||||
|
||||
// Scrambling parameters. Note that this needs to be low-latency, hence we have to keep the
|
||||
// amount of cipher rounds low. PRINCE has 5 half rounds in its original form, which corresponds
|
||||
|
@ -75,13 +74,19 @@ module prim_ram_1p_scr #(
|
|||
input [AddrWidth-1:0] addr_i,
|
||||
input [Width-1:0] wdata_i,
|
||||
input [Width-1:0] wmask_i, // Needs to be byte-aligned for parity
|
||||
// The incoming transaction contains an integrity error and the module should alter
|
||||
// its behavior appropriately.
|
||||
// On integrity errors, the primitive reverses the bit-order of the nonce and surpresses
|
||||
// any real transaction to the memory.
|
||||
input intg_error_i,
|
||||
output logic [Width-1:0] rdata_o,
|
||||
output logic rvalid_o, // Read response (rdata_o) is valid
|
||||
output logic [1:0] rerror_o, // Bit1: Uncorrectable, Bit0: Correctable
|
||||
output logic [31:0] raddr_o, // Read address for error reporting.
|
||||
output logic intg_error_o,
|
||||
|
||||
// config
|
||||
input [CfgWidth-1:0] cfg_i
|
||||
input ram_1p_cfg_t cfg_i
|
||||
);
|
||||
|
||||
//////////////////////
|
||||
|
@ -93,6 +98,24 @@ module prim_ram_1p_scr #(
|
|||
`ASSERT_INIT(DiffWidthAligned_A, (DataBitsPerMask % DiffWidth) == 0)
|
||||
`ASSERT_INIT(DiffWidthWithParity_A, EnableParity && (DiffWidth == 8) || !EnableParity)
|
||||
|
||||
//////////////////////////////
|
||||
// Integrity error latching //
|
||||
//////////////////////////////
|
||||
|
||||
logic intg_err_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
intg_err_q <= '0;
|
||||
end else if (intg_error_i) begin
|
||||
intg_err_q <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
prim_buf u_intg_err_out (
|
||||
.in_i(intg_error_i | intg_err_q),
|
||||
.out_o(intg_error_o)
|
||||
);
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Pending Write and Address Registers //
|
||||
/////////////////////////////////////////
|
||||
|
@ -118,8 +141,14 @@ module prim_ram_1p_scr #(
|
|||
assign addr_collision_d = read_en & (write_en_q | write_pending_q) & (addr_i == waddr_q);
|
||||
|
||||
// Macro requests and write strobe
|
||||
// The macro operation is silenced if an integrity error is seen
|
||||
logic macro_req;
|
||||
assign macro_req = read_en | write_en_q | write_pending_q;
|
||||
logic intg_err_macro_req;
|
||||
prim_buf u_intg_err_macro_req (
|
||||
.in_i(intg_error_i | intg_err_q),
|
||||
.out_o(intg_err_macro_req)
|
||||
);
|
||||
assign macro_req = ~intg_err_macro_req & (read_en | write_en_q | write_pending_q);
|
||||
// We are allowed to write a pending write transaction to the memory if there is no incoming read
|
||||
logic macro_write;
|
||||
assign macro_write = (write_en_q | write_pending_q) & ~read_en;
|
||||
|
@ -138,18 +167,34 @@ module prim_ram_1p_scr #(
|
|||
// This creates a bijective address mapping using a substitution / permutation network.
|
||||
logic [AddrWidth-1:0] addr_scr;
|
||||
if (NumAddrScrRounds > 0) begin : gen_addr_scr
|
||||
|
||||
// TODO, expand this into copies with another primitive
|
||||
logic intg_err_addr_scr;
|
||||
prim_buf u_intg_err_addr_scr (
|
||||
.in_i(intg_error_i | intg_err_q),
|
||||
.out_o(intg_err_addr_scr)
|
||||
);
|
||||
|
||||
// If there is an intergirty error, the nonce used is reversed
|
||||
logic [AddrWidth-1:0] addr_scr_nonce;
|
||||
for (genvar j = 0; j < AddrWidth; j++) begin : gen_addr_scr_nonce
|
||||
assign addr_scr_nonce[j] = intg_err_addr_scr ?
|
||||
nonce_i[NonceWidth - 1 - j] :
|
||||
nonce_i[NonceWidth - AddrWidth + j];
|
||||
end
|
||||
|
||||
prim_subst_perm #(
|
||||
.DataWidth ( AddrWidth ),
|
||||
.NumRounds ( NumAddrScrRounds ),
|
||||
.Decrypt ( 0 )
|
||||
) u_prim_subst_perm (
|
||||
.data_i ( addr_mux ),
|
||||
.data_i ( addr_mux ),
|
||||
// Since the counter mode concatenates {nonce_i[NonceWidth-1-AddrWidth:0], addr_i} to form
|
||||
// the IV, the upper AddrWidth bits of the nonce are not used and can be used for address
|
||||
// scrambling. In cases where N parallel PRINCE blocks are used due to a data
|
||||
// width > 64bit, N*AddrWidth nonce bits are left dangling.
|
||||
.key_i ( nonce_i[NonceWidth - 1 : NonceWidth - AddrWidth] ),
|
||||
.data_o ( addr_scr )
|
||||
.key_i ( addr_scr_nonce ),
|
||||
.data_o ( addr_scr )
|
||||
);
|
||||
end else begin : gen_no_addr_scr
|
||||
assign addr_scr = addr_mux;
|
||||
|
@ -166,8 +211,26 @@ module prim_ram_1p_scr #(
|
|||
// This encrypts the IV consisting of the nonce and address using the key provided in order to
|
||||
// generate the keystream for the data. Note that we instantiate a register halfway within this
|
||||
// primitive to balance the delay between request and response side.
|
||||
localparam int DataNonceWidth = 64 - AddrWidth;
|
||||
logic [NumParScr*64-1:0] keystream;
|
||||
logic [NumParScr-1:0][DataNonceWidth-1:0] data_scr_nonce;
|
||||
|
||||
// TODO, expand this into copies with another primitive
|
||||
logic intg_err_data_scr;
|
||||
prim_buf u_intg_err_data_scr (
|
||||
.in_i(intg_error_i | intg_err_q),
|
||||
.out_o(intg_err_data_scr)
|
||||
);
|
||||
|
||||
for (genvar k = 0; k < NumParScr; k++) begin : gen_par_scr
|
||||
|
||||
for (genvar j = 0; j < DataNonceWidth; j++) begin : gen_data_nonce
|
||||
assign data_scr_nonce[k][j] = intg_err_data_scr ?
|
||||
nonce_i[(k + 1) * DataNonceWidth - j] :
|
||||
nonce_i[k * DataNonceWidth + j];
|
||||
end
|
||||
|
||||
|
||||
prim_prince #(
|
||||
.DataWidth (64),
|
||||
.KeyWidth (128),
|
||||
|
@ -180,7 +243,8 @@ module prim_ram_1p_scr #(
|
|||
.rst_ni,
|
||||
.valid_i ( gnt_o ),
|
||||
// The IV is composed of a nonce and the row address
|
||||
.data_i ( {nonce_i[k * (64 - AddrWidth) +: (64 - AddrWidth)], addr_i} ),
|
||||
//.data_i ( {nonce_i[k * (64 - AddrWidth) +: (64 - AddrWidth)], addr_i} ),
|
||||
.data_i ( {data_scr_nonce[k], addr_i} ),
|
||||
// All parallel scramblers use the same key
|
||||
.key_i,
|
||||
// Since we operate in counter mode, this can always be set to encryption mode
|
||||
|
@ -222,8 +286,8 @@ module prim_ram_1p_scr #(
|
|||
localparam int LocalWidth = (Width - k * DiffWidth >= DiffWidth) ? DiffWidth :
|
||||
(Width - k * DiffWidth);
|
||||
|
||||
// Write path. Note that since this does not fan out into the interconnect, the write path is not
|
||||
// as critical as the read path below in terms of timing.
|
||||
// Write path. Note that since this does not fan out into the interconnect, the write path is
|
||||
// not as critical as the read path below in terms of timing.
|
||||
// Apply the keystream first
|
||||
logic [LocalWidth-1:0] wdata_xor;
|
||||
assign wdata_xor = wdata_q[k*DiffWidth +: LocalWidth] ^
|
||||
|
@ -296,16 +360,28 @@ module prim_ram_1p_scr #(
|
|||
logic rvalid_q;
|
||||
assign rvalid_o = rvalid_q;
|
||||
|
||||
// In case of a collision, we forward the write data from the unscrambled holding register
|
||||
assign rdata_o = (addr_collision_q) ? wdata_q : // forward pending (unscrambled) write data
|
||||
(rvalid_q) ? rdata : // regular reads
|
||||
'0; // tie to zero otherwise
|
||||
logic [Width-1:0] wmask_q;
|
||||
always_comb begin : p_forward_mux
|
||||
rdata_o = '0;
|
||||
// regular reads
|
||||
if (rvalid_q) begin
|
||||
rdata_o = rdata;
|
||||
end
|
||||
// In case of a collision, we forward the valid bytes of the write data from the unscrambled
|
||||
// holding register.
|
||||
if (addr_collision_q) begin
|
||||
for (int k = 0; k < Width; k++) begin
|
||||
if (wmask_q[k]) begin
|
||||
rdata_o[k] = wdata_q[k];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
///////////////
|
||||
// Registers //
|
||||
///////////////
|
||||
|
||||
logic [Width-1:0] wmask_q;
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_wdata_buf
|
||||
if (!rst_ni) begin
|
||||
write_pending_q <= 1'b0;
|
||||
|
@ -345,7 +421,6 @@ module prim_ram_1p_scr #(
|
|||
.Depth(Depth),
|
||||
.Width(Width),
|
||||
.DataBitsPerMask(DataBitsPerMask),
|
||||
.CfgW(CfgWidth),
|
||||
.EnableECC(1'b0),
|
||||
.EnableParity(EnableParity),
|
||||
.EnableInputPipeline(1'b0),
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_ram_2p_adv #(
|
||||
module prim_ram_2p_adv import prim_ram_2p_pkg::*; #(
|
||||
parameter int Depth = 512,
|
||||
parameter int Width = 32,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
parameter int CfgW = 8, // WTC, RTC, etc
|
||||
parameter MemInitFile = "", // VMEM file to initialize the memory with
|
||||
|
||||
// Configurations
|
||||
|
@ -56,14 +55,13 @@ module prim_ram_2p_adv #(
|
|||
output logic b_rvalid_o, // read response (b_rdata_o) is valid
|
||||
output logic [1:0] b_rerror_o, // Bit1: Uncorrectable, Bit0: Correctable
|
||||
|
||||
input [CfgW-1:0] cfg_i
|
||||
input ram_2p_cfg_t cfg_i
|
||||
);
|
||||
|
||||
prim_ram_2p_async_adv #(
|
||||
.Depth (Depth),
|
||||
.Width (Width),
|
||||
.DataBitsPerMask (DataBitsPerMask),
|
||||
.CfgW (CfgW),
|
||||
.MemInitFile (MemInitFile),
|
||||
.EnableECC (EnableECC),
|
||||
.EnableParity (EnableParity),
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_ram_2p_async_adv #(
|
||||
module prim_ram_2p_async_adv import prim_ram_2p_pkg::*; #(
|
||||
parameter int Depth = 512,
|
||||
parameter int Width = 32,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
parameter int CfgW = 8, // WTC, RTC, etc
|
||||
parameter MemInitFile = "", // VMEM file to initialize the memory with
|
||||
|
||||
// Configurations
|
||||
|
@ -59,11 +58,9 @@ module prim_ram_2p_async_adv #(
|
|||
output logic [1:0] b_rerror_o, // Bit1: Uncorrectable, Bit0: Correctable
|
||||
|
||||
// config
|
||||
input [CfgW-1:0] cfg_i
|
||||
input ram_2p_cfg_t cfg_i
|
||||
);
|
||||
|
||||
logic [CfgW-1:0] unused_cfg;
|
||||
assign unused_cfg = cfg_i;
|
||||
|
||||
`ASSERT_INIT(CannotHaveEccAndParity_A, !(EnableParity && EnableECC))
|
||||
|
||||
|
@ -130,7 +127,9 @@ module prim_ram_2p_async_adv #(
|
|||
.b_addr_i (b_addr_q),
|
||||
.b_wdata_i (b_wdata_q),
|
||||
.b_wmask_i (b_wmask_q),
|
||||
.b_rdata_o (b_rdata_sram)
|
||||
.b_rdata_o (b_rdata_sram),
|
||||
|
||||
.cfg_i
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_a_i or negedge rst_a_ni) begin
|
||||
|
|
22
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_2p_pkg.sv
vendored
Normal file
22
vendor/lowrisc_ip/ip/prim/rtl/prim_ram_2p_pkg.sv
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package prim_ram_2p_pkg;
|
||||
|
||||
typedef struct packed {
|
||||
logic cfg_en;
|
||||
logic [3:0] cfg;
|
||||
} cfg_t;
|
||||
|
||||
typedef struct packed {
|
||||
cfg_t a_ram_fcfg; // configuration for a port
|
||||
cfg_t a_ram_lcfg; // configuration for a port
|
||||
cfg_t b_ram_fcfg; // configuration for b port
|
||||
cfg_t b_ram_lcfg; // configuration for b port
|
||||
} ram_2p_cfg_t;
|
||||
|
||||
parameter ram_2p_cfg_t RAM_2P_CFG_DEFAULT = '0;
|
||||
|
||||
endpackage // prim_ram_2p_pkg
|
13
vendor/lowrisc_ip/ip/prim/rtl/prim_rom_adv.sv
vendored
13
vendor/lowrisc_ip/ip/prim/rtl/prim_rom_adv.sv
vendored
|
@ -6,14 +6,12 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_rom_adv #(
|
||||
module prim_rom_adv import prim_rom_pkg::*; #(
|
||||
// Parameters passed on the the ROM primitive.
|
||||
parameter int Width = 32,
|
||||
parameter int Depth = 2048, // 8kB default
|
||||
parameter MemInitFile = "", // VMEM file to initialize the memory with
|
||||
|
||||
parameter int CfgW = 8, // WTC, RTC, etc
|
||||
|
||||
localparam int Aw = $clog2(Depth)
|
||||
) (
|
||||
input logic clk_i,
|
||||
|
@ -23,13 +21,9 @@ module prim_rom_adv #(
|
|||
output logic rvalid_o,
|
||||
output logic [Width-1:0] rdata_o,
|
||||
|
||||
input [CfgW-1:0] cfg_i
|
||||
input rom_cfg_t cfg_i
|
||||
);
|
||||
|
||||
// We will eventually use cfg_i for RTC/WTC or other memory parameters.
|
||||
logic [CfgW-1:0] unused_cfg;
|
||||
assign unused_cfg = cfg_i;
|
||||
|
||||
prim_rom #(
|
||||
.Width(Width),
|
||||
.Depth(Depth),
|
||||
|
@ -38,7 +32,8 @@ module prim_rom_adv #(
|
|||
.clk_i,
|
||||
.req_i,
|
||||
.addr_i,
|
||||
.rdata_o
|
||||
.rdata_o,
|
||||
.cfg_i
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
|
13
vendor/lowrisc_ip/ip/prim/rtl/prim_rom_pkg.sv
vendored
Normal file
13
vendor/lowrisc_ip/ip/prim/rtl/prim_rom_pkg.sv
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package prim_rom_pkg;
|
||||
|
||||
typedef struct packed {
|
||||
logic cfg_en;
|
||||
logic [3:0] cfg;
|
||||
} rom_cfg_t;
|
||||
|
||||
endpackage // prim_rom_pkg
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 3741324996 -c hsiao
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_22_16_dec (
|
||||
input [21:0] in,
|
||||
|
@ -15,30 +15,30 @@ module prim_secded_22_16_dec (
|
|||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
assign syndrome_o[0] = ^(in & 22'h01C5C6);
|
||||
assign syndrome_o[1] = ^(in & 22'h023317);
|
||||
assign syndrome_o[2] = ^(in & 22'h049E2C);
|
||||
assign syndrome_o[3] = ^(in & 22'h0831E9);
|
||||
assign syndrome_o[4] = ^(in & 22'h10CA71);
|
||||
assign syndrome_o[5] = ^(in & 22'h206C9A);
|
||||
assign syndrome_o[0] = ^(in & 22'h019F41);
|
||||
assign syndrome_o[1] = ^(in & 22'h027A34);
|
||||
assign syndrome_o[2] = ^(in & 22'h0429CD);
|
||||
assign syndrome_o[3] = ^(in & 22'h08C0AF);
|
||||
assign syndrome_o[4] = ^(in & 22'h1074D2);
|
||||
assign syndrome_o[5] = ^(in & 22'h20873A);
|
||||
|
||||
// Corrected output calculation
|
||||
assign d_o[0] = (syndrome_o == 6'h1a) ^ in[0];
|
||||
assign d_o[1] = (syndrome_o == 6'h23) ^ in[1];
|
||||
assign d_o[2] = (syndrome_o == 6'h7) ^ in[2];
|
||||
assign d_o[0] = (syndrome_o == 6'hd) ^ in[0];
|
||||
assign d_o[1] = (syndrome_o == 6'h38) ^ in[1];
|
||||
assign d_o[2] = (syndrome_o == 6'he) ^ in[2];
|
||||
assign d_o[3] = (syndrome_o == 6'h2c) ^ in[3];
|
||||
assign d_o[4] = (syndrome_o == 6'h32) ^ in[4];
|
||||
assign d_o[5] = (syndrome_o == 6'h1c) ^ in[5];
|
||||
assign d_o[6] = (syndrome_o == 6'h19) ^ in[6];
|
||||
assign d_o[7] = (syndrome_o == 6'h29) ^ in[7];
|
||||
assign d_o[8] = (syndrome_o == 6'hb) ^ in[8];
|
||||
assign d_o[9] = (syndrome_o == 6'h16) ^ in[9];
|
||||
assign d_o[10] = (syndrome_o == 6'h25) ^ in[10];
|
||||
assign d_o[11] = (syndrome_o == 6'h34) ^ in[11];
|
||||
assign d_o[12] = (syndrome_o == 6'he) ^ in[12];
|
||||
assign d_o[13] = (syndrome_o == 6'h2a) ^ in[13];
|
||||
assign d_o[14] = (syndrome_o == 6'h31) ^ in[14];
|
||||
assign d_o[15] = (syndrome_o == 6'h15) ^ in[15];
|
||||
assign d_o[5] = (syndrome_o == 6'h2a) ^ in[5];
|
||||
assign d_o[6] = (syndrome_o == 6'h15) ^ in[6];
|
||||
assign d_o[7] = (syndrome_o == 6'h1c) ^ in[7];
|
||||
assign d_o[8] = (syndrome_o == 6'h25) ^ in[8];
|
||||
assign d_o[9] = (syndrome_o == 6'h23) ^ in[9];
|
||||
assign d_o[10] = (syndrome_o == 6'h31) ^ in[10];
|
||||
assign d_o[11] = (syndrome_o == 6'h7) ^ in[11];
|
||||
assign d_o[12] = (syndrome_o == 6'h13) ^ in[12];
|
||||
assign d_o[13] = (syndrome_o == 6'h16) ^ in[13];
|
||||
assign d_o[14] = (syndrome_o == 6'h1a) ^ in[14];
|
||||
assign d_o[15] = (syndrome_o == 6'h29) ^ in[15];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
assign single_error = ^syndrome_o;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 3741324996 -c hsiao
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_22_16_enc (
|
||||
input [15:0] in,
|
||||
|
@ -12,12 +12,12 @@ module prim_secded_22_16_enc (
|
|||
|
||||
always_comb begin : p_encode
|
||||
out = 22'(in);
|
||||
out[16] = ^(out & 22'h00C5C6);
|
||||
out[17] = ^(out & 22'h003317);
|
||||
out[18] = ^(out & 22'h009E2C);
|
||||
out[19] = ^(out & 22'h0031E9);
|
||||
out[20] = ^(out & 22'h00CA71);
|
||||
out[21] = ^(out & 22'h006C9A);
|
||||
out[16] = ^(out & 22'h009F41);
|
||||
out[17] = ^(out & 22'h007A34);
|
||||
out[18] = ^(out & 22'h0029CD);
|
||||
out[19] = ^(out & 22'h00C0AF);
|
||||
out[20] = ^(out & 22'h0074D2);
|
||||
out[21] = ^(out & 22'h00873A);
|
||||
end
|
||||
|
||||
endmodule : prim_secded_22_16_enc
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 22 -s 4256260335 -c hsiao
|
||||
// util/design/secded_gen.py -m 6 -k 22 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_28_22_dec (
|
||||
input [27:0] in,
|
||||
|
@ -16,11 +16,11 @@ module prim_secded_28_22_dec (
|
|||
|
||||
// Syndrome calculation
|
||||
assign syndrome_o[0] = ^(in & 28'h07003FF);
|
||||
assign syndrome_o[1] = ^(in & 28'h0B0FC0F);
|
||||
assign syndrome_o[1] = ^(in & 28'h090FC0F);
|
||||
assign syndrome_o[2] = ^(in & 28'h1371C71);
|
||||
assign syndrome_o[3] = ^(in & 28'h23B6592);
|
||||
assign syndrome_o[4] = ^(in & 28'h42DAAA4);
|
||||
assign syndrome_o[5] = ^(in & 28'h81ED348);
|
||||
assign syndrome_o[4] = ^(in & 28'h43DAAA4);
|
||||
assign syndrome_o[5] = ^(in & 28'h82ED348);
|
||||
|
||||
// Corrected output calculation
|
||||
assign d_o[0] = (syndrome_o == 6'h7) ^ in[0];
|
||||
|
@ -43,8 +43,8 @@ module prim_secded_28_22_dec (
|
|||
assign d_o[17] = (syndrome_o == 6'h2c) ^ in[17];
|
||||
assign d_o[18] = (syndrome_o == 6'h34) ^ in[18];
|
||||
assign d_o[19] = (syndrome_o == 6'h38) ^ in[19];
|
||||
assign d_o[20] = (syndrome_o == 6'h2f) ^ in[20];
|
||||
assign d_o[21] = (syndrome_o == 6'h1f) ^ in[21];
|
||||
assign d_o[20] = (syndrome_o == 6'h1f) ^ in[20];
|
||||
assign d_o[21] = (syndrome_o == 6'h3d) ^ in[21];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
assign single_error = ^syndrome_o;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 22 -s 4256260335 -c hsiao
|
||||
// util/design/secded_gen.py -m 6 -k 22 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_28_22_enc (
|
||||
input [21:0] in,
|
||||
|
@ -13,11 +13,11 @@ module prim_secded_28_22_enc (
|
|||
always_comb begin : p_encode
|
||||
out = 28'(in);
|
||||
out[22] = ^(out & 28'h03003FF);
|
||||
out[23] = ^(out & 28'h030FC0F);
|
||||
out[23] = ^(out & 28'h010FC0F);
|
||||
out[24] = ^(out & 28'h0371C71);
|
||||
out[25] = ^(out & 28'h03B6592);
|
||||
out[26] = ^(out & 28'h02DAAA4);
|
||||
out[27] = ^(out & 28'h01ED348);
|
||||
out[26] = ^(out & 28'h03DAAA4);
|
||||
out[27] = ^(out & 28'h02ED348);
|
||||
end
|
||||
|
||||
endmodule : prim_secded_28_22_enc
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 3759507082 -c hsiao
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_39_32_dec (
|
||||
input [38:0] in,
|
||||
|
@ -15,47 +15,47 @@ module prim_secded_39_32_dec (
|
|||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
assign syndrome_o[0] = ^(in & 39'h01432358F1);
|
||||
assign syndrome_o[1] = ^(in & 39'h02991D7680);
|
||||
assign syndrome_o[2] = ^(in & 39'h04417AA04E);
|
||||
assign syndrome_o[3] = ^(in & 39'h08EC104B1E);
|
||||
assign syndrome_o[4] = ^(in & 39'h10A484A4E5);
|
||||
assign syndrome_o[5] = ^(in & 39'h2016ED0B28);
|
||||
assign syndrome_o[6] = ^(in & 39'h403AC29513);
|
||||
assign syndrome_o[0] = ^(in & 39'h01850E56A2);
|
||||
assign syndrome_o[1] = ^(in & 39'h022E534C61);
|
||||
assign syndrome_o[2] = ^(in & 39'h040901A9FE);
|
||||
assign syndrome_o[3] = ^(in & 39'h087079A702);
|
||||
assign syndrome_o[4] = ^(in & 39'h10CABA900D);
|
||||
assign syndrome_o[5] = ^(in & 39'h20D3C44B18);
|
||||
assign syndrome_o[6] = ^(in & 39'h4034A430D5);
|
||||
|
||||
// Corrected output calculation
|
||||
assign d_o[0] = (syndrome_o == 7'h51) ^ in[0];
|
||||
assign d_o[1] = (syndrome_o == 7'h4c) ^ in[1];
|
||||
assign d_o[2] = (syndrome_o == 7'h1c) ^ in[2];
|
||||
assign d_o[3] = (syndrome_o == 7'h2c) ^ in[3];
|
||||
assign d_o[4] = (syndrome_o == 7'h49) ^ in[4];
|
||||
assign d_o[5] = (syndrome_o == 7'h31) ^ in[5];
|
||||
assign d_o[6] = (syndrome_o == 7'h15) ^ in[6];
|
||||
assign d_o[7] = (syndrome_o == 7'h13) ^ in[7];
|
||||
assign d_o[8] = (syndrome_o == 7'h68) ^ in[8];
|
||||
assign d_o[9] = (syndrome_o == 7'h2a) ^ in[9];
|
||||
assign d_o[10] = (syndrome_o == 7'h52) ^ in[10];
|
||||
assign d_o[11] = (syndrome_o == 7'h29) ^ in[11];
|
||||
assign d_o[12] = (syndrome_o == 7'h43) ^ in[12];
|
||||
assign d_o[13] = (syndrome_o == 7'h16) ^ in[13];
|
||||
assign d_o[14] = (syndrome_o == 7'hb) ^ in[14];
|
||||
assign d_o[15] = (syndrome_o == 7'h54) ^ in[15];
|
||||
assign d_o[16] = (syndrome_o == 7'h23) ^ in[16];
|
||||
assign d_o[17] = (syndrome_o == 7'h45) ^ in[17];
|
||||
assign d_o[18] = (syndrome_o == 7'h32) ^ in[18];
|
||||
assign d_o[19] = (syndrome_o == 7'h26) ^ in[19];
|
||||
assign d_o[20] = (syndrome_o == 7'he) ^ in[20];
|
||||
assign d_o[21] = (syndrome_o == 7'h25) ^ in[21];
|
||||
assign d_o[22] = (syndrome_o == 7'h64) ^ in[22];
|
||||
assign d_o[0] = (syndrome_o == 7'h52) ^ in[0];
|
||||
assign d_o[1] = (syndrome_o == 7'hd) ^ in[1];
|
||||
assign d_o[2] = (syndrome_o == 7'h54) ^ in[2];
|
||||
assign d_o[3] = (syndrome_o == 7'h34) ^ in[3];
|
||||
assign d_o[4] = (syndrome_o == 7'h64) ^ in[4];
|
||||
assign d_o[5] = (syndrome_o == 7'h7) ^ in[5];
|
||||
assign d_o[6] = (syndrome_o == 7'h46) ^ in[6];
|
||||
assign d_o[7] = (syndrome_o == 7'h45) ^ in[7];
|
||||
assign d_o[8] = (syndrome_o == 7'h2c) ^ in[8];
|
||||
assign d_o[9] = (syndrome_o == 7'h29) ^ in[9];
|
||||
assign d_o[10] = (syndrome_o == 7'hb) ^ in[10];
|
||||
assign d_o[11] = (syndrome_o == 7'h26) ^ in[11];
|
||||
assign d_o[12] = (syndrome_o == 7'h51) ^ in[12];
|
||||
assign d_o[13] = (syndrome_o == 7'h4c) ^ in[13];
|
||||
assign d_o[14] = (syndrome_o == 7'h23) ^ in[14];
|
||||
assign d_o[15] = (syndrome_o == 7'h1c) ^ in[15];
|
||||
assign d_o[16] = (syndrome_o == 7'he) ^ in[16];
|
||||
assign d_o[17] = (syndrome_o == 7'h13) ^ in[17];
|
||||
assign d_o[18] = (syndrome_o == 7'h61) ^ in[18];
|
||||
assign d_o[19] = (syndrome_o == 7'h19) ^ in[19];
|
||||
assign d_o[20] = (syndrome_o == 7'h1a) ^ in[20];
|
||||
assign d_o[21] = (syndrome_o == 7'h58) ^ in[21];
|
||||
assign d_o[22] = (syndrome_o == 7'h2a) ^ in[22];
|
||||
assign d_o[23] = (syndrome_o == 7'h70) ^ in[23];
|
||||
assign d_o[24] = (syndrome_o == 7'h7) ^ in[24];
|
||||
assign d_o[25] = (syndrome_o == 7'h61) ^ in[25];
|
||||
assign d_o[26] = (syndrome_o == 7'h38) ^ in[26];
|
||||
assign d_o[27] = (syndrome_o == 7'h4a) ^ in[27];
|
||||
assign d_o[28] = (syndrome_o == 7'h62) ^ in[28];
|
||||
assign d_o[29] = (syndrome_o == 7'h58) ^ in[29];
|
||||
assign d_o[30] = (syndrome_o == 7'hd) ^ in[30];
|
||||
assign d_o[31] = (syndrome_o == 7'h1a) ^ in[31];
|
||||
assign d_o[24] = (syndrome_o == 7'h25) ^ in[24];
|
||||
assign d_o[25] = (syndrome_o == 7'h32) ^ in[25];
|
||||
assign d_o[26] = (syndrome_o == 7'h43) ^ in[26];
|
||||
assign d_o[27] = (syndrome_o == 7'h16) ^ in[27];
|
||||
assign d_o[28] = (syndrome_o == 7'h68) ^ in[28];
|
||||
assign d_o[29] = (syndrome_o == 7'h4a) ^ in[29];
|
||||
assign d_o[30] = (syndrome_o == 7'h38) ^ in[30];
|
||||
assign d_o[31] = (syndrome_o == 7'h31) ^ in[31];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
assign single_error = ^syndrome_o;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 3759507082 -c hsiao
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_39_32_enc (
|
||||
input [31:0] in,
|
||||
|
@ -12,13 +12,13 @@ module prim_secded_39_32_enc (
|
|||
|
||||
always_comb begin : p_encode
|
||||
out = 39'(in);
|
||||
out[32] = ^(out & 39'h00432358F1);
|
||||
out[33] = ^(out & 39'h00991D7680);
|
||||
out[34] = ^(out & 39'h00417AA04E);
|
||||
out[35] = ^(out & 39'h00EC104B1E);
|
||||
out[36] = ^(out & 39'h00A484A4E5);
|
||||
out[37] = ^(out & 39'h0016ED0B28);
|
||||
out[38] = ^(out & 39'h003AC29513);
|
||||
out[32] = ^(out & 39'h00850E56A2);
|
||||
out[33] = ^(out & 39'h002E534C61);
|
||||
out[34] = ^(out & 39'h000901A9FE);
|
||||
out[35] = ^(out & 39'h007079A702);
|
||||
out[36] = ^(out & 39'h00CABA900D);
|
||||
out[37] = ^(out & 39'h00D3C44B18);
|
||||
out[38] = ^(out & 39'h0034A430D5);
|
||||
end
|
||||
|
||||
endmodule : prim_secded_39_32_enc
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 57 -s 2871209727 -c hsiao
|
||||
// util/design/secded_gen.py -m 7 -k 57 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_64_57_dec (
|
||||
input [63:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 57 -s 2871209727 -c hsiao
|
||||
// util/design/secded_gen.py -m 7 -k 57 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_64_57_enc (
|
||||
input [56:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 3843802612 -c hsiao
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_72_64_dec (
|
||||
input [71:0] in,
|
||||
|
@ -15,14 +15,14 @@ module prim_secded_72_64_dec (
|
|||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
assign syndrome_o[0] = ^(in & 72'h019B000000001FFFFF);
|
||||
assign syndrome_o[1] = ^(in & 72'h027900000FFFE0003F);
|
||||
assign syndrome_o[2] = ^(in & 72'h04DC003FF003E007C1);
|
||||
assign syndrome_o[3] = ^(in & 72'h08370FC0F03C207842);
|
||||
assign syndrome_o[4] = ^(in & 72'h10EA71C711C4438884);
|
||||
assign syndrome_o[5] = ^(in & 72'h202FB65926488C9108);
|
||||
assign syndrome_o[6] = ^(in & 72'h40E6DAAA4A91152210);
|
||||
assign syndrome_o[7] = ^(in & 72'h80D5ED348D221A4420);
|
||||
assign syndrome_o[0] = ^(in & 72'h019D000000001FFFFF);
|
||||
assign syndrome_o[1] = ^(in & 72'h027600000FFFE0003F);
|
||||
assign syndrome_o[2] = ^(in & 72'h0479003FF003E007C1);
|
||||
assign syndrome_o[3] = ^(in & 72'h08A70FC0F03C207842);
|
||||
assign syndrome_o[4] = ^(in & 72'h10D371C711C4438884);
|
||||
assign syndrome_o[5] = ^(in & 72'h20F8B65926488C9108);
|
||||
assign syndrome_o[6] = ^(in & 72'h40AEDAAA4A91152210);
|
||||
assign syndrome_o[7] = ^(in & 72'h804FED348D221A4420);
|
||||
|
||||
// Corrected output calculation
|
||||
assign d_o[0] = (syndrome_o == 8'h7) ^ in[0];
|
||||
|
@ -81,14 +81,14 @@ module prim_secded_72_64_dec (
|
|||
assign d_o[53] = (syndrome_o == 8'hb0) ^ in[53];
|
||||
assign d_o[54] = (syndrome_o == 8'hd0) ^ in[54];
|
||||
assign d_o[55] = (syndrome_o == 8'he0) ^ in[55];
|
||||
assign d_o[56] = (syndrome_o == 8'hab) ^ in[56];
|
||||
assign d_o[57] = (syndrome_o == 8'h79) ^ in[57];
|
||||
assign d_o[58] = (syndrome_o == 8'hec) ^ in[58];
|
||||
assign d_o[59] = (syndrome_o == 8'h37) ^ in[59];
|
||||
assign d_o[60] = (syndrome_o == 8'h8f) ^ in[60];
|
||||
assign d_o[61] = (syndrome_o == 8'h7a) ^ in[61];
|
||||
assign d_o[62] = (syndrome_o == 8'hd6) ^ in[62];
|
||||
assign d_o[63] = (syndrome_o == 8'hd5) ^ in[63];
|
||||
assign d_o[56] = (syndrome_o == 8'h9d) ^ in[56];
|
||||
assign d_o[57] = (syndrome_o == 8'hda) ^ in[57];
|
||||
assign d_o[58] = (syndrome_o == 8'hcb) ^ in[58];
|
||||
assign d_o[59] = (syndrome_o == 8'he5) ^ in[59];
|
||||
assign d_o[60] = (syndrome_o == 8'h37) ^ in[60];
|
||||
assign d_o[61] = (syndrome_o == 8'h6e) ^ in[61];
|
||||
assign d_o[62] = (syndrome_o == 8'hb6) ^ in[62];
|
||||
assign d_o[63] = (syndrome_o == 8'h79) ^ in[63];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
assign single_error = ^syndrome_o;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 3843802612 -c hsiao
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hsiao
|
||||
|
||||
module prim_secded_72_64_enc (
|
||||
input [63:0] in,
|
||||
|
@ -12,14 +12,14 @@ module prim_secded_72_64_enc (
|
|||
|
||||
always_comb begin : p_encode
|
||||
out = 72'(in);
|
||||
out[64] = ^(out & 72'h009B000000001FFFFF);
|
||||
out[65] = ^(out & 72'h007900000FFFE0003F);
|
||||
out[66] = ^(out & 72'h00DC003FF003E007C1);
|
||||
out[67] = ^(out & 72'h00370FC0F03C207842);
|
||||
out[68] = ^(out & 72'h00EA71C711C4438884);
|
||||
out[69] = ^(out & 72'h002FB65926488C9108);
|
||||
out[70] = ^(out & 72'h00E6DAAA4A91152210);
|
||||
out[71] = ^(out & 72'h00D5ED348D221A4420);
|
||||
out[64] = ^(out & 72'h009D000000001FFFFF);
|
||||
out[65] = ^(out & 72'h007600000FFFE0003F);
|
||||
out[66] = ^(out & 72'h0079003FF003E007C1);
|
||||
out[67] = ^(out & 72'h00A70FC0F03C207842);
|
||||
out[68] = ^(out & 72'h00D371C711C4438884);
|
||||
out[69] = ^(out & 72'h00F8B65926488C9108);
|
||||
out[70] = ^(out & 72'h00AEDAAA4A91152210);
|
||||
out[71] = ^(out & 72'h004FED348D221A4420);
|
||||
end
|
||||
|
||||
endmodule : prim_secded_72_64_enc
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1997031251 -c hamming
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_22_16_dec (
|
||||
input [21:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1997031251 -c hamming
|
||||
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_22_16_enc (
|
||||
input [15:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 390368410 -c hamming
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_39_32_dec (
|
||||
input [38:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 390368410 -c hamming
|
||||
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_39_32_enc (
|
||||
input [31:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Decoder generated by
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1218923287 -c hamming
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_72_64_dec (
|
||||
input [71:0] in,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1218923287 -c hamming
|
||||
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hamming
|
||||
|
||||
module prim_secded_hamming_72_64_enc (
|
||||
input [63:0] in,
|
||||
|
|
714
vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv
vendored
Normal file
714
vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv
vendored
Normal file
|
@ -0,0 +1,714 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// SECDED Encoder generated by
|
||||
// util/design/secded_gen.py -s 1592631616 from util/design/data/secded_cfg.hjson
|
||||
|
||||
package prim_secded_pkg;
|
||||
|
||||
typedef struct packed {
|
||||
logic [15:0] data;
|
||||
logic [5:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_22_16_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [21:0] data;
|
||||
logic [5:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_28_22_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] data;
|
||||
logic [6:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_39_32_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [56:0] data;
|
||||
logic [6:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_64_57_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [63:0] data;
|
||||
logic [7:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_72_64_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [15:0] data;
|
||||
logic [5:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_hamming_22_16_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] data;
|
||||
logic [6:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_hamming_39_32_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [63:0] data;
|
||||
logic [7:0] syndrome;
|
||||
logic [1:0] err;
|
||||
} secded_hamming_72_64_t;
|
||||
|
||||
function automatic logic [21:0] prim_secded_22_16_enc (logic [15:0] in);
|
||||
logic [21:0] out;
|
||||
out = 22'(in);
|
||||
out[16] = ^(out & 22'h009F41);
|
||||
out[17] = ^(out & 22'h007A34);
|
||||
out[18] = ^(out & 22'h0029CD);
|
||||
out[19] = ^(out & 22'h00C0AF);
|
||||
out[20] = ^(out & 22'h0074D2);
|
||||
out[21] = ^(out & 22'h00873A);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_22_16_t prim_secded_22_16_dec (logic [21:0] in);
|
||||
logic [15:0] d_o;
|
||||
logic [5:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_22_16_t dec;
|
||||
|
||||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 22'h019F41);
|
||||
syndrome_o[1] = ^(in & 22'h027A34);
|
||||
syndrome_o[2] = ^(in & 22'h0429CD);
|
||||
syndrome_o[3] = ^(in & 22'h08C0AF);
|
||||
syndrome_o[4] = ^(in & 22'h1074D2);
|
||||
syndrome_o[5] = ^(in & 22'h20873A);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 6'hd) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 6'h38) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 6'he) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 6'h2c) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 6'h32) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 6'h2a) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 6'h15) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 6'h1c) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 6'h25) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 6'h23) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 6'h31) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 6'h7) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 6'h13) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 6'h16) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 6'h1a) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 6'h29) ^ in[15];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
single_error = ^syndrome_o;
|
||||
err_o[0] = single_error;
|
||||
err_o[1] = ~single_error & (|syndrome_o);
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [27:0] prim_secded_28_22_enc (logic [21:0] in);
|
||||
logic [27:0] out;
|
||||
out = 28'(in);
|
||||
out[22] = ^(out & 28'h03003FF);
|
||||
out[23] = ^(out & 28'h010FC0F);
|
||||
out[24] = ^(out & 28'h0371C71);
|
||||
out[25] = ^(out & 28'h03B6592);
|
||||
out[26] = ^(out & 28'h03DAAA4);
|
||||
out[27] = ^(out & 28'h02ED348);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_28_22_t prim_secded_28_22_dec (logic [27:0] in);
|
||||
logic [21:0] d_o;
|
||||
logic [5:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_28_22_t dec;
|
||||
|
||||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 28'h07003FF);
|
||||
syndrome_o[1] = ^(in & 28'h090FC0F);
|
||||
syndrome_o[2] = ^(in & 28'h1371C71);
|
||||
syndrome_o[3] = ^(in & 28'h23B6592);
|
||||
syndrome_o[4] = ^(in & 28'h43DAAA4);
|
||||
syndrome_o[5] = ^(in & 28'h82ED348);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 6'h7) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 6'hb) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 6'h13) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 6'h23) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 6'hd) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 6'h15) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 6'h25) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 6'h19) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 6'h29) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 6'h31) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 6'he) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 6'h16) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 6'h26) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 6'h1a) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 6'h2a) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 6'h32) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 6'h1c) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 6'h2c) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 6'h34) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 6'h38) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 6'h1f) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 6'h3d) ^ in[21];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
single_error = ^syndrome_o;
|
||||
err_o[0] = single_error;
|
||||
err_o[1] = ~single_error & (|syndrome_o);
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [38:0] prim_secded_39_32_enc (logic [31:0] in);
|
||||
logic [38:0] out;
|
||||
out = 39'(in);
|
||||
out[32] = ^(out & 39'h00850E56A2);
|
||||
out[33] = ^(out & 39'h002E534C61);
|
||||
out[34] = ^(out & 39'h000901A9FE);
|
||||
out[35] = ^(out & 39'h007079A702);
|
||||
out[36] = ^(out & 39'h00CABA900D);
|
||||
out[37] = ^(out & 39'h00D3C44B18);
|
||||
out[38] = ^(out & 39'h0034A430D5);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_39_32_t prim_secded_39_32_dec (logic [38:0] in);
|
||||
logic [31:0] d_o;
|
||||
logic [6:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_39_32_t dec;
|
||||
|
||||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 39'h01850E56A2);
|
||||
syndrome_o[1] = ^(in & 39'h022E534C61);
|
||||
syndrome_o[2] = ^(in & 39'h040901A9FE);
|
||||
syndrome_o[3] = ^(in & 39'h087079A702);
|
||||
syndrome_o[4] = ^(in & 39'h10CABA900D);
|
||||
syndrome_o[5] = ^(in & 39'h20D3C44B18);
|
||||
syndrome_o[6] = ^(in & 39'h4034A430D5);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 7'h52) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 7'hd) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 7'h54) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 7'h34) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 7'h64) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 7'h7) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 7'h46) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 7'h45) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 7'h2c) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 7'h29) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 7'hb) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 7'h26) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 7'h51) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 7'h4c) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 7'h23) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 7'h1c) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 7'he) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 7'h13) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 7'h61) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 7'h19) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 7'h1a) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 7'h58) ^ in[21];
|
||||
d_o[22] = (syndrome_o == 7'h2a) ^ in[22];
|
||||
d_o[23] = (syndrome_o == 7'h70) ^ in[23];
|
||||
d_o[24] = (syndrome_o == 7'h25) ^ in[24];
|
||||
d_o[25] = (syndrome_o == 7'h32) ^ in[25];
|
||||
d_o[26] = (syndrome_o == 7'h43) ^ in[26];
|
||||
d_o[27] = (syndrome_o == 7'h16) ^ in[27];
|
||||
d_o[28] = (syndrome_o == 7'h68) ^ in[28];
|
||||
d_o[29] = (syndrome_o == 7'h4a) ^ in[29];
|
||||
d_o[30] = (syndrome_o == 7'h38) ^ in[30];
|
||||
d_o[31] = (syndrome_o == 7'h31) ^ in[31];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
single_error = ^syndrome_o;
|
||||
err_o[0] = single_error;
|
||||
err_o[1] = ~single_error & (|syndrome_o);
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [63:0] prim_secded_64_57_enc (logic [56:0] in);
|
||||
logic [63:0] out;
|
||||
out = 64'(in);
|
||||
out[57] = ^(out & 64'h0103FFF800007FFF);
|
||||
out[58] = ^(out & 64'h017C1FF801FF801F);
|
||||
out[59] = ^(out & 64'h01BDE1F87E0781E1);
|
||||
out[60] = ^(out & 64'h01DEEE3B8E388E22);
|
||||
out[61] = ^(out & 64'h01EF76CDB2C93244);
|
||||
out[62] = ^(out & 64'h01F7BB56D5525488);
|
||||
out[63] = ^(out & 64'h01FBDDA769A46910);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_64_57_t prim_secded_64_57_dec (logic [63:0] in);
|
||||
logic [56:0] d_o;
|
||||
logic [6:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_64_57_t dec;
|
||||
|
||||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 64'h0303FFF800007FFF);
|
||||
syndrome_o[1] = ^(in & 64'h057C1FF801FF801F);
|
||||
syndrome_o[2] = ^(in & 64'h09BDE1F87E0781E1);
|
||||
syndrome_o[3] = ^(in & 64'h11DEEE3B8E388E22);
|
||||
syndrome_o[4] = ^(in & 64'h21EF76CDB2C93244);
|
||||
syndrome_o[5] = ^(in & 64'h41F7BB56D5525488);
|
||||
syndrome_o[6] = ^(in & 64'h81FBDDA769A46910);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 7'h7) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 7'hb) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 7'h13) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 7'h23) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 7'h43) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 7'hd) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 7'h15) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 7'h25) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 7'h45) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 7'h19) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 7'h29) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 7'h49) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 7'h31) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 7'h51) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 7'h61) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 7'he) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 7'h16) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 7'h26) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 7'h46) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 7'h1a) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 7'h2a) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 7'h4a) ^ in[21];
|
||||
d_o[22] = (syndrome_o == 7'h32) ^ in[22];
|
||||
d_o[23] = (syndrome_o == 7'h52) ^ in[23];
|
||||
d_o[24] = (syndrome_o == 7'h62) ^ in[24];
|
||||
d_o[25] = (syndrome_o == 7'h1c) ^ in[25];
|
||||
d_o[26] = (syndrome_o == 7'h2c) ^ in[26];
|
||||
d_o[27] = (syndrome_o == 7'h4c) ^ in[27];
|
||||
d_o[28] = (syndrome_o == 7'h34) ^ in[28];
|
||||
d_o[29] = (syndrome_o == 7'h54) ^ in[29];
|
||||
d_o[30] = (syndrome_o == 7'h64) ^ in[30];
|
||||
d_o[31] = (syndrome_o == 7'h38) ^ in[31];
|
||||
d_o[32] = (syndrome_o == 7'h58) ^ in[32];
|
||||
d_o[33] = (syndrome_o == 7'h68) ^ in[33];
|
||||
d_o[34] = (syndrome_o == 7'h70) ^ in[34];
|
||||
d_o[35] = (syndrome_o == 7'h1f) ^ in[35];
|
||||
d_o[36] = (syndrome_o == 7'h2f) ^ in[36];
|
||||
d_o[37] = (syndrome_o == 7'h4f) ^ in[37];
|
||||
d_o[38] = (syndrome_o == 7'h37) ^ in[38];
|
||||
d_o[39] = (syndrome_o == 7'h57) ^ in[39];
|
||||
d_o[40] = (syndrome_o == 7'h67) ^ in[40];
|
||||
d_o[41] = (syndrome_o == 7'h3b) ^ in[41];
|
||||
d_o[42] = (syndrome_o == 7'h5b) ^ in[42];
|
||||
d_o[43] = (syndrome_o == 7'h6b) ^ in[43];
|
||||
d_o[44] = (syndrome_o == 7'h73) ^ in[44];
|
||||
d_o[45] = (syndrome_o == 7'h3d) ^ in[45];
|
||||
d_o[46] = (syndrome_o == 7'h5d) ^ in[46];
|
||||
d_o[47] = (syndrome_o == 7'h6d) ^ in[47];
|
||||
d_o[48] = (syndrome_o == 7'h75) ^ in[48];
|
||||
d_o[49] = (syndrome_o == 7'h79) ^ in[49];
|
||||
d_o[50] = (syndrome_o == 7'h3e) ^ in[50];
|
||||
d_o[51] = (syndrome_o == 7'h5e) ^ in[51];
|
||||
d_o[52] = (syndrome_o == 7'h6e) ^ in[52];
|
||||
d_o[53] = (syndrome_o == 7'h76) ^ in[53];
|
||||
d_o[54] = (syndrome_o == 7'h7a) ^ in[54];
|
||||
d_o[55] = (syndrome_o == 7'h7c) ^ in[55];
|
||||
d_o[56] = (syndrome_o == 7'h7f) ^ in[56];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
single_error = ^syndrome_o;
|
||||
err_o[0] = single_error;
|
||||
err_o[1] = ~single_error & (|syndrome_o);
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [71:0] prim_secded_72_64_enc (logic [63:0] in);
|
||||
logic [71:0] out;
|
||||
out = 72'(in);
|
||||
out[64] = ^(out & 72'h009D000000001FFFFF);
|
||||
out[65] = ^(out & 72'h007600000FFFE0003F);
|
||||
out[66] = ^(out & 72'h0079003FF003E007C1);
|
||||
out[67] = ^(out & 72'h00A70FC0F03C207842);
|
||||
out[68] = ^(out & 72'h00D371C711C4438884);
|
||||
out[69] = ^(out & 72'h00F8B65926488C9108);
|
||||
out[70] = ^(out & 72'h00AEDAAA4A91152210);
|
||||
out[71] = ^(out & 72'h004FED348D221A4420);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_72_64_t prim_secded_72_64_dec (logic [71:0] in);
|
||||
logic [63:0] d_o;
|
||||
logic [7:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_72_64_t dec;
|
||||
|
||||
logic single_error;
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 72'h019D000000001FFFFF);
|
||||
syndrome_o[1] = ^(in & 72'h027600000FFFE0003F);
|
||||
syndrome_o[2] = ^(in & 72'h0479003FF003E007C1);
|
||||
syndrome_o[3] = ^(in & 72'h08A70FC0F03C207842);
|
||||
syndrome_o[4] = ^(in & 72'h10D371C711C4438884);
|
||||
syndrome_o[5] = ^(in & 72'h20F8B65926488C9108);
|
||||
syndrome_o[6] = ^(in & 72'h40AEDAAA4A91152210);
|
||||
syndrome_o[7] = ^(in & 72'h804FED348D221A4420);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 8'h7) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 8'hb) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 8'h13) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 8'h23) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 8'h43) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 8'h83) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 8'hd) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 8'h15) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 8'h25) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 8'h45) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 8'h85) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 8'h19) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 8'h29) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 8'h49) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 8'h89) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 8'h31) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 8'h51) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 8'h91) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 8'h61) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 8'ha1) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 8'hc1) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 8'he) ^ in[21];
|
||||
d_o[22] = (syndrome_o == 8'h16) ^ in[22];
|
||||
d_o[23] = (syndrome_o == 8'h26) ^ in[23];
|
||||
d_o[24] = (syndrome_o == 8'h46) ^ in[24];
|
||||
d_o[25] = (syndrome_o == 8'h86) ^ in[25];
|
||||
d_o[26] = (syndrome_o == 8'h1a) ^ in[26];
|
||||
d_o[27] = (syndrome_o == 8'h2a) ^ in[27];
|
||||
d_o[28] = (syndrome_o == 8'h4a) ^ in[28];
|
||||
d_o[29] = (syndrome_o == 8'h8a) ^ in[29];
|
||||
d_o[30] = (syndrome_o == 8'h32) ^ in[30];
|
||||
d_o[31] = (syndrome_o == 8'h52) ^ in[31];
|
||||
d_o[32] = (syndrome_o == 8'h92) ^ in[32];
|
||||
d_o[33] = (syndrome_o == 8'h62) ^ in[33];
|
||||
d_o[34] = (syndrome_o == 8'ha2) ^ in[34];
|
||||
d_o[35] = (syndrome_o == 8'hc2) ^ in[35];
|
||||
d_o[36] = (syndrome_o == 8'h1c) ^ in[36];
|
||||
d_o[37] = (syndrome_o == 8'h2c) ^ in[37];
|
||||
d_o[38] = (syndrome_o == 8'h4c) ^ in[38];
|
||||
d_o[39] = (syndrome_o == 8'h8c) ^ in[39];
|
||||
d_o[40] = (syndrome_o == 8'h34) ^ in[40];
|
||||
d_o[41] = (syndrome_o == 8'h54) ^ in[41];
|
||||
d_o[42] = (syndrome_o == 8'h94) ^ in[42];
|
||||
d_o[43] = (syndrome_o == 8'h64) ^ in[43];
|
||||
d_o[44] = (syndrome_o == 8'ha4) ^ in[44];
|
||||
d_o[45] = (syndrome_o == 8'hc4) ^ in[45];
|
||||
d_o[46] = (syndrome_o == 8'h38) ^ in[46];
|
||||
d_o[47] = (syndrome_o == 8'h58) ^ in[47];
|
||||
d_o[48] = (syndrome_o == 8'h98) ^ in[48];
|
||||
d_o[49] = (syndrome_o == 8'h68) ^ in[49];
|
||||
d_o[50] = (syndrome_o == 8'ha8) ^ in[50];
|
||||
d_o[51] = (syndrome_o == 8'hc8) ^ in[51];
|
||||
d_o[52] = (syndrome_o == 8'h70) ^ in[52];
|
||||
d_o[53] = (syndrome_o == 8'hb0) ^ in[53];
|
||||
d_o[54] = (syndrome_o == 8'hd0) ^ in[54];
|
||||
d_o[55] = (syndrome_o == 8'he0) ^ in[55];
|
||||
d_o[56] = (syndrome_o == 8'h9d) ^ in[56];
|
||||
d_o[57] = (syndrome_o == 8'hda) ^ in[57];
|
||||
d_o[58] = (syndrome_o == 8'hcb) ^ in[58];
|
||||
d_o[59] = (syndrome_o == 8'he5) ^ in[59];
|
||||
d_o[60] = (syndrome_o == 8'h37) ^ in[60];
|
||||
d_o[61] = (syndrome_o == 8'h6e) ^ in[61];
|
||||
d_o[62] = (syndrome_o == 8'hb6) ^ in[62];
|
||||
d_o[63] = (syndrome_o == 8'h79) ^ in[63];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
single_error = ^syndrome_o;
|
||||
err_o[0] = single_error;
|
||||
err_o[1] = ~single_error & (|syndrome_o);
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [21:0] prim_secded_hamming_22_16_enc (logic [15:0] in);
|
||||
logic [21:0] out;
|
||||
out = 22'(in);
|
||||
out[16] = ^(out & 22'h00AD5B);
|
||||
out[17] = ^(out & 22'h00366D);
|
||||
out[18] = ^(out & 22'h00C78E);
|
||||
out[19] = ^(out & 22'h0007F0);
|
||||
out[20] = ^(out & 22'h00F800);
|
||||
out[21] = ^(out & 22'h1FFFFF);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_hamming_22_16_t prim_secded_hamming_22_16_dec (logic [21:0] in);
|
||||
logic [15:0] d_o;
|
||||
logic [5:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_hamming_22_16_t dec;
|
||||
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 22'h01AD5B);
|
||||
syndrome_o[1] = ^(in & 22'h02366D);
|
||||
syndrome_o[2] = ^(in & 22'h04C78E);
|
||||
syndrome_o[3] = ^(in & 22'h0807F0);
|
||||
syndrome_o[4] = ^(in & 22'h10F800);
|
||||
syndrome_o[5] = ^(in & 22'h3FFFFF);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 6'h23) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 6'h25) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 6'h26) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 6'h27) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 6'h29) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 6'h2a) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 6'h2b) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 6'h2c) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 6'h2d) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 6'h2e) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 6'h2f) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 6'h31) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 6'h32) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 6'h33) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 6'h34) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 6'h35) ^ in[15];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
err_o[0] = syndrome_o[5];
|
||||
err_o[1] = |syndrome_o[4:0] & ~syndrome_o[5];
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [38:0] prim_secded_hamming_39_32_enc (logic [31:0] in);
|
||||
logic [38:0] out;
|
||||
out = 39'(in);
|
||||
out[32] = ^(out & 39'h0056AAAD5B);
|
||||
out[33] = ^(out & 39'h009B33366D);
|
||||
out[34] = ^(out & 39'h00E3C3C78E);
|
||||
out[35] = ^(out & 39'h0003FC07F0);
|
||||
out[36] = ^(out & 39'h0003FFF800);
|
||||
out[37] = ^(out & 39'h00FC000000);
|
||||
out[38] = ^(out & 39'h3FFFFFFFFF);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_hamming_39_32_t prim_secded_hamming_39_32_dec (logic [38:0] in);
|
||||
logic [31:0] d_o;
|
||||
logic [6:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_hamming_39_32_t dec;
|
||||
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 39'h0156AAAD5B);
|
||||
syndrome_o[1] = ^(in & 39'h029B33366D);
|
||||
syndrome_o[2] = ^(in & 39'h04E3C3C78E);
|
||||
syndrome_o[3] = ^(in & 39'h0803FC07F0);
|
||||
syndrome_o[4] = ^(in & 39'h1003FFF800);
|
||||
syndrome_o[5] = ^(in & 39'h20FC000000);
|
||||
syndrome_o[6] = ^(in & 39'h7FFFFFFFFF);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 7'h43) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 7'h45) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 7'h46) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 7'h47) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 7'h49) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 7'h4a) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 7'h4b) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 7'h4c) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 7'h4d) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 7'h4e) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 7'h4f) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 7'h51) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 7'h52) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 7'h53) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 7'h54) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 7'h55) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 7'h56) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 7'h57) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 7'h58) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 7'h59) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 7'h5a) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 7'h5b) ^ in[21];
|
||||
d_o[22] = (syndrome_o == 7'h5c) ^ in[22];
|
||||
d_o[23] = (syndrome_o == 7'h5d) ^ in[23];
|
||||
d_o[24] = (syndrome_o == 7'h5e) ^ in[24];
|
||||
d_o[25] = (syndrome_o == 7'h5f) ^ in[25];
|
||||
d_o[26] = (syndrome_o == 7'h61) ^ in[26];
|
||||
d_o[27] = (syndrome_o == 7'h62) ^ in[27];
|
||||
d_o[28] = (syndrome_o == 7'h63) ^ in[28];
|
||||
d_o[29] = (syndrome_o == 7'h64) ^ in[29];
|
||||
d_o[30] = (syndrome_o == 7'h65) ^ in[30];
|
||||
d_o[31] = (syndrome_o == 7'h66) ^ in[31];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
err_o[0] = syndrome_o[6];
|
||||
err_o[1] = |syndrome_o[5:0] & ~syndrome_o[6];
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
function automatic logic [71:0] prim_secded_hamming_72_64_enc (logic [63:0] in);
|
||||
logic [71:0] out;
|
||||
out = 72'(in);
|
||||
out[64] = ^(out & 72'h00AB55555556AAAD5B);
|
||||
out[65] = ^(out & 72'h00CD9999999B33366D);
|
||||
out[66] = ^(out & 72'h00F1E1E1E1E3C3C78E);
|
||||
out[67] = ^(out & 72'h0001FE01FE03FC07F0);
|
||||
out[68] = ^(out & 72'h0001FFFE0003FFF800);
|
||||
out[69] = ^(out & 72'h0001FFFFFFFC000000);
|
||||
out[70] = ^(out & 72'h00FE00000000000000);
|
||||
out[71] = ^(out & 72'h7FFFFFFFFFFFFFFFFF);
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic secded_hamming_72_64_t prim_secded_hamming_72_64_dec (logic [71:0] in);
|
||||
logic [63:0] d_o;
|
||||
logic [7:0] syndrome_o;
|
||||
logic [1:0] err_o;
|
||||
|
||||
secded_hamming_72_64_t dec;
|
||||
|
||||
|
||||
// Syndrome calculation
|
||||
syndrome_o[0] = ^(in & 72'h01AB55555556AAAD5B);
|
||||
syndrome_o[1] = ^(in & 72'h02CD9999999B33366D);
|
||||
syndrome_o[2] = ^(in & 72'h04F1E1E1E1E3C3C78E);
|
||||
syndrome_o[3] = ^(in & 72'h0801FE01FE03FC07F0);
|
||||
syndrome_o[4] = ^(in & 72'h1001FFFE0003FFF800);
|
||||
syndrome_o[5] = ^(in & 72'h2001FFFFFFFC000000);
|
||||
syndrome_o[6] = ^(in & 72'h40FE00000000000000);
|
||||
syndrome_o[7] = ^(in & 72'hFFFFFFFFFFFFFFFFFF);
|
||||
|
||||
// Corrected output calculation
|
||||
d_o[0] = (syndrome_o == 8'h83) ^ in[0];
|
||||
d_o[1] = (syndrome_o == 8'h85) ^ in[1];
|
||||
d_o[2] = (syndrome_o == 8'h86) ^ in[2];
|
||||
d_o[3] = (syndrome_o == 8'h87) ^ in[3];
|
||||
d_o[4] = (syndrome_o == 8'h89) ^ in[4];
|
||||
d_o[5] = (syndrome_o == 8'h8a) ^ in[5];
|
||||
d_o[6] = (syndrome_o == 8'h8b) ^ in[6];
|
||||
d_o[7] = (syndrome_o == 8'h8c) ^ in[7];
|
||||
d_o[8] = (syndrome_o == 8'h8d) ^ in[8];
|
||||
d_o[9] = (syndrome_o == 8'h8e) ^ in[9];
|
||||
d_o[10] = (syndrome_o == 8'h8f) ^ in[10];
|
||||
d_o[11] = (syndrome_o == 8'h91) ^ in[11];
|
||||
d_o[12] = (syndrome_o == 8'h92) ^ in[12];
|
||||
d_o[13] = (syndrome_o == 8'h93) ^ in[13];
|
||||
d_o[14] = (syndrome_o == 8'h94) ^ in[14];
|
||||
d_o[15] = (syndrome_o == 8'h95) ^ in[15];
|
||||
d_o[16] = (syndrome_o == 8'h96) ^ in[16];
|
||||
d_o[17] = (syndrome_o == 8'h97) ^ in[17];
|
||||
d_o[18] = (syndrome_o == 8'h98) ^ in[18];
|
||||
d_o[19] = (syndrome_o == 8'h99) ^ in[19];
|
||||
d_o[20] = (syndrome_o == 8'h9a) ^ in[20];
|
||||
d_o[21] = (syndrome_o == 8'h9b) ^ in[21];
|
||||
d_o[22] = (syndrome_o == 8'h9c) ^ in[22];
|
||||
d_o[23] = (syndrome_o == 8'h9d) ^ in[23];
|
||||
d_o[24] = (syndrome_o == 8'h9e) ^ in[24];
|
||||
d_o[25] = (syndrome_o == 8'h9f) ^ in[25];
|
||||
d_o[26] = (syndrome_o == 8'ha1) ^ in[26];
|
||||
d_o[27] = (syndrome_o == 8'ha2) ^ in[27];
|
||||
d_o[28] = (syndrome_o == 8'ha3) ^ in[28];
|
||||
d_o[29] = (syndrome_o == 8'ha4) ^ in[29];
|
||||
d_o[30] = (syndrome_o == 8'ha5) ^ in[30];
|
||||
d_o[31] = (syndrome_o == 8'ha6) ^ in[31];
|
||||
d_o[32] = (syndrome_o == 8'ha7) ^ in[32];
|
||||
d_o[33] = (syndrome_o == 8'ha8) ^ in[33];
|
||||
d_o[34] = (syndrome_o == 8'ha9) ^ in[34];
|
||||
d_o[35] = (syndrome_o == 8'haa) ^ in[35];
|
||||
d_o[36] = (syndrome_o == 8'hab) ^ in[36];
|
||||
d_o[37] = (syndrome_o == 8'hac) ^ in[37];
|
||||
d_o[38] = (syndrome_o == 8'had) ^ in[38];
|
||||
d_o[39] = (syndrome_o == 8'hae) ^ in[39];
|
||||
d_o[40] = (syndrome_o == 8'haf) ^ in[40];
|
||||
d_o[41] = (syndrome_o == 8'hb0) ^ in[41];
|
||||
d_o[42] = (syndrome_o == 8'hb1) ^ in[42];
|
||||
d_o[43] = (syndrome_o == 8'hb2) ^ in[43];
|
||||
d_o[44] = (syndrome_o == 8'hb3) ^ in[44];
|
||||
d_o[45] = (syndrome_o == 8'hb4) ^ in[45];
|
||||
d_o[46] = (syndrome_o == 8'hb5) ^ in[46];
|
||||
d_o[47] = (syndrome_o == 8'hb6) ^ in[47];
|
||||
d_o[48] = (syndrome_o == 8'hb7) ^ in[48];
|
||||
d_o[49] = (syndrome_o == 8'hb8) ^ in[49];
|
||||
d_o[50] = (syndrome_o == 8'hb9) ^ in[50];
|
||||
d_o[51] = (syndrome_o == 8'hba) ^ in[51];
|
||||
d_o[52] = (syndrome_o == 8'hbb) ^ in[52];
|
||||
d_o[53] = (syndrome_o == 8'hbc) ^ in[53];
|
||||
d_o[54] = (syndrome_o == 8'hbd) ^ in[54];
|
||||
d_o[55] = (syndrome_o == 8'hbe) ^ in[55];
|
||||
d_o[56] = (syndrome_o == 8'hbf) ^ in[56];
|
||||
d_o[57] = (syndrome_o == 8'hc1) ^ in[57];
|
||||
d_o[58] = (syndrome_o == 8'hc2) ^ in[58];
|
||||
d_o[59] = (syndrome_o == 8'hc3) ^ in[59];
|
||||
d_o[60] = (syndrome_o == 8'hc4) ^ in[60];
|
||||
d_o[61] = (syndrome_o == 8'hc5) ^ in[61];
|
||||
d_o[62] = (syndrome_o == 8'hc6) ^ in[62];
|
||||
d_o[63] = (syndrome_o == 8'hc7) ^ in[63];
|
||||
|
||||
// err_o calc. bit0: single error, bit1: double error
|
||||
err_o[0] = syndrome_o[7];
|
||||
err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7];
|
||||
|
||||
dec.data = d_o;
|
||||
dec.syndrome = syndrome_o;
|
||||
dec.err = err_o;
|
||||
return dec;
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
endpackage
|
|
@ -13,7 +13,11 @@
|
|||
* - A parameter `Width` giving the memory width (word size) in bit.
|
||||
* - A parameter `Depth` giving the memory depth in words.
|
||||
* - A parameter `MemInitFile` with a file path of a VMEM file to be loaded into
|
||||
* the memory if not empty.
|
||||
* the memory if not empty.
|
||||
*
|
||||
* Note this works with memories up to a maximum width of 312 bits. Should this maximum width be
|
||||
* increased all of the `simutil_set_mem` and `simutil_get_mem` call sites must be found (e.g. using
|
||||
* git grep) and adjusted appropriately.
|
||||
*/
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
@ -29,10 +33,10 @@
|
|||
// Returns 1 (true) for success, 0 (false) for errors.
|
||||
export "DPI-C" function simutil_set_mem;
|
||||
|
||||
function int simutil_set_mem(input int index, input bit [255:0] val);
|
||||
function int simutil_set_mem(input int index, input bit [311:0] val);
|
||||
|
||||
// Function will only work for memories <= 256 bits
|
||||
if (Width > 256) begin
|
||||
// Function will only work for memories <= 312 bits
|
||||
if (Width > 312) begin
|
||||
return 0;
|
||||
end
|
||||
|
||||
|
@ -47,10 +51,10 @@
|
|||
// Function for getting a specific element in |mem|
|
||||
export "DPI-C" function simutil_get_mem;
|
||||
|
||||
function int simutil_get_mem(input int index, output bit [255:0] val);
|
||||
function int simutil_get_mem(input int index, output bit [311:0] val);
|
||||
|
||||
// Function will only work for memories <= 256 bits
|
||||
if (Width > 256) begin
|
||||
// Function will only work for memories <= 312 bits
|
||||
if (Width > 312) begin
|
||||
return 0;
|
||||
end
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ filesets:
|
|||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:ram_1p_pkg
|
||||
- lowrisc:prim:util_memload
|
||||
files:
|
||||
- rtl/prim_generic_ram_1p.sv
|
||||
|
|
|
@ -9,6 +9,7 @@ filesets:
|
|||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:ram_2p_pkg
|
||||
- lowrisc:prim:util_memload
|
||||
files:
|
||||
- rtl/prim_generic_ram_2p.sv
|
||||
|
|
|
@ -9,6 +9,7 @@ filesets:
|
|||
files_rtl:
|
||||
depend:
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:prim:rom_pkg
|
||||
- lowrisc:prim:util_memload
|
||||
files:
|
||||
- rtl/prim_generic_rom.sv
|
||||
|
|
|
@ -151,6 +151,7 @@ module prim_generic_flash #(
|
|||
.addr_o(cfg_addr),
|
||||
.wdata_o(cfg_wdata),
|
||||
.wmask_o(),
|
||||
.intg_error_o(),
|
||||
.rdata_i(cfg_rdata),
|
||||
.rvalid_i(cfg_rvalid),
|
||||
.rerror_i('0)
|
||||
|
@ -166,7 +167,8 @@ module prim_generic_flash #(
|
|||
.addr_i(cfg_addr),
|
||||
.wdata_i(cfg_wdata),
|
||||
.wmask_i({32{1'b1}}),
|
||||
.rdata_o(cfg_rdata)
|
||||
.rdata_o(cfg_rdata),
|
||||
.cfg_i('0)
|
||||
);
|
||||
|
||||
lc_ctrl_pkg::lc_tx_t unused_bist_enable;
|
||||
|
|
|
@ -381,7 +381,8 @@ module prim_generic_flash_bank #(
|
|||
.addr_i (mem_addr),
|
||||
.wdata_i (mem_wdata[MemWidth-1:0]),
|
||||
.wmask_i ({MemWidth{1'b1}}),
|
||||
.rdata_o (rd_nom_data_main)
|
||||
.rdata_o (rd_nom_data_main),
|
||||
.cfg_i ('0)
|
||||
);
|
||||
|
||||
prim_ram_1p #(
|
||||
|
@ -395,7 +396,8 @@ module prim_generic_flash_bank #(
|
|||
.addr_i (mem_addr),
|
||||
.wdata_i (mem_wdata[MemWidth +: MetaDataWidth]),
|
||||
.wmask_i ({MetaDataWidth{1'b1}}),
|
||||
.rdata_o (rd_meta_data_main)
|
||||
.rdata_o (rd_meta_data_main),
|
||||
.cfg_i ('0)
|
||||
);
|
||||
|
||||
for (genvar info_type = 0; info_type < InfoTypes; info_type++) begin : gen_info_types
|
||||
|
@ -416,7 +418,8 @@ module prim_generic_flash_bank #(
|
|||
.addr_i (mem_addr[0 +: InfoAddrW]),
|
||||
.wdata_i (mem_wdata[MemWidth-1:0]),
|
||||
.wmask_i ({MemWidth{1'b1}}),
|
||||
.rdata_o (rd_nom_data_info[info_type])
|
||||
.rdata_o (rd_nom_data_info[info_type]),
|
||||
.cfg_i ('0)
|
||||
);
|
||||
|
||||
prim_ram_1p #(
|
||||
|
@ -430,7 +433,8 @@ module prim_generic_flash_bank #(
|
|||
.addr_i (mem_addr[0 +: InfoAddrW]),
|
||||
.wdata_i (mem_wdata[MemWidth +: MetaDataWidth]),
|
||||
.wmask_i ({MetaDataWidth{1'b1}}),
|
||||
.rdata_o (rd_meta_data_info[info_type])
|
||||
.rdata_o (rd_meta_data_info[info_type]),
|
||||
.cfg_i ('0)
|
||||
);
|
||||
end
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ module prim_generic_otp
|
|||
.addr_o ( tlul_addr ),
|
||||
.wdata_o ( tlul_wdata ),
|
||||
.wmask_o ( ),
|
||||
.intg_error_o( ),
|
||||
.rdata_i ( tlul_rdata_q ),
|
||||
.rvalid_i ( tlul_rvalid_q ),
|
||||
.rerror_i ( '0 )
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_generic_ram_1p #(
|
||||
module prim_generic_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
|
||||
|
@ -21,9 +21,13 @@ module prim_generic_ram_1p #(
|
|||
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.
|
||||
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
|
||||
);
|
||||
|
||||
logic unused_cfg;
|
||||
assign unused_cfg = ^cfg_i;
|
||||
|
||||
// Width of internal write mask. Note wmask_i input into the module is always assumed
|
||||
// to be the full bit mask
|
||||
localparam int MaskWidth = Width / DataBitsPerMask;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// This module is for simulation and small size SRAM.
|
||||
// Implementing ECC should be done inside wrapper not this model.
|
||||
`include "prim_assert.sv"
|
||||
module prim_generic_ram_2p #(
|
||||
module prim_generic_ram_2p import prim_ram_2p_pkg::*; #(
|
||||
parameter int Width = 32, // bit
|
||||
parameter int Depth = 128,
|
||||
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
|
||||
|
@ -30,8 +30,14 @@ module prim_generic_ram_2p #(
|
|||
input [Aw-1:0] b_addr_i,
|
||||
input [Width-1:0] b_wdata_i,
|
||||
input logic [Width-1:0] b_wmask_i,
|
||||
output logic [Width-1:0] b_rdata_o
|
||||
output logic [Width-1:0] b_rdata_o,
|
||||
|
||||
input ram_2p_cfg_t cfg_i
|
||||
);
|
||||
|
||||
logic unused_cfg;
|
||||
assign unused_cfg = ^cfg_i;
|
||||
|
||||
// Width of internal write mask. Note *_wmask_i input into the module is always assumed
|
||||
// to be the full bit mask.
|
||||
localparam int MaskWidth = Width / DataBitsPerMask;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
`include "prim_assert.sv"
|
||||
|
||||
module prim_generic_rom #(
|
||||
module prim_generic_rom import prim_rom_pkg::*; #(
|
||||
parameter int Width = 32,
|
||||
parameter int Depth = 2048, // 8kB default
|
||||
parameter MemInitFile = "", // VMEM file to initialize the memory with
|
||||
|
@ -14,9 +14,13 @@ module prim_generic_rom #(
|
|||
input logic clk_i,
|
||||
input logic req_i,
|
||||
input logic [Aw-1:0] addr_i,
|
||||
output logic [Width-1:0] rdata_o
|
||||
output logic [Width-1:0] rdata_o,
|
||||
input rom_cfg_t cfg_i
|
||||
);
|
||||
|
||||
logic unused_cfg;
|
||||
assign unused_cfg = ^cfg_i;
|
||||
|
||||
logic [Width-1:0] mem [Depth];
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
|
|
1
vendor/lowrisc_ip/lint/tools/dvsim/lint.mk
vendored
1
vendor/lowrisc_ip/lint/tools/dvsim/lint.mk
vendored
|
@ -2,6 +2,7 @@
|
|||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export SHELL := /bin/bash
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
all: build
|
||||
|
|
|
@ -13,3 +13,8 @@ lint_off -rule PINCONNECTEMPTY
|
|||
// This warning gives wrong results with blackboxed embedded modules, see
|
||||
// https://github.com/verilator/verilator/issues/2430
|
||||
lint_off -rule DECLFILENAME -file "*" -match "Filename '*' does not match NOTFOUNDMODULE name:*"
|
||||
|
||||
// Don't generate lint errors for unused parameters in packages. The point is
|
||||
// that a user of a package might not want to use all of the parameters it
|
||||
// defines.
|
||||
lint_off -rule UNUSED -file "*_pkg.sv" -match "*Parameter is not used*"
|
||||
|
|
808
vendor/lowrisc_ip/util/dvsim/Deploy.py
vendored
808
vendor/lowrisc_ip/util/dvsim/Deploy.py
vendored
File diff suppressed because it is too large
Load diff
2
vendor/lowrisc_ip/util/dvsim/FlowCfg.py
vendored
2
vendor/lowrisc_ip/util/dvsim/FlowCfg.py
vendored
|
@ -73,9 +73,7 @@ class FlowCfg():
|
|||
self.deploy = []
|
||||
|
||||
# Timestamp
|
||||
self.ts_format_long = args.ts_format_long
|
||||
self.timestamp_long = args.timestamp_long
|
||||
self.ts_format = args.ts_format
|
||||
self.timestamp = args.timestamp
|
||||
|
||||
# Results
|
||||
|
|
232
vendor/lowrisc_ip/util/dvsim/Launcher.py
vendored
Normal file
232
vendor/lowrisc_ip/util/dvsim/Launcher.py
vendored
Normal file
|
@ -0,0 +1,232 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging as log
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from utils import VERBOSE, clean_odirs, rm_path
|
||||
|
||||
|
||||
class LauncherError(Exception):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
|
||||
class Launcher:
|
||||
"""
|
||||
Abstraction for launching and maintaining a job.
|
||||
|
||||
An abstract class that provides methods to prepare a job's environment,
|
||||
launch the job, poll for its completion and finally do some cleanup
|
||||
activities. This class is not meant to be instantiated directly. Each
|
||||
launcher object holds an instance of the deploy object.
|
||||
"""
|
||||
|
||||
# If a history of previous invocations is to be maintained, then keep no
|
||||
# more than this many directories.
|
||||
max_odirs = 5
|
||||
|
||||
def __str__(self):
|
||||
return self.deploy.full_name + ":launcher"
|
||||
|
||||
def __init__(self, deploy):
|
||||
# Store the deploy object handle.
|
||||
self.deploy = deploy
|
||||
|
||||
# Return status of the process running the job.
|
||||
self.exit_code = None
|
||||
|
||||
# Flag to indicate whether to 'overwrite' if odir already exists,
|
||||
# or to backup the existing one and create a new one.
|
||||
# For builds, we want to overwrite existing to leverage the tools'
|
||||
# incremental / partition compile features. For runs, we may want to
|
||||
# create a new one.
|
||||
self.renew_odir = False
|
||||
|
||||
# Construct failure message if the test fails.
|
||||
self.fail_msg = "\n**{!r}:** {!r}<br>\n".format(
|
||||
self.deploy.target.upper(), self.deploy.qual_name)
|
||||
self.fail_msg += "**LOG:** {}<br>\n".format(self.deploy.get_log_path())
|
||||
|
||||
def _make_odir(self):
|
||||
"""Create the output directory."""
|
||||
|
||||
# If renew_odir flag is True - then move it.
|
||||
if self.renew_odir:
|
||||
clean_odirs(odir=self.deploy.odir, max_odirs=self.max_odirs)
|
||||
os.makedirs(self.deploy.odir, exist_ok=True)
|
||||
|
||||
def _dump_env_vars(self, exports):
|
||||
"""Write env vars to a file for ease of debug.
|
||||
|
||||
Each extended class computes the list of exports and invokes this
|
||||
method right before launching the job.
|
||||
"""
|
||||
|
||||
with open(self.deploy.odir + "/env_vars",
|
||||
"w",
|
||||
encoding="UTF-8",
|
||||
errors="surrogateescape") as f:
|
||||
for var in sorted(exports.keys()):
|
||||
f.write("{}={}\n".format(var, exports[var]))
|
||||
|
||||
def _pre_launch(self):
|
||||
"""Do pre-launch activities.
|
||||
|
||||
Examples include such as preparing the job's environment, clearing
|
||||
old runs, creating the output directory, dumping all env variables
|
||||
etc. This method is already invoked by launch() as the first step.
|
||||
"""
|
||||
|
||||
self.deploy.pre_launch()
|
||||
self._make_odir()
|
||||
|
||||
def _do_launch(self):
|
||||
"""Launch the job."""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def launch(self):
|
||||
"""Launch the job."""
|
||||
|
||||
self._pre_launch()
|
||||
self._do_launch()
|
||||
|
||||
def _post_finish(self, status):
|
||||
"""Do post-completion activities, such as preparing the results.
|
||||
|
||||
Must be invoked by poll().
|
||||
"""
|
||||
|
||||
assert status in ['P', 'F', 'K']
|
||||
if status in ['P', 'F']:
|
||||
self._link_odir(status)
|
||||
self.deploy.post_finish(status)
|
||||
log.debug("Item %s has completed execution: %s", self, status)
|
||||
|
||||
def poll(self):
|
||||
"""Poll the launched job for completion.
|
||||
|
||||
Invokes _has_passed() and _post_finish() when the job completes.
|
||||
"""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def kill(self):
|
||||
"""Terminate the job."""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def _has_passed(self):
|
||||
"""Determine the outcome of the job (P/F if it ran to completion).
|
||||
|
||||
Return True if the job passed, False otherwise. This is called by
|
||||
poll() just after the job finishes.
|
||||
"""
|
||||
def log_fail_msg(msg):
|
||||
"""Logs the fail msg to the final report."""
|
||||
|
||||
self.fail_msg += msg
|
||||
log.log(VERBOSE, msg)
|
||||
|
||||
def _find_patterns(patterns, line):
|
||||
"""Helper function that returns the pattern if any of the given
|
||||
patterns is found, else None."""
|
||||
|
||||
assert patterns
|
||||
for pattern in patterns:
|
||||
match = re.search(r"{}".format(pattern), line)
|
||||
if match:
|
||||
return pattern
|
||||
return None
|
||||
|
||||
def _get_n_lines(pos, num):
|
||||
"Helper function that returns next N lines starting at pos index."
|
||||
|
||||
return ''.join(lines[pos:pos + num - 1]).strip()
|
||||
|
||||
if self.deploy.dry_run:
|
||||
return True
|
||||
|
||||
# Only one fail pattern needs to be seen.
|
||||
failed = False
|
||||
chk_failed = bool(self.deploy.fail_patterns)
|
||||
|
||||
# All pass patterns need to be seen, so we replicate the list and remove
|
||||
# patterns as we encounter them.
|
||||
pass_patterns = self.deploy.pass_patterns.copy()
|
||||
chk_passed = bool(pass_patterns) and (self.exit_code == 0)
|
||||
|
||||
try:
|
||||
with open(self.deploy.get_log_path(), "r", encoding="UTF-8") as f:
|
||||
lines = f.readlines()
|
||||
except OSError as e:
|
||||
log_fail_msg("Error opening file {}:\n{}".format(
|
||||
self.deploy.get_log_path(), e))
|
||||
return False
|
||||
|
||||
if chk_failed or chk_passed:
|
||||
for cnt, line in enumerate(lines):
|
||||
if chk_failed:
|
||||
if _find_patterns(self.deploy.fail_patterns,
|
||||
line) is not None:
|
||||
# Print 4 additional lines to help debug more easily.
|
||||
log_fail_msg("```\n{}\n```\n".format(
|
||||
_get_n_lines(cnt, 5)))
|
||||
failed = True
|
||||
chk_failed = False
|
||||
chk_passed = False
|
||||
|
||||
if chk_passed:
|
||||
pattern = _find_patterns(pass_patterns, line)
|
||||
if pattern is not None:
|
||||
pass_patterns.remove(pattern)
|
||||
chk_passed = bool(pass_patterns)
|
||||
|
||||
# If failed, then nothing else to do. Just return.
|
||||
if failed:
|
||||
return False
|
||||
|
||||
# If no fail patterns were seen, but the job returned with non-zero
|
||||
# exit code for whatever reason, then show the last 10 lines of the log
|
||||
# as the failure message, which might help with the debug.
|
||||
if self.exit_code != 0:
|
||||
msg = ''.join(lines[-10:]).strip()
|
||||
log_fail_msg("Job returned non-zero exit code. "
|
||||
"Last 10 lines:\n```\n{}\n```\n".format(msg))
|
||||
return False
|
||||
|
||||
# Ensure all pass patterns were seen.
|
||||
if chk_passed:
|
||||
msg = ''.join(lines[-10:]).strip()
|
||||
log_fail_msg("One or more pass patterns not found:\n{}\n"
|
||||
"Last 10 lines:\n```\n{}\n```\n".format(
|
||||
pass_patterns, msg))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _link_odir(self, status):
|
||||
"""Soft-links the job's directory based on job's status.
|
||||
|
||||
The dispatched, passed and failed directories in the scratch area
|
||||
provide a quick way to get to the job that was executed.
|
||||
"""
|
||||
|
||||
dest = Path(self.deploy.sim_cfg.links[status], self.deploy.qual_name)
|
||||
|
||||
# If dest exists, then atomically remove it and link the odir again.
|
||||
while True:
|
||||
try:
|
||||
os.symlink(self.deploy.odir, dest)
|
||||
break
|
||||
except FileExistsError:
|
||||
rm_path(dest)
|
||||
|
||||
# Delete the symlink from dispatched directory if it exists.
|
||||
if status != "D":
|
||||
old = Path(self.deploy.sim_cfg.links['D'], self.deploy.qual_name)
|
||||
rm_path(old)
|
139
vendor/lowrisc_ip/util/dvsim/LocalLauncher.py
vendored
Normal file
139
vendor/lowrisc_ip/util/dvsim/LocalLauncher.py
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
# Copyright lowRISC contributors.
|
||||
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging as log
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from Launcher import Launcher, LauncherError
|
||||
|
||||
|
||||
class LocalLauncher(Launcher):
|
||||
"""
|
||||
Implementation of Launcher to launch jobs in the user's local workstation.
|
||||
"""
|
||||
|
||||
# Misc common LocalLauncher settings.
|
||||
max_odirs = 5
|
||||
|
||||
def __init__(self, deploy):
|
||||
'''Initialize common class members.'''
|
||||
|
||||
super().__init__(deploy)
|
||||
|
||||
# Popen object when launching the job.
|
||||
self.process = None
|
||||
|
||||
def _do_launch(self):
|
||||
# Update the shell's env vars with self.exports. Values in exports must
|
||||
# replace the values in the shell's env vars if the keys match.
|
||||
exports = os.environ.copy()
|
||||
if self.deploy.exports:
|
||||
exports.update(self.deploy.exports)
|
||||
|
||||
# Clear the magic MAKEFLAGS variable from exports if necessary. This
|
||||
# variable is used by recursive Make calls to pass variables from one
|
||||
# level to the next. Here, self.cmd is a call to Make but it's
|
||||
# logically a top-level invocation: we don't want to pollute the flow's
|
||||
# Makefile with Make variables from any wrapper that called dvsim.
|
||||
if 'MAKEFLAGS' in exports:
|
||||
del exports['MAKEFLAGS']
|
||||
|
||||
self._dump_env_vars(exports)
|
||||
|
||||
args = shlex.split(self.deploy.cmd)
|
||||
try:
|
||||
f = open(self.deploy.get_log_path(),
|
||||
"w",
|
||||
encoding="UTF-8",
|
||||
errors="surrogateescape")
|
||||
f.write("[Executing]:\n{}\n\n".format(self.deploy.cmd))
|
||||
f.flush()
|
||||
self.process = subprocess.Popen(args,
|
||||
bufsize=4096,
|
||||
universal_newlines=True,
|
||||
stdout=f,
|
||||
stderr=f,
|
||||
env=exports)
|
||||
except subprocess.SubprocessError as e:
|
||||
raise LauncherError('IO Error: {}\nSee {}'.format(
|
||||
e, self.deploy.get_log_path()))
|
||||
finally:
|
||||
self._close_process()
|
||||
|
||||
self._link_odir("D")
|
||||
|
||||
def poll(self):
|
||||
'''Check status of the running process
|
||||
|
||||
This returns 'D', 'P' or 'F'. If 'D', the job is still running. If 'P',
|
||||
the job finished successfully. If 'F', the job finished with an error.
|
||||
|
||||
This function must only be called after running self.dispatch_cmd() and
|
||||
must not be called again once it has returned 'P' or 'F'.
|
||||
'''
|
||||
|
||||
assert self.process is not None
|
||||
if self.process.poll() is None:
|
||||
return 'D'
|
||||
|
||||
self.exit_code = self.process.returncode
|
||||
status = 'P' if self._has_passed() else 'F'
|
||||
|
||||
self._post_finish(status)
|
||||
return status
|
||||
|
||||
def _post_finish(self, status):
|
||||
super()._post_finish(status)
|
||||
self._close_process()
|
||||
self.process = None
|
||||
|
||||
def kill(self):
|
||||
'''Kill the running process.
|
||||
|
||||
This must be called between dispatching and reaping the process (the
|
||||
same window as poll()).
|
||||
|
||||
'''
|
||||
assert self.process is not None
|
||||
self.kill_remote_job()
|
||||
|
||||
# Try to kill the running process. Send SIGTERM first, wait a bit,
|
||||
# and then send SIGKILL if it didn't work.
|
||||
self.process.terminate()
|
||||
try:
|
||||
self.process.wait(timeout=2)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.process.kill()
|
||||
|
||||
self._post_finish('K')
|
||||
|
||||
def _close_process(self):
|
||||
'''Close the file descriptors associated with the process.'''
|
||||
|
||||
assert self.process
|
||||
if self.process.stdout:
|
||||
self.process.stdout.close()
|
||||
|
||||
def kill_remote_job(self):
|
||||
'''
|
||||
If jobs are run in remote server, need to use another command to kill them.
|
||||
'''
|
||||
# TODO: Currently only support lsf, may need to add support for GCP later.
|
||||
|
||||
# If use lsf, kill it by job ID.
|
||||
if re.match("^bsub", self.deploy.sim_cfg.job_prefix):
|
||||
# get job id from below string
|
||||
# Job <xxxxxx> is submitted to default queue
|
||||
grep_cmd = "grep -m 1 -E \'" + "^Job <" + "\' " + \
|
||||
self.deploy.get_log_path()
|
||||
(status, rslt) = subprocess.getstatusoutput(grep_cmd)
|
||||
if rslt != "":
|
||||
job_id = rslt.split('Job <')[1].split('>')[0]
|
||||
try:
|
||||
subprocess.run(["bkill", job_id], check=True)
|
||||
except Exception as e:
|
||||
log.error("%s: Failed to run bkill\n", e)
|
25
vendor/lowrisc_ip/util/dvsim/Scheduler.py
vendored
25
vendor/lowrisc_ip/util/dvsim/Scheduler.py
vendored
|
@ -7,7 +7,7 @@ import threading
|
|||
from collections import OrderedDict
|
||||
from signal import SIGINT, signal
|
||||
|
||||
from Deploy import DeployError
|
||||
from Launcher import LauncherError
|
||||
from Timer import Timer
|
||||
from utils import VERBOSE
|
||||
|
||||
|
@ -42,32 +42,31 @@ class TargetScheduler:
|
|||
def _kill_item(self, item):
|
||||
'''Kill a running item'''
|
||||
self._running.remove(item)
|
||||
item.kill()
|
||||
item.launcher.kill()
|
||||
self._killed.add(item)
|
||||
self.item_to_status[item] = 'K'
|
||||
|
||||
def _poll(self, hms):
|
||||
'''Check for running items that have finished
|
||||
'''Check for running items that have finished.
|
||||
|
||||
Returns True if something changed.
|
||||
|
||||
'''
|
||||
to_pass = []
|
||||
to_fail = []
|
||||
|
||||
for item in self._running:
|
||||
status = item.poll()
|
||||
status = item.launcher.poll()
|
||||
assert status in ['D', 'P', 'F']
|
||||
if status == 'D':
|
||||
# Still running
|
||||
continue
|
||||
elif status == 'P':
|
||||
log.log(VERBOSE, "[%s]: [%s]: [status] [%s: P]", hms,
|
||||
item.target, item.identifier)
|
||||
item.target, item.full_name)
|
||||
to_pass.append(item)
|
||||
else:
|
||||
log.error("[%s]: [%s]: [status] [%s: F]", hms, item.target,
|
||||
item.identifier)
|
||||
item.full_name)
|
||||
to_fail.append(item)
|
||||
|
||||
for item in to_pass:
|
||||
|
@ -85,7 +84,6 @@ class TargetScheduler:
|
|||
'''Dispatch some queued items if possible.
|
||||
|
||||
See run() for the format of old_results.
|
||||
|
||||
'''
|
||||
num_slots = min(Scheduler.slot_limit,
|
||||
Scheduler.max_parallel - len(self._running),
|
||||
|
@ -131,14 +129,14 @@ class TargetScheduler:
|
|||
return
|
||||
|
||||
log.log(VERBOSE, "[%s]: [%s]: [dispatch]:\n%s", hms, self.name,
|
||||
", ".join(item.identifier for item in to_dispatch))
|
||||
", ".join(item.full_name for item in to_dispatch))
|
||||
|
||||
for item in to_dispatch:
|
||||
self._running.add(item)
|
||||
self.item_to_status[item] = 'D'
|
||||
try:
|
||||
item.dispatch_cmd()
|
||||
except DeployError as err:
|
||||
item.launcher.launch()
|
||||
except LauncherError as err:
|
||||
log.error('{}'.format(err))
|
||||
self._kill_item(item)
|
||||
|
||||
|
@ -167,7 +165,6 @@ class TargetScheduler:
|
|||
|
||||
If print_status or we've reached a time interval then print current
|
||||
status for those jobs that weren't known to be finished already.
|
||||
|
||||
'''
|
||||
if timer.check_time():
|
||||
print_status = True
|
||||
|
@ -195,10 +192,7 @@ class TargetScheduler:
|
|||
statuses. Every job that appears as a dependency will be in this list
|
||||
(because it ran as part of a previous target).
|
||||
|
||||
is_first_tgt is true if this is the first target to run.
|
||||
|
||||
Returns the results from this target (in the same format).
|
||||
|
||||
'''
|
||||
# Catch one SIGINT and tell the runner to quit. On a second, die.
|
||||
stop_now = threading.Event()
|
||||
|
@ -271,7 +265,6 @@ class Scheduler:
|
|||
'''Run all items
|
||||
|
||||
Returns a map from item to status.
|
||||
|
||||
'''
|
||||
timer = Timer()
|
||||
|
||||
|
|
2
vendor/lowrisc_ip/util/dvsim/SimCfg.py
vendored
2
vendor/lowrisc_ip/util/dvsim/SimCfg.py
vendored
|
@ -62,7 +62,7 @@ class Results:
|
|||
'''Recursively add a single item to the table of results'''
|
||||
status = results[item]
|
||||
if status == "F":
|
||||
self.fail_msgs.append(item.fail_msg)
|
||||
self.fail_msgs.append(item.launcher.fail_msg)
|
||||
|
||||
# Runs get added to the table directly
|
||||
if item.target == "run":
|
||||
|
|
52
vendor/lowrisc_ip/util/dvsim/dvsim.py
vendored
52
vendor/lowrisc_ip/util/dvsim/dvsim.py
vendored
|
@ -30,10 +30,12 @@ import textwrap
|
|||
from pathlib import Path
|
||||
|
||||
from CfgFactory import make_cfg
|
||||
from Deploy import Deploy, RunTest
|
||||
from Deploy import RunTest
|
||||
from Launcher import Launcher
|
||||
from Scheduler import Scheduler
|
||||
from Timer import Timer
|
||||
from utils import VERBOSE, rm_path, run_cmd_with_timeout
|
||||
from utils import (TS_FORMAT, TS_FORMAT_LONG, VERBOSE, rm_path,
|
||||
run_cmd_with_timeout)
|
||||
|
||||
# TODO: add dvsim_cfg.hjson to retrieve this info
|
||||
version = 0.1
|
||||
|
@ -162,13 +164,14 @@ def get_proj_root():
|
|||
def resolve_proj_root(args):
|
||||
'''Update proj_root based on how DVSim is invoked.
|
||||
|
||||
If --remote env var is set, a location in the scratch area is chosen as the
|
||||
If --remote switch is set, a location in the scratch area is chosen as the
|
||||
new proj_root. The entire repo is copied over to this location. Else, the
|
||||
proj_root is discovered using get_proj_root() method, unless the user
|
||||
overrides it on the command line.
|
||||
|
||||
This function returns the updated proj_root src and destination path. If
|
||||
--remote env var is not set, the destination path is identical to the src path.
|
||||
--remote switch is not set, the destination path is identical to the src
|
||||
path. Likewise, if --dry-run is set.
|
||||
'''
|
||||
proj_root_src = args.proj_root or get_proj_root()
|
||||
|
||||
|
@ -176,19 +179,19 @@ def resolve_proj_root(args):
|
|||
# then the repo needs to be copied over to the scratch area
|
||||
# accessible to those machines.
|
||||
# If --purge arg is set, then purge the repo_top that was copied before.
|
||||
if args.remote:
|
||||
if args.remote and not args.dry_run:
|
||||
proj_root_dest = os.path.join(args.scratch_root, args.branch,
|
||||
"repo_top")
|
||||
if args.purge:
|
||||
rm_path(proj_root_dest)
|
||||
copy_repo(proj_root_src, proj_root_dest, args.dry_run)
|
||||
copy_repo(proj_root_src, proj_root_dest)
|
||||
else:
|
||||
proj_root_dest = proj_root_src
|
||||
|
||||
return proj_root_src, proj_root_dest
|
||||
|
||||
|
||||
def copy_repo(src, dest, dry_run):
|
||||
def copy_repo(src, dest):
|
||||
'''Copy over the repo to a new location.
|
||||
|
||||
The repo is copied over from src to dest area. It tentatively uses the
|
||||
|
@ -217,17 +220,17 @@ def copy_repo(src, dest, dry_run):
|
|||
|
||||
log.info("[copy_repo] [dest]: %s", dest)
|
||||
log.log(VERBOSE, "[copy_repo] [cmd]: \n%s", ' '.join(cmd))
|
||||
if not dry_run:
|
||||
# Make sure the dest exists first.
|
||||
os.makedirs(dest, exist_ok=True)
|
||||
try:
|
||||
subprocess.run(cmd,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as e:
|
||||
log.error("Failed to copy over %s to %s: %s", src, dest,
|
||||
e.stderr.decode("utf-8").strip())
|
||||
|
||||
# Make sure the dest exists first.
|
||||
os.makedirs(dest, exist_ok=True)
|
||||
try:
|
||||
subprocess.run(cmd,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as e:
|
||||
log.error("Failed to copy over %s to %s: %s", src, dest,
|
||||
e.stderr.decode("utf-8").strip())
|
||||
log.info("Done.")
|
||||
|
||||
|
||||
|
@ -620,16 +623,9 @@ def main():
|
|||
args.cfg = os.path.join(proj_root, cfg_path)
|
||||
|
||||
# Add timestamp to args that all downstream objects can use.
|
||||
# Static variables - indicate timestamp.
|
||||
ts_format_long = "%A %B %d %Y %I:%M:%S%p UTC"
|
||||
ts_format = "%a.%m.%d.%y__%I.%M.%S%p"
|
||||
curr_ts = datetime.datetime.utcnow()
|
||||
timestamp_long = curr_ts.strftime(ts_format_long)
|
||||
timestamp = curr_ts.strftime(ts_format)
|
||||
setattr(args, "ts_format_long", ts_format_long)
|
||||
setattr(args, "ts_format", ts_format)
|
||||
setattr(args, "timestamp_long", timestamp_long)
|
||||
setattr(args, "timestamp", timestamp)
|
||||
setattr(args, "timestamp_long", curr_ts.strftime(TS_FORMAT_LONG))
|
||||
setattr(args, "timestamp", curr_ts.strftime(TS_FORMAT))
|
||||
|
||||
# Register the seeds from command line with RunTest class.
|
||||
RunTest.seeds = args.seeds
|
||||
|
@ -641,7 +637,7 @@ def main():
|
|||
# Register the common deploy settings.
|
||||
Timer.print_interval = args.print_interval
|
||||
Scheduler.max_parallel = args.max_parallel
|
||||
Deploy.max_odirs = args.max_odirs
|
||||
Launcher.max_odirs = args.max_odirs
|
||||
|
||||
# Build infrastructure from hjson file and create the list of items to
|
||||
# be deployed.
|
||||
|
|
39
vendor/lowrisc_ip/util/dvsim/utils.py
vendored
39
vendor/lowrisc_ip/util/dvsim/utils.py
vendored
|
@ -14,6 +14,8 @@ import subprocess
|
|||
import sys
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import hjson
|
||||
import mistletoe
|
||||
|
@ -22,6 +24,12 @@ from premailer import transform
|
|||
# For verbose logging
|
||||
VERBOSE = 15
|
||||
|
||||
# Timestamp format when creating directory backups.
|
||||
TS_FORMAT = "%y.%m.%d_%H.%M.%S"
|
||||
|
||||
# Timestamp format when generating reports.
|
||||
TS_FORMAT_LONG = "%A %B %d %Y %H:%M:%S UTC"
|
||||
|
||||
|
||||
# Run a command and get the result. Exit with error if the command did not
|
||||
# succeed. This is a simpler version of the run_cmd function below.
|
||||
|
@ -541,3 +549,34 @@ def rm_path(path, ignore_error=False):
|
|||
log.error("Failed to remove {}:\n{}.".format(path, e))
|
||||
if not ignore_error:
|
||||
raise e
|
||||
|
||||
|
||||
def clean_odirs(odir, max_odirs, ts_format=TS_FORMAT):
|
||||
"""Clean previous output directories.
|
||||
|
||||
When running jobs, we may want to maintain a limited history of
|
||||
previous invocations. This method finds and deletes the output
|
||||
directories at the base of input arg 'odir' with the oldest timestamps,
|
||||
if that limit is reached. It returns a list of directories that
|
||||
remain after deletion.
|
||||
"""
|
||||
|
||||
if os.path.exists(odir):
|
||||
# If output directory exists, back it up.
|
||||
ts = datetime.fromtimestamp(os.stat(odir).st_ctime).strftime(ts_format)
|
||||
shutil.move(odir, "{}_{}".format(odir, ts))
|
||||
|
||||
# Get list of past output directories sorted by creation time.
|
||||
pdir = Path(odir).resolve().parent
|
||||
if not pdir.exists():
|
||||
return []
|
||||
|
||||
dirs = sorted([old for old in pdir.iterdir() if old.is_dir()],
|
||||
key=os.path.getctime,
|
||||
reverse=True)
|
||||
|
||||
for old in dirs[max_odirs - 1:]:
|
||||
if os.path.exists(old):
|
||||
shutil.rmtree(old, ignore_errors=True)
|
||||
|
||||
return dirs[0:max_odirs - 2]
|
||||
|
|
1
vendor/lowrisc_ip/util/uvmdvgen/gen_agent.py
vendored
1
vendor/lowrisc_ip/util/uvmdvgen/gen_agent.py
vendored
|
@ -16,6 +16,7 @@ def gen_agent(name, has_separate_host_device_driver, root_dir, vendor):
|
|||
agent_dir = root_dir + "/" + name + "_agent"
|
||||
|
||||
# yapf: disable
|
||||
# flake8: noqa
|
||||
# 4-tuple - path, ip name, class name, file ext
|
||||
agent_srcs = [(agent_dir, name + '_', 'if', '.sv'),
|
||||
(agent_dir, name + '_', 'item', '.sv'),
|
||||
|
|
3
vendor/lowrisc_ip/util/uvmdvgen/gen_env.py
vendored
3
vendor/lowrisc_ip/util/uvmdvgen/gen_env.py
vendored
|
@ -15,6 +15,7 @@ from uvmdvgen import VENDOR_DEFAULT
|
|||
def gen_env(name, is_cip, has_ral, has_interrupts, has_alerts, has_edn,
|
||||
env_agents, root_dir, vendor):
|
||||
# yapf: disable
|
||||
# flake8: noqa
|
||||
# 4-tuple - sub-path, ip name, class name, file ext
|
||||
env_srcs = [('dv/env', name + '_', 'env_cfg', '.sv'),
|
||||
('dv/env', name + '_', 'env_cov', '.sv'),
|
||||
|
@ -35,7 +36,7 @@ def gen_env(name, is_cip, has_ral, has_interrupts, has_alerts, has_edn,
|
|||
('dv/tests', name + '_', 'test', '.core'),
|
||||
('dv/cov', '', '', ''),
|
||||
('dv', name + '_', 'sim_cfg', '.hjson'),
|
||||
('doc/dv_plan', '', 'index', '.md'),
|
||||
('doc/dv', '', 'index', '.md'),
|
||||
('doc', '', 'checklist', '.md'),
|
||||
('data', name + '_', 'testplan', '.hjson'),
|
||||
('dv', name + '_', 'sim', '.core')]
|
||||
|
|
10
vendor/lowrisc_ip/util/uvmdvgen/index.md.tpl
vendored
10
vendor/lowrisc_ip/util/uvmdvgen/index.md.tpl
vendored
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
title: "${name.upper()} DV Plan"
|
||||
title: "${name.upper()} DV document"
|
||||
---
|
||||
|
||||
<!-- Copy this file to hw/ip/${name}/doc/${name}_dv_plan.md and make changes as needed.
|
||||
<!-- Copy this file to hw/ip/${name}/doc/dv/index.md and make changes as needed.
|
||||
For convenience '${name}' in the document can be searched and replaced easily with the
|
||||
desired IP (with case sensitivity!). Also, use the testbench block diagram
|
||||
located at OpenTitan team drive / 'design verification'
|
||||
as a starting point and modify it to reflect your ${name} testbench and save it
|
||||
to hw/ip/${name}/doc/tb.svg. It should get linked and rendered under the block
|
||||
to hw/ip/${name}/doc/dv/tb.svg. It should get linked and rendered under the block
|
||||
diagram section below. Please update / modify / remove sections below as
|
||||
applicable. Once done, remove this comment before making a PR. -->
|
||||
|
||||
${'##'} Goals
|
||||
* **DV**
|
||||
* Verify all ${name.upper()} IP features by running dynamic simulations with a SV/UVM based testbench
|
||||
* Develop and run all tests based on the [testplan](#testplan) below towards closing code and functional coverage on the IP and all of its sub-modules
|
||||
* Develop and run all tests based on the [DV plan](#dv-plan) below towards closing code and functional coverage on the IP and all of its sub-modules
|
||||
* **FPV**
|
||||
* Verify TileLink device protocol compliance with an SVA based testbench
|
||||
|
||||
|
@ -122,6 +122,6 @@ Here's how to run a smoke test:
|
|||
$ $REPO_TOP/util/dvsim/dvsim.py $REPO_TOP/hw/ip/${name}/dv/${name}_sim_cfg.hjson -i ${name}_smoke
|
||||
```
|
||||
|
||||
${'##'} Testplan
|
||||
${'##'} DV plan
|
||||
<!-- TODO: uncomment the line below after adding the testplan -->
|
||||
{{</* testplan "hw/ip/${name}/data/${name}_testplan.hjson" */>}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue