Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
ca950b43a0e9ef5013b8e2e5de765bc34fb59b74

Two updates to the Ibex code were required:
* Adjust the prim_secded port names to match the changes in
  OpenTitan.
* Replace `has_ral` in `ibex_icache_env_cfg.sv` and
  `ibex_icache_base_test.sv` with its newer equivalent, matching
  https://github.com/lowRISC/opentitan/pull/5932 and the additional
  updates in https://github.com/lowRISC/opentitan/pull/5951.

Upstream changes include:
* [prim_secded] Use _i/_o suffix for port names (Philipp Wagner)
* [tl,dv] Allow bits to be set in responses regardless of mask (Rupert
  Swarbrick)
* [push_pull agent] Driver code refactor (Srikrishna Iyer)
* [dv/dvsim] Group failures per test in buckets (Guillermo Maturana)
* [dv/uvmdvgen] Flag error for paths in block name (Guillermo
  Maturana)
* [prim_fifo_async] Style fixes (Philipp Wagner)
* Remove non-ASCII characters from SV code and meson.build (Rupert
  Swarbrick)
* [dv/spi_device] Fix spi_device_csr_wr_with_rand_reset timeout issue
  (Cindy Chen)
* [otp] Update to match latest foundry wrapper (Timothy Chen)
* [flash] update to match latest foundry wrapper (Timothy Chen)
* [top] Latest ast integration (Timothy Chen)
* [lint] Strengthen Verible lint check to 100-character lines (Rupert
  Swarbrick)
* [ prim ] Suppress unneeded assertion when clearing prim_packer_fifo
  (Martin Lueker-Boden)
* [dv/otp_ctrl] Add coverage exclusions (Cindy Chen)
* [dv/dvsim] Add "^Error:" as a run fail pattern. (Guillermo Maturana)
* [dvsim] Fix column bug in DV summary report (Srikrishna Iyer)
* [dvsim] Fix testplan test counts (Srikrishna Iyer)
* [dvsim] Fix lowRISC/opentitan#6061 (Srikrishna Iyer)
* [prim_clock_div] Update waiver (Michael Schaffner)
* [fpv] dvsim script error (Cindy Chen)
* [prim_otp] Update interface (Michael Schaffner)
* [dvsim] update edacloudlauncher imports (Udi Jonnalagadda)
* [dv/doc] Minor fix on dv_doc (Cindy Chen)
* [dvsim] Scheduler updates - max_parallel, max_poll (Srikrishna Iyer)
* [dvsim] Set `Deploy.job_name` more robustly (Srikrishna Iyer)
* [prim] Make SECDED prim generation deterministic (Rupert Swarbrick)
* [tool, xcel] Support dumpping the array of struct in shm/vcd (Tung
  Hoang)
* [dv/otp_ctrl] OTP_CTRL DV doc (Cindy Chen)
* [dv/dv_macros] Fix DV_PRINT_ARR_CONTENTS (Guillermo Maturana)
* [prim_pad_attr/prim_flop_en] Add waiver files (Michael Schaffner)
* [prim_usb_diff] Minor lint fix (Michael Schaffner)
* [prim_clock_div] Update waiver file (Michael Schaffner)
* [top] change prim_generic usage into prim (Timothy Chen)
* [formal/conn] Support dvsim to publish regression result summary
  (Cindy Chen)
* Add formatting changes from allow list (Rafal Kapuscik)
* [prim] Add generic and Xilinx-specific xor2 primitives (Pirmin
  Vogel)
* [prim] Add Width parameter to buffer primitives (Pirmin Vogel)
* [prim] Add generic and Xilinx-specific enable-FF primitives (Pirmin
  Vogel)
* [prim] Remove temporary workaround in parameter list related to
  primgen (Pirmin Vogel)
* [dv/dvsim] Provides more context on some failures. (Guillermo
  Maturana)
* [dvsim] Fix local run error. (Eunchan Kim)
* [dv] Support multi-ral (part 4) (Weicai Yang)
* [dv/dvsim] Adds failure bucketizer for triage. (Guillermo Maturana)
* [lint/docs] Update ascentlint dvsim command in readme (Michael
  Schaffner)
* [top] Various top level lint fixes (Timothy Chen)
* [pinmux/padring] Wire up the pad attribute WARL behavior modules
  (Michael Schaffner)
* [dv] Fix tl_error failure (Weicai Yang)
* [pinout] Update flash test mode and voltage signals/pads (Michael
  Schaffner)
* [pad_wrapper] Extend the generic and Xilinx pad wrapper models
  (Michael Schaffner)
* [dv] Update scb for all blocks (Weicai Yang)
* [dv] Support multi-ral (part 3) (Weicai Yang)
* [prim_arbiter,lint] Tell Verilator to split variables for scheduling
  (Rupert Swarbrick)
* [prim] Fix lint warnings, replace inline AscentLint waivers (Pirmin
  Vogel)
* [dvsim] Scratch root default to $REPO_TOP/scratch (Srikrishna Iyer)
* [dv] Update `process_tl_access` args for all blocks (Weicai Yang)
* [dv] Support multi-ral (part 2) (Weicai Yang)
* [formal] Clean up some formal warnings (Cindy Chen)
* [topgen] Rework pinmux datastructure and templatize tops (Michael
  Schaffner)
* [otp_ctrl] Several small lint fixes (Michael Schaffner)
* [prim_fifo_async] Make async FIFO output zero when empty (Noah
  Moroze)
* [flash] Improve flash ECC handling based on transasction attribute
  (Timothy Chen)
* [dv] Remove toggle coverage excl for a_user/d_user (Weicai Yang)
* [dvsim] Fix remaining comments  from lowRISC/opentitan#5876
  (Srikrishna Iyer)
* [dv] Support multi-ral (part 1) (Weicai Yang)

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
This commit is contained in:
Philipp Wagner 2021-05-11 10:43:04 +01:00 committed by Philipp Wagner
parent 8ef06de73d
commit c7cb958f0d
107 changed files with 2699 additions and 1569 deletions

View file

@ -32,10 +32,10 @@ class ibex_icache_env_cfg extends dv_base_env_cfg;
function new (string name="");
super.new(name);
has_ral = 1'b0; // The ICache has no RAL model
endfunction
virtual function void initialize(bit [BUS_AW-1:0] csr_base_addr = '1);
ral_model_names = {}; // The ICache has no RAL model
super.initialize(csr_base_addr);
core_agent_cfg = ibex_icache_core_agent_cfg::type_id::create("core_agent_cfg");

View file

@ -22,8 +22,6 @@ class ibex_icache_base_test extends dv_base_test #(
super.build_phase(phase);
cfg.has_ral = 1'b0;
// Create config objects for each of the ECC agents. We can't do that in the config object
// itself (because that's not a component, so doesn't have access to the uvm_config_db).
cfg.create_ecc_agent_cfgs(num_ecc_ways);
@ -34,4 +32,3 @@ class ibex_icache_base_test extends dv_base_test #(
// the run_phase; as such, nothing more needs to be done
endclass : ibex_icache_base_test

View file

@ -791,20 +791,20 @@ module ibex_core import ibex_pkg::*; #(
// ECC checkbit generation for regiter file wdata
prim_secded_39_32_enc regfile_ecc_enc (
.in (rf_wdata_wb),
.out (rf_wdata_wb_ecc_o)
.data_i (rf_wdata_wb),
.data_o (rf_wdata_wb_ecc_o)
);
// ECC checking on register file rdata
prim_secded_39_32_dec regfile_ecc_dec_a (
.in (rf_rdata_a_ecc_i),
.d_o (),
.data_i (rf_rdata_a_ecc_i),
.data_o (),
.syndrome_o (),
.err_o (rf_ecc_err_a)
);
prim_secded_39_32_dec regfile_ecc_dec_b (
.in (rf_rdata_b_ecc_i),
.d_o (),
.data_i (rf_rdata_b_ecc_i),
.data_o (),
.syndrome_o (),
.err_o (rf_ecc_err_b)
);

View file

@ -307,8 +307,8 @@ module ibex_icache import ibex_pkg::*; #(
assign tag_ecc_output_unused = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
prim_secded_28_22_enc tag_ecc_enc (
.in (tag_ecc_input_padded),
.out (tag_ecc_output_padded)
.data_i (tag_ecc_input_padded),
.data_o (tag_ecc_output_padded)
);
assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]};
@ -316,8 +316,8 @@ module ibex_icache import ibex_pkg::*; #(
// Dataram ECC
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_enc data_ecc_enc (
.in (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
.out (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
.data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
.data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
);
end
@ -426,8 +426,8 @@ module ibex_icache import ibex_pkg::*; #(
tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
prim_secded_28_22_dec data_ecc_dec (
.in (tag_rdata_padded_ic1),
.d_o (),
.data_i (tag_rdata_padded_ic1),
.data_o (),
.syndrome_o (),
.err_o (tag_err_bank_ic1)
);
@ -438,8 +438,8 @@ module ibex_icache import ibex_pkg::*; #(
// Note - could generate for all ways and mux after
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_dec data_ecc_dec (
.in (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
.d_o (),
.data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
.data_o (),
.syndrome_o (),
.err_o (data_err_ic1[bank*2+:2])
);

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/opentitan
rev: f29a0f7a7115e03fba734b1c00691c253aceb07e
rev: ca950b43a0e9ef5013b8e2e5de765bc34fb59b74
}
}

View file

@ -23,10 +23,9 @@
class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
`uvm_object_utils(csr_base_seq)
uvm_reg_block models[$];
uvm_reg_block models[string];
uvm_reg all_csrs[$];
uvm_reg test_csrs[$];
csr_excl_item m_csr_excl_item;
// By default, assume external checker (example, scoreboard) is turned off. If that is the case,
// then writes are followed by call to predict function to update the mirrored value. Reads are
@ -48,12 +47,6 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
// create test_csrs list only if its empty
if (test_csrs.size() == 0) set_csr_test_range();
// create dummy m_csr_excl_item if not supplied
if (m_csr_excl_item == null) begin
`uvm_info(`gtn, "m_csr_excl_item is null, creating a dummy one locally", UVM_LOW)
m_csr_excl_item = csr_excl_item::type_id::create("m_csr_excl_item");
end
endtask
// post_start
@ -63,10 +56,6 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
test_csrs.delete();
endtask
function void set_csr_excl_item(csr_excl_item item);
this.m_csr_excl_item = item;
endfunction
// extract csrs and split and prune to a specified test_csr_chunk
virtual function void set_csr_test_range();
int start_idx;
@ -112,6 +101,18 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
test_csrs.shuffle();
endfunction
// check if this csr/fld is excluded from test based on the excl info in blk.csr_excl
// TODO, consider to put excl info in dv_base_reg and dv_base_reg_field
function bit is_excl(uvm_object obj,
csr_excl_type_e csr_excl_type,
csr_test_type_e csr_test_type);
csr_excl_item csr_excl = get_excl_item(obj);
if (csr_excl == null) begin
return 0;
end else begin
return csr_excl.is_excl(obj, csr_excl_type, csr_test_type);
end
endfunction
endclass
//--------------------------------------------------------------------------------------------------
@ -131,7 +132,7 @@ class csr_hw_reset_seq extends csr_base_seq;
uvm_reg_data_t compare_mask;
// check if parent block or register is excluded from init check
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclInitCheck, CsrHwResetTest)) begin
if (is_excl(test_csrs[i], CsrExclInitCheck, CsrHwResetTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclInitCheck exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -140,8 +141,7 @@ class csr_hw_reset_seq extends csr_base_seq;
`uvm_info(`gtn, $sformatf("Verifying reset value of register %0s",
test_csrs[i].get_full_name()), UVM_MEDIUM)
compare_mask = get_mask_excl_fields(test_csrs[i], CsrExclInitCheck, CsrHwResetTest,
m_csr_excl_item);
compare_mask = get_mask_excl_fields(test_csrs[i], CsrExclInitCheck, CsrHwResetTest);
csr_rd_check(.ptr (test_csrs[i]),
.blocking (0),
.compare (!external_checker),
@ -190,7 +190,7 @@ class csr_write_seq extends csr_base_seq;
dv_base_reg dv_csr;
bit backdoor;
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrHwResetTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrHwResetTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -200,7 +200,7 @@ class csr_write_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrHwResetTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrHwResetTest);
`downcast(dv_csr, test_csrs[i])
if (en_rand_backdoor_write && !dv_csr.get_is_ext_reg()) begin
@ -234,7 +234,7 @@ class csr_rw_seq extends csr_base_seq;
uvm_reg_field test_fields[$];
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrRwTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrRwTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -244,7 +244,7 @@ class csr_rw_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrRwTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrRwTest);
// if external checker is not enabled and writes are made non-blocking, then we need to
// pre-predict so that the mirrored value will be updated. if we dont, then csr_rd_check task
@ -258,8 +258,7 @@ class csr_rw_seq extends csr_base_seq;
.compare(!external_checker),
.compare_vs_ral(1),
.csr_excl_type(CsrExclWriteCheck),
.csr_test_type(CsrRwTest),
.csr_excl_item(m_csr_excl_item));
.csr_test_type(CsrRwTest));
wait_if_max_outstanding_accesses_reached();
end
@ -281,8 +280,8 @@ class csr_bit_bash_seq extends csr_base_seq;
virtual task body();
foreach (test_csrs[i]) begin
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrBitBashTest) ||
m_csr_excl_item.is_excl(test_csrs[i], CsrExclWriteCheck, CsrBitBashTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrBitBashTest) ||
is_excl(test_csrs[i], CsrExclWriteCheck, CsrBitBashTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite/WriteCheck exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -323,15 +322,15 @@ class csr_bit_bash_seq extends csr_base_seq;
endcase
// skip fields that are wr-excluded
if (m_csr_excl_item.is_excl(fields[j], CsrExclWrite, CsrBitBashTest)) begin
if (is_excl(fields[j], CsrExclWrite, CsrBitBashTest)) begin
`uvm_info(`gtn, $sformatf("Skipping field %0s due to CsrExclWrite exclusion",
fields[j].get_full_name()), UVM_MEDIUM)
dc = 1;
end
// ignore fields that are init or rd-excluded
cmp = m_csr_excl_item.is_excl(fields[j], CsrExclInitCheck, CsrBitBashTest) ||
m_csr_excl_item.is_excl(fields[j], CsrExclWriteCheck, CsrBitBashTest) ;
cmp = is_excl(fields[j], CsrExclInitCheck, CsrBitBashTest) ||
is_excl(fields[j], CsrExclWriteCheck, CsrBitBashTest) ;
// Any unused bits on the right side of the LSB?
while (next_lsb < lsb) mode[next_lsb++] = "RO";
@ -404,7 +403,7 @@ class csr_aliasing_seq extends csr_base_seq;
uvm_reg_data_t wdata;
// check if parent block or register is excluded
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrAliasingTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrAliasingTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -414,7 +413,7 @@ class csr_aliasing_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrAliasingTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrAliasingTest);
csr_wr(.ptr(test_csrs[i]), .value(wdata), .blocking(0), .predict(!external_checker));
all_csrs.shuffle();
@ -427,15 +426,14 @@ class csr_aliasing_seq extends csr_base_seq;
uvm_reg_data_t compare_mask;
// check if parent block or register is excluded
if (m_csr_excl_item.is_excl(all_csrs[j], CsrExclInitCheck, CsrAliasingTest) ||
m_csr_excl_item.is_excl(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest)) begin
if (is_excl(all_csrs[j], CsrExclInitCheck, CsrAliasingTest) ||
is_excl(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclInit/WriteCheck exclusion",
all_csrs[j].get_full_name()), UVM_MEDIUM)
continue;
end
compare_mask = get_mask_excl_fields(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest,
m_csr_excl_item);
compare_mask = get_mask_excl_fields(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest);
csr_rd_check(.ptr (all_csrs[j]),
.blocking (0),
.compare (!external_checker),

View file

@ -14,7 +14,7 @@ package csr_utils_pkg;
// local types and variables
uint outstanding_accesses = 0;
uint default_timeout_ns = 1_000_000; // 1ms
uint default_timeout_ns = 2_000_000; // 2ms
uint default_spinwait_timeout_ns = 10_000_000; // 10ms
string msg_id = "csr_utils";
bit default_csr_blocking = 1;
@ -540,7 +540,7 @@ package csr_utils_pkg;
input bit compare_vs_ral = 1,
input csr_excl_type_e csr_excl_type = CsrNoExcl,
input csr_test_type_e csr_test_type = CsrRwTest,
input csr_excl_item csr_excl_item = null);
input csr_excl_item csr_excl_item = get_excl_item(csr));
uvm_reg_data_t compare_mask;
// Check if parent block or register is excluded from read-check
@ -730,10 +730,12 @@ package csr_utils_pkg;
function automatic uvm_reg_data_t get_mask_excl_fields(uvm_reg csr,
csr_excl_type_e csr_excl_type,
csr_test_type_e csr_test_type,
csr_excl_item m_csr_excl_item);
csr_excl_item m_csr_excl_item =
get_excl_item(csr));
uvm_reg_field flds[$];
csr.get_fields(flds);
get_mask_excl_fields = '1;
if (m_csr_excl_item != null) begin
foreach (flds[i]) begin
if (m_csr_excl_item.is_excl(flds[i], csr_excl_type, csr_test_type)) begin
@ -746,6 +748,20 @@ package csr_utils_pkg;
end
endfunction
function automatic csr_excl_item get_excl_item(uvm_object ptr);
csr_field_t csr_or_fld;
dv_base_reg_block blk;
csr_or_fld = decode_csr_or_field(ptr);
`downcast(blk, csr_or_fld.csr.get_parent(), , , msg_id)
// csr_excl is at the highest level of reg block
while (blk.csr_excl == null) begin
`downcast(blk, blk.get_parent(), , , msg_id)
`DV_CHECK_NE_FATAL(blk, null, "", msg_id)
end
return blk.csr_excl;
endfunction
// sources
`include "csr_seq_lib.sv"

View file

@ -342,7 +342,7 @@ class dv_base_reg extends uvm_reg;
string parent_name = this.get_parent().get_name();
// block level alert name is input alert name from hjson
if (parent_name == "ral") return update_err_alert_name;
if (get_parent().get_parent() == null) return update_err_alert_name;
// top-level alert name is ${block_name} + alert name from hjson
return ($sformatf("%0s_%0s", parent_name, update_err_alert_name));
@ -360,7 +360,7 @@ class dv_base_reg extends uvm_reg;
string parent_name = this.get_parent().get_name();
// block level alert name is input alert name from hjson
if (parent_name == "ral") return storage_err_alert_name;
if (get_parent().get_parent() == null) return storage_err_alert_name;
// top-level alert name is ${block_name} + alert name from hjson
return ($sformatf("%0s_%0s", parent_name, storage_err_alert_name));

View file

@ -20,6 +20,9 @@ class dv_base_agent_cfg extends uvm_object;
// use for phase_ready_to_end to add additional delay after ok_to_end is set
int ok_to_end_delay_ns = 1000;
// Indicates that the interface is under reset. The derived monitor detects and maintains it.
bit in_reset;
`uvm_object_utils_begin(dv_base_agent_cfg)
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)

View file

@ -16,17 +16,42 @@ class dv_base_env #(type CFG_T = dv_base_env_cfg,
`uvm_component_new
virtual function void build_phase(uvm_phase phase);
string default_ral_name;
super.build_phase(phase);
// get dv_base_env_cfg object from uvm_config_db
if (!uvm_config_db#(CFG_T)::get(this, "", "cfg", cfg)) begin
`uvm_fatal(`gfn, $sformatf("failed to get %s from uvm_config_db", cfg.get_type_name()))
end
// get vifs
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", "clk_rst_vif", cfg.clk_rst_vif)) begin
`uvm_fatal(get_full_name(), "failed to get clk_rst_if from uvm_config_db")
// get vifs for RAL models
if (cfg.ral_model_names.size > 0) begin
default_ral_name = cfg.ral.get_type_name();
foreach (cfg.ral_model_names[i]) begin
string ral_name = cfg.ral_model_names[i];
string if_name;
if (ral_name == default_ral_name) if_name = "clk_rst_vif";
else if_name = {"clk_rst_vif_", ral_name};
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", if_name,
cfg.clk_rst_vifs[ral_name])) begin
`uvm_fatal(`gfn, $sformatf("failed to get clk_rst_if for %0s from uvm_config_db", ral_name))
end
cfg.clk_rst_vifs[ral_name].set_freq_mhz(cfg.clk_freqs_mhz[ral_name]);
end
// assign default clk_rst_vif
`DV_CHECK_FATAL(cfg.clk_rst_vifs.exists(default_ral_name))
cfg.clk_rst_vif = cfg.clk_rst_vifs[default_ral_name];
end else begin
// no RAL model, get the default clk_rst_vif for the block
// such as xbar, it doesn't has ral model, but it also needs a default clk_rst_vif
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", "clk_rst_vif", cfg.clk_rst_vif))
begin
`uvm_fatal(`gfn, "failed to get clk_rst_if from uvm_config_db")
end
cfg.clk_rst_vif.set_freq_mhz(cfg.clk_freq_mhz);
end
cfg.clk_rst_vif.set_freq_mhz(cfg.clk_freq_mhz);
// create components
if (cfg.en_cov) begin

View file

@ -9,7 +9,7 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
bit en_scb_tl_err_chk = 1;
bit en_scb_mem_chk = 1;
bit en_cov = 0; // Enable via plusarg, only if coverage collection is turned on.
bit has_ral = 1;
bit under_reset = 0;
bit is_initialized; // Indicates that the initialize() method has been called.
@ -29,20 +29,31 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
// reg model & q of valid csr addresses
RAL_T ral;
dv_base_reg_block ral_models[$];
bit [bus_params_pkg::BUS_AW-1:0] csr_addrs[$];
addr_range_t mem_ranges[$];
dv_base_reg_block ral_models[string];
// A queue of the names of RAL models that should be created in the `initialize` function
// Related agents, adapters will be created in env as well as connecting them with scb
// For example, if the IP has an additional RAL model named `ral1`, add it into the list as below
// virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1);
// ral_model_names.push_back("ral1");
// super.initialize(csr_base_addr);
string ral_model_names[$] = {RAL_T::type_name};
bit [bus_params_pkg::BUS_AW-1:0] csr_addrs[string][$];
addr_range_t mem_ranges[string][$];
// clk_rst_if & freq
// clk_rst_vif and clk_freq_mhz are used for default clk/rst. If more than one RAL, the other
// clk_rst_vif and clk_freq_mhz can be found from the associative arrays
virtual clk_rst_if clk_rst_vif;
virtual clk_rst_if clk_rst_vifs[string];
rand clk_freq_mhz_e clk_freq_mhz;
rand clk_freq_mhz_e clk_freqs_mhz[string];
`uvm_object_param_utils_begin(dv_base_env_cfg #(RAL_T))
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_scb, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)
`uvm_field_int (zero_delays, UVM_DEFAULT)
`uvm_field_enum (clk_freq_mhz_e, clk_freq_mhz, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
@ -51,36 +62,22 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
`DV_CHECK_FATAL(is_initialized, "Please invoke initialize() before randomizing this object.")
endfunction
function void post_randomize();
if (clk_freqs_mhz.size > 0) begin
`DV_CHECK_FATAL(clk_freqs_mhz.exists(RAL_T::type_name))
clk_freqs_mhz[RAL_T::type_name] = clk_freq_mhz;
end
endfunction
virtual function void initialize(bit [bus_params_pkg::BUS_AW-1:0] csr_base_addr = '1);
is_initialized = 1'b1;
// build the ral model
if (has_ral) begin
uvm_reg_addr_t base_addr;
create_ral_models(csr_base_addr);
ral = RAL_T::type_id::create("ral");
// Build the register block with an arbitrary base address (we choose 0). We'll change it
// later.
ral.build(.base_addr(0), .csr_excl(null));
apply_ral_fixes();
ral.lock_model();
// Now the model is locked, we know its layout. Set the base address for the register block.
// The function internally picks a random one if we pass '1 to it, and performs an integrity
// check on the set address.
//
// The definition of base_addr explicitly casts from a bus address to a uvm_reg_addr_t (to
// correctly handle the case where a bus address is narrower than a uvm_reg_addr_t).
base_addr = (&csr_base_addr ?
{`UVM_REG_ADDR_WIDTH{1'b1}} :
{{(`UVM_REG_ADDR_WIDTH - bus_params_pkg::BUS_AW){1'b0}}, csr_base_addr});
ral.set_base_addr(base_addr);
// Get list of valid csr addresses (useful in seq to randomize addr as well as in scb checks)
get_csr_addrs(ral, csr_addrs);
get_mem_addr_ranges(ral, mem_ranges);
ral_models.push_back(ral);
// add items to clk_freqs_mhz before randomizing it
foreach (ral_model_names[i]) begin
clk_freqs_mhz[ral_model_names[i]] = ClkFreq24Mhz;
end
endfunction
@ -100,4 +97,58 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
csr_utils_pkg::reset_deasserted();
endfunction
virtual function void create_ral_models(bit [bus_params_pkg::BUS_AW-1:0] csr_base_addr = '1);
foreach (ral_model_names[i]) begin
string ral_name = ral_model_names[i];
uvm_reg_addr_t base_addr;
dv_base_reg_block reg_blk = create_ral_by_name(ral_name);
if (reg_blk.get_name() == RAL_T::type_name) `downcast(ral, reg_blk)
// Build the register block with an arbitrary base address (we choose 0). We'll change it
// later.
reg_blk.build(.base_addr(0), .csr_excl(null));
apply_ral_fixes();
reg_blk.lock_model();
// Now the model is locked, we know its layout. Set the base address for the register block.
// The function internally picks a random one if we pass '1 to it, and performs an integrity
// check on the set address.
//
// The definition of base_addr explicitly casts from a bus address to a uvm_reg_addr_t (to
// correctly handle the case where a bus address is narrower than a uvm_reg_addr_t).
base_addr = (&csr_base_addr ?
{`UVM_REG_ADDR_WIDTH{1'b1}} :
{{(`UVM_REG_ADDR_WIDTH - bus_params_pkg::BUS_AW){1'b0}}, csr_base_addr});
reg_blk.set_base_addr(base_addr);
// Get list of valid csr addresses (useful in seq to randomize addr as well as in scb checks)
get_csr_addrs(reg_blk, csr_addrs[ral_name]);
get_mem_addr_ranges(reg_blk, mem_ranges[ral_name]);
ral_models[ral_name] = reg_blk;
end
if (ral_model_names.size > 0) begin
`DV_CHECK_FATAL(ral_models.exists(RAL_T::type_name))
end
endfunction
virtual function dv_base_reg_block create_ral_by_name(string name);
uvm_object obj;
uvm_factory factory;
dv_base_reg_block ral;
factory = uvm_factory::get();
obj = factory.create_object_by_name(.requested_type_name(name), .name(name));
if (obj == null) begin
// print factory overrides to help debug
factory.print();
`uvm_fatal(msg_id, $sformatf("could not create %0s as a RAL model, see above for a list of \
type/instance overrides", name))
end
if (!$cast(ral, obj)) begin
`uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a dv_base_reg_block", name))
end
return ral;
endfunction
endclass

View file

@ -50,9 +50,7 @@ class dv_base_scoreboard #(type RAL_T = dv_base_reg_block,
virtual function void reset(string kind = "HARD");
// reset the ral model
if (cfg.has_ral) begin
foreach (cfg.ral_models[i]) cfg.ral_models[i].reset(kind);
end
foreach (cfg.ral_models[i]) cfg.ral_models[i].reset(kind);
endfunction
virtual function void pre_abort();

View file

@ -86,8 +86,22 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
virtual task apply_reset(string kind = "HARD");
if (kind == "HARD") begin
cfg.clk_rst_vif.apply_reset();
end
if (cfg.clk_rst_vifs.size > 0) begin
fork
begin : isolation_fork
foreach (cfg.clk_rst_vifs[i]) begin
automatic string ral_name = i;
fork
cfg.clk_rst_vifs[ral_name].apply_reset();
join_none
end
wait fork;
end : isolation_fork
join
end else begin // no ral model and only has default clk_rst_vif
cfg.clk_rst_vif.apply_reset();
end
end // if (kind == "HARD")
endtask
virtual task wait_for_reset(string reset_kind = "HARD",
@ -109,62 +123,37 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
csr_utils_pkg::wait_no_outstanding_access();
endtask
// function to add csr exclusions of the given type using the csr_excl_item item
// arg csr_test_type: this the the type of csr test run - we may want additional exclusions
// depending on what test seq we are running
// arg csr_excl: this is the csr exclusion object that maintains the list of exclusions
// the same object handle is to be passed to csr sequences in csr_seq_lib so that they can query
// those exclusions
virtual function void add_csr_exclusions(string csr_test_type,
csr_excl_item csr_excl,
string scope = "ral");
`uvm_info(`gfn, "no exclusion item added from this function", UVM_DEBUG)
endfunction
// TODO: temp support, can delete this once all IPs update their exclusion in hjson
virtual function csr_excl_item add_and_return_csr_excl(string csr_test_type);
add_csr_exclusions(csr_test_type, ral.csr_excl);
ral.csr_excl.print_exclusions();
return ral.csr_excl;
endfunction
// wrapper task around run_csr_vseq - the purpose is to be able to call this directly for actual
// csr tests (as opposed to higher level stress test that could also run csr seq as a fork by
// calling run_csr_vseq(..) task)
virtual task run_csr_vseq_wrapper(int num_times = 1);
string csr_test_type;
csr_excl_item csr_excl;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
`DV_CHECK_GE_FATAL(cfg.ral_models.size(), 1)
// get csr_test_type from plusarg
void'($value$plusargs("csr_%0s", csr_test_type));
// create csr exclusions before running the csr seq
csr_excl = add_and_return_csr_excl(csr_test_type);
// run the csr seq
for (int i = 1; i <= num_times; i++) begin
`uvm_info(`gfn, $sformatf("running csr %0s vseq iteration %0d/%0d",
csr_test_type, i, num_times), UVM_LOW)
run_csr_vseq(.csr_test_type(csr_test_type), .csr_excl(csr_excl));
run_csr_vseq(.csr_test_type(csr_test_type));
end
endtask
// capture the entire csr seq as a task that can be overridden if desired
// arg csr_test_type: what csr test to run {hw_reset, rw, bit_bash, aliasing}
// arg csr_excl: csr exclusion object - needs to be created and exclusions set before call
// arg num_test_csrs:instead of testing the entire ral model or passing test chunk info via
// plusarg, provide ability to set a random number of csrs to test from higher level sequence
virtual task run_csr_vseq(string csr_test_type = "",
csr_excl_item csr_excl = null,
int num_test_csrs = 0,
bit do_rand_wr_and_reset = 1);
csr_base_seq m_csr_seq;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
`DV_CHECK_GE_FATAL(cfg.ral_models.size(), 1)
// check which csr test type
case (csr_test_type)
@ -193,7 +182,6 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
m_csr_write_seq.models = cfg.ral_models;
m_csr_write_seq.external_checker = cfg.en_scb;
m_csr_write_seq.en_rand_backdoor_write = 1'b1;
m_csr_write_seq.set_csr_excl_item(csr_excl);
m_csr_write_seq.start(null);
// run dut_shutdown before asserting reset
@ -211,7 +199,6 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
m_csr_seq.models = cfg.ral_models;
m_csr_seq.external_checker = cfg.en_scb;
m_csr_seq.num_test_csrs = num_test_csrs;
m_csr_seq.set_csr_excl_item(csr_excl);
m_csr_seq.start(null);
endtask

View file

@ -270,7 +270,7 @@
`define DV_PRINT_ARR_CONTENTS(ARR_, V_=uvm_pkg::UVM_MEDIUM, ID_=`gfn) \
begin \
foreach (ARR_[i]) begin \
`dv_info($sformatf("%s[%0d] = 0x%0d[0x%0h]", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \
`dv_info($sformatf("%s[%0d] = %0d (0x%0h)", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \
end \
end
`endif

View file

@ -18,8 +18,7 @@ package dv_test_status_pkg;
$display(" | | __/\\__ \\ |_ | |_) | (_| \\__ \\__ \\ __/ (_| |_|");
$display(" |_|\\___||___/\\__| | .__/ \\__,_|___/___/\\___|\\__,_(_)");
$display(" |_| \n");
end
else begin
end else begin
$display("\nTEST FAILED CHECKS");
$display(" _____ _ __ _ _ _ _ ");
$display("|_ _|__ ___| |_ / _| __ _(_) | ___ __| | |");

View file

@ -74,8 +74,8 @@ class mem_model #(int AddrWidth = bus_params_pkg::BUS_AW,
if (mask[0]) begin
compare_byte(addr + i, byte_data);
end else begin
`DV_CHECK_EQ(byte_data, 0,
$sformatf("addr 0x%0h masked data aren't 0, mask 0x%0h", addr, mask))
// Nothing to do here: since this byte wasn't selected by the mask, there are no
// requirements about what data came back.
end
act_data = act_data>> 8;
mask = mask >> 1;

View file

@ -28,7 +28,8 @@
"^UVM_WARNING\\s[^:].*$",
"^Assert failed: ",
"^\\s*Offending '.*'",
"^TEST FAILED (UVM_)?CHECKS$"]
"^TEST FAILED (UVM_)?CHECKS$",
"^Error:.*$"] // ISS errors
// Default TileLink widths
tl_aw: 32

View file

@ -2,14 +2,18 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Exclude below TL toggle coverage as these pins won't be changed in the comportable IPs
// Exclude below TL toggle coverage as these pins won't be changed in the comportable IPs.
// Exclude alert_sender as it is fully verified in FPV. Note that user might also need to exclude
// prim_diff_decode module, but it is not listed here because modules other than prim_alert_sender
// might instantiate this prim_diff_decode as well.
INSTANCE: tb.dut
Toggle tl_i.a_user.parity "logic tl_i.a_user.parity[7:0]"
Toggle tl_i.a_user.parity_en "logic tl_i.a_user.parity_en"
Toggle tl_i.a_user.rsvd1 "logic tl_i.a_user.rsvd1[6:0]"
Toggle tl_o.d_opcode [1] "logic tl_o.d_opcode[2:0]"
Toggle tl_o.d_opcode [2] "logic tl_o.d_opcode[2:0]"
Toggle tl_o.d_param "logic tl_o.d_param[2:0]"
Toggle tl_o.d_sink "logic tl_o.d_sink[0:0]"
Toggle tl_o.d_user "logic tl_o.d_user[15:0]"
Toggle tl_i.a_param "logic tl_i.a_param[2:0]"
// TODO: revisit after issue #6089 is implemented
ANNOTATION: "[EXTERNAL] alert_sender is fully verified by FPV testbench."
MODULE:prim_alert_sender

View file

@ -110,7 +110,7 @@ proc wavedumpScope {scope fid {depth 0} {fsdb_flags "+all"} {probe_flags "-all"
if {$depth == 0} {
set depth "all"
}
probe "$scope" $probe_flags -depth $depth -shm
probe "$scope" $probe_flags -depth $depth -memories -shm
}
"vpd" {
@ -124,7 +124,7 @@ proc wavedumpScope {scope fid {depth 0} {fsdb_flags "+all"} {probe_flags "-all"
if {$depth == 0} {
set depth "all"
}
probe "$scope" $probe_flags -depth $depth -vcd
probe "$scope" $probe_flags -depth $depth -memories -vcd
}
}

View file

@ -4,6 +4,10 @@
`verilator_config
// prim_arbiter_ppc
// ppc_out[i] depends on ppc_out[i-1]
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_ppc.sv" -match "*ppc_out*"
// prim_lfsr
// lfsr_perm_test is just used for an SVA
lint_off -rule UNUSED -file "*/rtl/prim_lfsr.sv" -match "*lfsr_perm_test*"

View file

@ -16,6 +16,10 @@ waive -rules {LINE_LENGTH} -location {prim_assert.sv} -msg {Line length of} \
waive -rules INTEGER -location {prim_packer.sv} -msg {'i' of type int used as a non-constant value} \
-comment "This assigns int i (signed) to a multibit logic variable (unsigned), which is fine"
# prim_packer_fifo
waive -rules {ZERO_REP} -location {prim_packer_fifo.sv} -regexp {Replication count is zero in .*DepthW.*} \
-comment "If InW equals OutW, DepthW is zero"
# TL-UL fifo
waive -rules {HIER_BRANCH_NOT_READ} -location {tlul_fifo_sync.sv} -regexp {Connected net '(clk_i|rst_ni)' at prim_fifo_sync.sv:.* is not read from in module 'prim_fifo_sync'} \
-comment "In passthrough mode, clk and reset are not read form within this module"

View 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
`verilator_config
// Tell the Verilator scheduler to split up these variables into
// separate pieces when it's figuring out process scheduling. This
// avoids spurious UNOPTFLAT warnings caused by the fact that the
// arrays feed into themselves (with different bits for different
// positions in the tree).
split_var -module "prim_arbiter_fixed" -var "data_tree"
split_var -module "prim_arbiter_fixed" -var "gnt_tree"
split_var -module "prim_arbiter_fixed" -var "idx_tree"
split_var -module "prim_arbiter_fixed" -var "req_tree"
split_var -module "prim_arbiter_tree" -var "req_tree"
split_var -module "prim_arbiter_tree" -var "prio_tree"
split_var -module "prim_arbiter_tree" -var "sel_tree"
split_var -module "prim_arbiter_tree" -var "mask_tree"
split_var -module "prim_arbiter_tree" -var "idx_tree"
split_var -module "prim_arbiter_tree" -var "data_tree"

View file

@ -4,8 +4,15 @@
#
# waiver file for prim_clock_div
waive -rules CLOCK_EDGE -location {prim_clock_div.sv} -msg {Falling edge of clock 'clk_i' used here, should use rising edge} \
-comment "The clock switch signal is synchronized on negative edge to ensure it is away from any transition"
waive -rules DUAL_EDGE_CLOCK -location {prim_clock_div.sv} -regexp {.*} \
-comment "The clock switch signal is synchronized on negative edge to ensure it is away from any transition"
waive -rules CLOCK_MUX -location {prim_clock_div.sv} -regexp {.*reaches a multiplexer here, used as a clock.*} \
-comment "A mux is used during scan bypass, and for switching between div by 2 and div by 1 clocks"
waive -rules CLOCK_USE -location {prim_clock_div.sv} -regexp {'clk_i' is connected to 'prim_clock_mux2' port 'clk1_i', and used as a clock} \
-comment "This clock mux usage is OK."

View file

@ -0,0 +1,8 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# waiver file for prim_flop_en
waive -rules {STAR_PORT_CONN_USE} -location {prim_flop_en.sv} -regexp {.*wild card port connection encountered on instance.*} \
-comment "Generated prims may have wildcard connections."

View file

@ -0,0 +1,8 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# waiver file for prim_pad_attr
waive -rules {STAR_PORT_CONN_USE} -location {prim_pad_attr.sv} -regexp {.*wild card port connection encountered on instance.*} \
-comment "Generated prims may have wildcard connections."

View file

@ -17,12 +17,14 @@ filesets:
- lowrisc:prim:clock_mux2
- lowrisc:prim:buf
- lowrisc:prim:flop
- lowrisc:prim:flop_en
- lowrisc:prim:flop_2sync
- lowrisc:prim:arbiter
- lowrisc:prim:fifo
- lowrisc:prim:alert
- lowrisc:prim:subreg
- lowrisc:prim:cipher
- lowrisc:prim:xor2
files:
- rtl/prim_clock_gating_sync.sv
- rtl/prim_esc_pkg.sv

View file

@ -19,6 +19,9 @@ filesets:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_arbiter.vlt
file_type: vlt
files_ascentlint_waiver:
depend:

View file

@ -0,0 +1,48 @@
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:flop_en"
description: "Generic enable flop"
filesets:
primgen_dep:
depend:
- lowrisc:prim:prim_pkg
- lowrisc:prim:primgen
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_flop_en.waiver
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
generate:
impl:
generator: primgen
parameters:
prim_name: flop_en
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- primgen_dep
generate:
- impl

View file

@ -0,0 +1,50 @@
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:pad_attr"
description: "PAD wrapper attributes"
filesets:
primgen_dep:
depend:
- lowrisc:prim:prim_pkg
- lowrisc:prim:pad_wrapper_pkg
- lowrisc:prim:primgen
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_pad_attr.waiver
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
generate:
impl:
generator: primgen
parameters:
prim_name: pad_attr
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- primgen_dep
generate:
- impl

View file

@ -9,6 +9,7 @@ filesets:
primgen_dep:
depend:
- lowrisc:prim:prim_pkg
- lowrisc:prim:pad_wrapper_pkg
- lowrisc:prim:primgen

View file

@ -0,0 +1,39 @@
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:pad_wrapper_pkg"
description: "Package for pad wrapper"
filesets:
files_rtl:
files:
- rtl/prim_pad_wrapper_pkg.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -0,0 +1,46 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:prim:xor2"
description: "Generic 2-input xor"
filesets:
primgen_dep:
depend:
- lowrisc:prim:prim_pkg
- lowrisc:prim:primgen
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
generate:
impl:
generator: primgen
parameters:
prim_name: xor2
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- primgen_dep
generate:
- impl

View file

@ -113,7 +113,9 @@ module prim_arbiter_ppc #(
end
end else begin: gen_nodatapath
assign data_o = '1;
// TODO: waive data_i from NOT_READ error
// The following signal is used to avoid possible lint errors.
logic [DW-1:0] unused_data [N];
assign unused_data = data_i;
end
always_comb begin

View file

@ -11,13 +11,22 @@
`ASSERT_ERROR(__name) \
end
`define ASSERT_INIT(__name, __prop) \
initial begin \
__name: assert (__prop) \
else begin \
`ASSERT_ERROR(__name) \
end \
end
// Formal tools will ignore the initial construct, so use static assertion as a workaround.
// This workaround terminates design elaboration if the __prop predict is false.
// It calls $fatal() with the first argument equal to 2, it outputs the statistics about the memory
// and CPU time.
`define ASSERT_INIT(__name, __prop) \
`ifdef FPV_ON \
if (!(__prop)) $fatal(2, "Fatal static assertion [%s]: (%s) is not true.", \
(__name), (__prop)); \
`else \
initial begin \
__name: assert (__prop) \
else begin \
`ASSERT_ERROR(__name) \
end \
end \
`endif
`define ASSERT_FINAL(__name, __prop) \
final begin \

View file

@ -9,6 +9,7 @@
module prim_fifo_async #(
parameter int unsigned Width = 16,
parameter int unsigned Depth = 4,
parameter bit OutputZeroIfEmpty = 1'b0, // if == 1 always output 0 when FIFO is empty
localparam int unsigned DepthW = $clog2(Depth+1) // derived parameter representing [0..Depth]
) (
// write port
@ -164,13 +165,14 @@ module prim_fifo_async #(
end
assign wready_o = !full_wclk;
assign rvalid_o = !empty_rclk;
assign wready_o = ~full_wclk;
assign rvalid_o = ~empty_rclk;
/////////////
// Storage //
/////////////
logic [Width-1:0] rdata_int;
if (Depth > 1) begin : g_storage_mux
always_ff @(posedge clk_wr_i) begin
@ -179,7 +181,7 @@ module prim_fifo_async #(
end
end
assign rdata_o = storage[fifo_rptr_q[PTRV_W-1:0]];
assign rdata_int = storage[fifo_rptr_q[PTRV_W-1:0]];
end else begin : g_storage_simple
@ -189,10 +191,16 @@ module prim_fifo_async #(
end
end
assign rdata_o = storage[0];
assign rdata_int = storage[0];
end
if (OutputZeroIfEmpty == 1'b1) begin : gen_output_zero
assign rdata_o = empty_rclk ? '0 : rdata_int;
end else begin : gen_no_output_zero
assign rdata_o = rdata_int;
end
//////////////////////////////////////
// Decimal <-> Gray-code Conversion //
//////////////////////////////////////

View file

@ -112,7 +112,7 @@ module prim_keccak #(
endfunction : box_to_bitarray
// Step Mapping =============================================================
// theta(θ)
// theta
// XOR each bit in the state with the parity of two columns
// C[x,z] = A[x,0,z] ^ A[x,1,z] ^ A[x,2,z] ^ A[x,3,z] ^ A[x,4,z]
// D[x,z] = C[x-1,z] ^ C[x+1,z-1]

View file

@ -20,10 +20,10 @@ module prim_lc_sender (
logic [lc_ctrl_pkg::TxWidth-1:0] lc_en, lc_en_out;
assign lc_en = lc_ctrl_pkg::TxWidth'(lc_en_i);
prim_generic_flop #(
prim_flop #(
.Width(lc_ctrl_pkg::TxWidth),
.ResetValue(lc_ctrl_pkg::TxWidth'(lc_ctrl_pkg::Off))
) u_prim_generic_flop (
) u_prim_flop (
.clk_i,
.rst_ni,
.d_i ( lc_en ),

View file

@ -59,10 +59,10 @@ module prim_multibit_sync #(
logic [NumChecks:0][Width-1:0] data_check_d;
logic [NumChecks-1:0][Width-1:0] data_check_q;
prim_generic_flop_2sync #(
prim_flop_2sync #(
.Width(Width),
.ResetValue(ResetValue)
) i_prim_generic_flop_2sync (
) i_prim_flop_2sync (
.clk_i,
.rst_ni,
.d_i(data_i),

View file

@ -113,7 +113,7 @@ module prim_packer_fifo #(
assign rvalid_o = (depth_q == FullDepth) && !clr_q;
end else begin : gen_unpack_mode
logic [MaxW-1:0] rdata_shifted; // ri lint_check_waive NOT_READ
logic [MaxW-1:0] rdata_shifted;
logic pull_data;
logic [DepthW:0] ptr_q, ptr_d;
logic [DepthW:0] lsb_is_one;
@ -127,7 +127,7 @@ module prim_packer_fifo #(
end
end
assign lsb_is_one = {{DepthW{1'b0}},1'b1}; // ri lint_check_waive ZERO_REP
assign lsb_is_one = {{DepthW{1'b0}},1'b1};
assign max_value = FullDepth;
assign rdata_shifted = data_q >> ptr_q*OutW;
assign clear_data = (rready_i && (depth_q == lsb_is_one)) || clr_q;
@ -152,6 +152,11 @@ module prim_packer_fifo #(
assign rdata_o = rdata_shifted[OutW-1:0];
assign rvalid_o = !(depth_q == '0) && !clr_q;
// Avoid possible lint errors in case InW > OutW.
if (InW > OutW) begin : gen_unused
logic [MaxW-MinW-1:0] unused_rdata_shifted;
assign unused_rdata_shifted = rdata_shifted[MaxW-1:MinW];
end
end
@ -160,13 +165,12 @@ module prim_packer_fifo #(
//////////////////////////////////////////////
// If not acked, valid_o should keep asserting
`ASSERT(ValidOPairedWidthReadyI_A,
rvalid_o && !rready_i |=> rvalid_o)
`ASSERT(ValidOPairedWithReadyI_A,
rvalid_o && !rready_i && !clr_i |=> rvalid_o)
// If output port doesn't accept the data, the data should be stable
`ASSERT(DataOStableWhenPending_A,
##1 rvalid_o && $past(rvalid_o)
&& !$past(rready_i) |-> $stable(rdata_o))
&& !$past(rready_i) && !$past(clr_i) |-> $stable(rdata_o))
endmodule

View file

@ -0,0 +1,44 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
package prim_pad_wrapper_pkg;
typedef enum logic [2:0] {
BidirStd = 3'h0, // Standard bidirectional pad
BidirTol = 3'h1, // Voltage tolerant pad
BidirOd = 3'h2, // Open-drain capable pad
InputStd = 3'h3, // Input-only pad
AnalogIn0 = 3'h4 // Analog input pad
} pad_type_e;
typedef enum logic [1:0] {
NoScan = 2'h0,
ScanIn = 2'h1,
ScanOut = 2'h2
} scan_role_e;
// Pad attributes
parameter int DriveStrDw = 4;
parameter int SlewRateDw = 2;
typedef struct packed {
logic [DriveStrDw-1:0] drive_strength; // Drive strength (0000: weakest, 1111: strongest).
logic [SlewRateDw-1:0] slew_rate; // Slew rate (0: slowest, 11: fastest).
logic od_en; // Open-drain enable
logic schmitt_en; // Schmitt trigger enable.
logic keep_en; // Keeper enable.
logic pull_select; // Pull direction (0: pull down, 1: pull up).
logic pull_en; // Pull enable.
logic virt_od_en; // Virtual open drain enable.
logic invert; // Input/output inversion.
} pad_attr_t;
parameter int AttrDw = $bits(pad_attr_t);
// Power OK signals (library dependent)
parameter int PokDw = 8;
typedef logic [PokDw-1:0] pad_pok_t;
endpackage : prim_pad_wrapper_pkg

View file

@ -137,23 +137,23 @@ module prim_ram_1p_adv import prim_ram_1p_pkg::*; #(
if (Width == 16) begin : gen_secded_22_16
if (HammingECC) begin : gen_hamming
prim_secded_hamming_22_16_enc u_enc (
.in(wdata_i),
.out(wdata_d)
.data_i(wdata_i),
.data_o(wdata_d)
);
prim_secded_hamming_22_16_dec u_dec (
.in (rdata_sram),
.d_o (rdata_d[0+:Width]),
.data_i (rdata_sram),
.data_o (rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (rerror_d)
);
end else begin : gen_hsiao
prim_secded_22_16_enc u_enc (
.in(wdata_i),
.out(wdata_d)
.data_i(wdata_i),
.data_o(wdata_d)
);
prim_secded_22_16_dec u_dec (
.in (rdata_sram),
.d_o (rdata_d[0+:Width]),
.data_i (rdata_sram),
.data_o (rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (rerror_d)
);
@ -161,23 +161,23 @@ module prim_ram_1p_adv import prim_ram_1p_pkg::*; #(
end else if (Width == 32) begin : gen_secded_39_32
if (HammingECC) begin : gen_hamming
prim_secded_hamming_39_32_enc u_enc (
.in(wdata_i),
.out(wdata_d)
.data_i(wdata_i),
.data_o(wdata_d)
);
prim_secded_hamming_39_32_dec u_dec (
.in (rdata_sram),
.d_o (rdata_d[0+:Width]),
.data_i (rdata_sram),
.data_o (rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (rerror_d)
);
end else begin : gen_hsiao
prim_secded_39_32_enc u_enc (
.in(wdata_i),
.out(wdata_d)
.data_i(wdata_i),
.data_o(wdata_d)
);
prim_secded_39_32_dec u_dec (
.in (rdata_sram),
.d_o (rdata_d[0+:Width]),
.data_i (rdata_sram),
.data_o (rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (rerror_d)
);

View file

@ -182,43 +182,43 @@ module prim_ram_2p_async_adv import prim_ram_2p_pkg::*; #(
if (Width == 32) begin : gen_secded_39_32
if (HammingECC) begin : gen_hamming
prim_secded_hamming_39_32_enc u_enc_a (
.in(a_wdata_i),
.out(a_wdata_d)
.data_i(a_wdata_i),
.data_o(a_wdata_d)
);
prim_secded_hamming_39_32_dec u_dec_a (
.in (a_rdata_sram),
.d_o (a_rdata_d[0+:Width]),
.data_i (a_rdata_sram),
.data_o (a_rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (a_rerror_d)
);
prim_secded_hamming_39_32_enc u_enc_b (
.in(b_wdata_i),
.out(b_wdata_d)
.data_i(b_wdata_i),
.data_o(b_wdata_d)
);
prim_secded_hamming_39_32_dec u_dec_b (
.in (b_rdata_sram),
.d_o (b_rdata_d[0+:Width]),
.data_i (b_rdata_sram),
.data_o (b_rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (b_rerror_d)
);
end else begin : gen_hsiao
prim_secded_39_32_enc u_enc_a (
.in(a_wdata_i),
.out(a_wdata_d)
.data_i(a_wdata_i),
.data_o(a_wdata_d)
);
prim_secded_39_32_dec u_dec_a (
.in (a_rdata_sram),
.d_o (a_rdata_d[0+:Width]),
.data_i (a_rdata_sram),
.data_o (a_rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (a_rerror_d)
);
prim_secded_39_32_enc u_enc_b (
.in(b_wdata_i),
.out(b_wdata_d)
.data_i(b_wdata_i),
.data_o(b_wdata_d)
);
prim_secded_39_32_dec u_dec_b (
.in (b_rdata_sram),
.d_o (b_rdata_d[0+:Width]),
.data_i (b_rdata_sram),
.data_o (b_rdata_d[0+:Width]),
.syndrome_o ( ),
.err_o (b_rerror_d)
);

View file

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hsiao
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_22_16_dec (
input [21:0] in,
output logic [15:0] d_o,
input [21:0] data_i,
output logic [15:0] data_o,
output logic [5:0] syndrome_o,
output logic [1:0] err_o
);
@ -15,30 +14,30 @@ module prim_secded_22_16_dec (
logic single_error;
// Syndrome calculation
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);
assign syndrome_o[0] = ^(data_i & 22'h01496E);
assign syndrome_o[1] = ^(data_i & 22'h02F20B);
assign syndrome_o[2] = ^(data_i & 22'h048ED8);
assign syndrome_o[3] = ^(data_i & 22'h087714);
assign syndrome_o[4] = ^(data_i & 22'h10ACA5);
assign syndrome_o[5] = ^(data_i & 22'h2011F3);
// Corrected output calculation
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'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];
assign data_o[0] = (syndrome_o == 6'h32) ^ data_i[0];
assign data_o[1] = (syndrome_o == 6'h23) ^ data_i[1];
assign data_o[2] = (syndrome_o == 6'h19) ^ data_i[2];
assign data_o[3] = (syndrome_o == 6'h7) ^ data_i[3];
assign data_o[4] = (syndrome_o == 6'h2c) ^ data_i[4];
assign data_o[5] = (syndrome_o == 6'h31) ^ data_i[5];
assign data_o[6] = (syndrome_o == 6'h25) ^ data_i[6];
assign data_o[7] = (syndrome_o == 6'h34) ^ data_i[7];
assign data_o[8] = (syndrome_o == 6'h29) ^ data_i[8];
assign data_o[9] = (syndrome_o == 6'he) ^ data_i[9];
assign data_o[10] = (syndrome_o == 6'h1c) ^ data_i[10];
assign data_o[11] = (syndrome_o == 6'h15) ^ data_i[11];
assign data_o[12] = (syndrome_o == 6'h2a) ^ data_i[12];
assign data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13];
assign data_o[14] = (syndrome_o == 6'hb) ^ data_i[14];
assign data_o[15] = (syndrome_o == 6'h16) ^ data_i[15];
// err_o calc. bit0: single error, bit1: double error
assign single_error = ^syndrome_o;

View file

@ -2,22 +2,21 @@
// 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 -m 6 -k 16 -s 1592631616 -c hsiao
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_22_16_enc (
input [15:0] in,
output logic [21:0] out
input [15:0] data_i,
output logic [21:0] data_o
);
always_comb begin : p_encode
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);
data_o = 22'(data_i);
data_o[16] = ^(data_o & 22'h00496E);
data_o[17] = ^(data_o & 22'h00F20B);
data_o[18] = ^(data_o & 22'h008ED8);
data_o[19] = ^(data_o & 22'h007714);
data_o[20] = ^(data_o & 22'h00ACA5);
data_o[21] = ^(data_o & 22'h0011F3);
end
endmodule : prim_secded_22_16_enc

View file

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 6 -k 22 -s 1592631616 -c hsiao
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_28_22_dec (
input [27:0] in,
output logic [21:0] d_o,
input [27:0] data_i,
output logic [21:0] data_o,
output logic [5:0] syndrome_o,
output logic [1:0] err_o
);
@ -15,36 +14,36 @@ module prim_secded_28_22_dec (
logic single_error;
// Syndrome calculation
assign syndrome_o[0] = ^(in & 28'h07003FF);
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'h43DAAA4);
assign syndrome_o[5] = ^(in & 28'h82ED348);
assign syndrome_o[0] = ^(data_i & 28'h07003FF);
assign syndrome_o[1] = ^(data_i & 28'h090FC0F);
assign syndrome_o[2] = ^(data_i & 28'h1271C71);
assign syndrome_o[3] = ^(data_i & 28'h23B6592);
assign syndrome_o[4] = ^(data_i & 28'h43DAAA4);
assign syndrome_o[5] = ^(data_i & 28'h83ED348);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 6'h7) ^ in[0];
assign d_o[1] = (syndrome_o == 6'hb) ^ in[1];
assign d_o[2] = (syndrome_o == 6'h13) ^ in[2];
assign d_o[3] = (syndrome_o == 6'h23) ^ in[3];
assign d_o[4] = (syndrome_o == 6'hd) ^ in[4];
assign d_o[5] = (syndrome_o == 6'h15) ^ in[5];
assign d_o[6] = (syndrome_o == 6'h25) ^ in[6];
assign d_o[7] = (syndrome_o == 6'h19) ^ in[7];
assign d_o[8] = (syndrome_o == 6'h29) ^ in[8];
assign d_o[9] = (syndrome_o == 6'h31) ^ in[9];
assign d_o[10] = (syndrome_o == 6'he) ^ in[10];
assign d_o[11] = (syndrome_o == 6'h16) ^ in[11];
assign d_o[12] = (syndrome_o == 6'h26) ^ in[12];
assign d_o[13] = (syndrome_o == 6'h1a) ^ in[13];
assign d_o[14] = (syndrome_o == 6'h2a) ^ in[14];
assign d_o[15] = (syndrome_o == 6'h32) ^ in[15];
assign d_o[16] = (syndrome_o == 6'h1c) ^ in[16];
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'h1f) ^ in[20];
assign d_o[21] = (syndrome_o == 6'h3d) ^ in[21];
assign data_o[0] = (syndrome_o == 6'h7) ^ data_i[0];
assign data_o[1] = (syndrome_o == 6'hb) ^ data_i[1];
assign data_o[2] = (syndrome_o == 6'h13) ^ data_i[2];
assign data_o[3] = (syndrome_o == 6'h23) ^ data_i[3];
assign data_o[4] = (syndrome_o == 6'hd) ^ data_i[4];
assign data_o[5] = (syndrome_o == 6'h15) ^ data_i[5];
assign data_o[6] = (syndrome_o == 6'h25) ^ data_i[6];
assign data_o[7] = (syndrome_o == 6'h19) ^ data_i[7];
assign data_o[8] = (syndrome_o == 6'h29) ^ data_i[8];
assign data_o[9] = (syndrome_o == 6'h31) ^ data_i[9];
assign data_o[10] = (syndrome_o == 6'he) ^ data_i[10];
assign data_o[11] = (syndrome_o == 6'h16) ^ data_i[11];
assign data_o[12] = (syndrome_o == 6'h26) ^ data_i[12];
assign data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13];
assign data_o[14] = (syndrome_o == 6'h2a) ^ data_i[14];
assign data_o[15] = (syndrome_o == 6'h32) ^ data_i[15];
assign data_o[16] = (syndrome_o == 6'h1c) ^ data_i[16];
assign data_o[17] = (syndrome_o == 6'h2c) ^ data_i[17];
assign data_o[18] = (syndrome_o == 6'h34) ^ data_i[18];
assign data_o[19] = (syndrome_o == 6'h38) ^ data_i[19];
assign data_o[20] = (syndrome_o == 6'h3b) ^ data_i[20];
assign data_o[21] = (syndrome_o == 6'h3d) ^ data_i[21];
// err_o calc. bit0: single error, bit1: double error
assign single_error = ^syndrome_o;

View file

@ -2,22 +2,21 @@
// 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 -m 6 -k 22 -s 1592631616 -c hsiao
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_28_22_enc (
input [21:0] in,
output logic [27:0] out
input [21:0] data_i,
output logic [27:0] data_o
);
always_comb begin : p_encode
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);
data_o = 28'(data_i);
data_o[22] = ^(data_o & 28'h03003FF);
data_o[23] = ^(data_o & 28'h010FC0F);
data_o[24] = ^(data_o & 28'h0271C71);
data_o[25] = ^(data_o & 28'h03B6592);
data_o[26] = ^(data_o & 28'h03DAAA4);
data_o[27] = ^(data_o & 28'h03ED348);
end
endmodule : prim_secded_28_22_enc

View file

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hsiao
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_39_32_dec (
input [38:0] in,
output logic [31:0] d_o,
input [38:0] data_i,
output logic [31:0] data_o,
output logic [6:0] syndrome_o,
output logic [1:0] err_o
);
@ -15,47 +14,47 @@ module prim_secded_39_32_dec (
logic single_error;
// Syndrome calculation
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);
assign syndrome_o[0] = ^(data_i & 39'h012606BD25);
assign syndrome_o[1] = ^(data_i & 39'h02DEBA8050);
assign syndrome_o[2] = ^(data_i & 39'h04413D89AA);
assign syndrome_o[3] = ^(data_i & 39'h0831234ED1);
assign syndrome_o[4] = ^(data_i & 39'h10C2C1323B);
assign syndrome_o[5] = ^(data_i & 39'h202DCC624C);
assign syndrome_o[6] = ^(data_i & 39'h4098505586);
// Corrected output calculation
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'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];
assign data_o[0] = (syndrome_o == 7'h19) ^ data_i[0];
assign data_o[1] = (syndrome_o == 7'h54) ^ data_i[1];
assign data_o[2] = (syndrome_o == 7'h61) ^ data_i[2];
assign data_o[3] = (syndrome_o == 7'h34) ^ data_i[3];
assign data_o[4] = (syndrome_o == 7'h1a) ^ data_i[4];
assign data_o[5] = (syndrome_o == 7'h15) ^ data_i[5];
assign data_o[6] = (syndrome_o == 7'h2a) ^ data_i[6];
assign data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7];
assign data_o[8] = (syndrome_o == 7'h45) ^ data_i[8];
assign data_o[9] = (syndrome_o == 7'h38) ^ data_i[9];
assign data_o[10] = (syndrome_o == 7'h49) ^ data_i[10];
assign data_o[11] = (syndrome_o == 7'hd) ^ data_i[11];
assign data_o[12] = (syndrome_o == 7'h51) ^ data_i[12];
assign data_o[13] = (syndrome_o == 7'h31) ^ data_i[13];
assign data_o[14] = (syndrome_o == 7'h68) ^ data_i[14];
assign data_o[15] = (syndrome_o == 7'h7) ^ data_i[15];
assign data_o[16] = (syndrome_o == 7'h1c) ^ data_i[16];
assign data_o[17] = (syndrome_o == 7'hb) ^ data_i[17];
assign data_o[18] = (syndrome_o == 7'h25) ^ data_i[18];
assign data_o[19] = (syndrome_o == 7'h26) ^ data_i[19];
assign data_o[20] = (syndrome_o == 7'h46) ^ data_i[20];
assign data_o[21] = (syndrome_o == 7'he) ^ data_i[21];
assign data_o[22] = (syndrome_o == 7'h70) ^ data_i[22];
assign data_o[23] = (syndrome_o == 7'h32) ^ data_i[23];
assign data_o[24] = (syndrome_o == 7'h2c) ^ data_i[24];
assign data_o[25] = (syndrome_o == 7'h13) ^ data_i[25];
assign data_o[26] = (syndrome_o == 7'h23) ^ data_i[26];
assign data_o[27] = (syndrome_o == 7'h62) ^ data_i[27];
assign data_o[28] = (syndrome_o == 7'h4a) ^ data_i[28];
assign data_o[29] = (syndrome_o == 7'h29) ^ data_i[29];
assign data_o[30] = (syndrome_o == 7'h16) ^ data_i[30];
assign data_o[31] = (syndrome_o == 7'h52) ^ data_i[31];
// err_o calc. bit0: single error, bit1: double error
assign single_error = ^syndrome_o;

View file

@ -2,23 +2,22 @@
// 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 -m 7 -k 32 -s 1592631616 -c hsiao
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_39_32_enc (
input [31:0] in,
output logic [38:0] out
input [31:0] data_i,
output logic [38:0] data_o
);
always_comb begin : p_encode
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);
data_o = 39'(data_i);
data_o[32] = ^(data_o & 39'h002606BD25);
data_o[33] = ^(data_o & 39'h00DEBA8050);
data_o[34] = ^(data_o & 39'h00413D89AA);
data_o[35] = ^(data_o & 39'h0031234ED1);
data_o[36] = ^(data_o & 39'h00C2C1323B);
data_o[37] = ^(data_o & 39'h002DCC624C);
data_o[38] = ^(data_o & 39'h0098505586);
end
endmodule : prim_secded_39_32_enc

View file

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 7 -k 57 -s 1592631616 -c hsiao
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_64_57_dec (
input [63:0] in,
output logic [56:0] d_o,
input [63:0] data_i,
output logic [56:0] data_o,
output logic [6:0] syndrome_o,
output logic [1:0] err_o
);
@ -15,72 +14,72 @@ module prim_secded_64_57_dec (
logic single_error;
// Syndrome calculation
assign syndrome_o[0] = ^(in & 64'h0303FFF800007FFF);
assign syndrome_o[1] = ^(in & 64'h057C1FF801FF801F);
assign syndrome_o[2] = ^(in & 64'h09BDE1F87E0781E1);
assign syndrome_o[3] = ^(in & 64'h11DEEE3B8E388E22);
assign syndrome_o[4] = ^(in & 64'h21EF76CDB2C93244);
assign syndrome_o[5] = ^(in & 64'h41F7BB56D5525488);
assign syndrome_o[6] = ^(in & 64'h81FBDDA769A46910);
assign syndrome_o[0] = ^(data_i & 64'h0303FFF800007FFF);
assign syndrome_o[1] = ^(data_i & 64'h057C1FF801FF801F);
assign syndrome_o[2] = ^(data_i & 64'h09BDE1F87E0781E1);
assign syndrome_o[3] = ^(data_i & 64'h11DEEE3B8E388E22);
assign syndrome_o[4] = ^(data_i & 64'h21EF76CDB2C93244);
assign syndrome_o[5] = ^(data_i & 64'h41F7BB56D5525488);
assign syndrome_o[6] = ^(data_i & 64'h81FBDDA769A46910);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 7'h7) ^ in[0];
assign d_o[1] = (syndrome_o == 7'hb) ^ in[1];
assign d_o[2] = (syndrome_o == 7'h13) ^ in[2];
assign d_o[3] = (syndrome_o == 7'h23) ^ in[3];
assign d_o[4] = (syndrome_o == 7'h43) ^ in[4];
assign d_o[5] = (syndrome_o == 7'hd) ^ in[5];
assign d_o[6] = (syndrome_o == 7'h15) ^ in[6];
assign d_o[7] = (syndrome_o == 7'h25) ^ in[7];
assign d_o[8] = (syndrome_o == 7'h45) ^ in[8];
assign d_o[9] = (syndrome_o == 7'h19) ^ in[9];
assign d_o[10] = (syndrome_o == 7'h29) ^ in[10];
assign d_o[11] = (syndrome_o == 7'h49) ^ in[11];
assign d_o[12] = (syndrome_o == 7'h31) ^ in[12];
assign d_o[13] = (syndrome_o == 7'h51) ^ in[13];
assign d_o[14] = (syndrome_o == 7'h61) ^ in[14];
assign d_o[15] = (syndrome_o == 7'he) ^ in[15];
assign d_o[16] = (syndrome_o == 7'h16) ^ in[16];
assign d_o[17] = (syndrome_o == 7'h26) ^ in[17];
assign d_o[18] = (syndrome_o == 7'h46) ^ in[18];
assign d_o[19] = (syndrome_o == 7'h1a) ^ in[19];
assign d_o[20] = (syndrome_o == 7'h2a) ^ in[20];
assign d_o[21] = (syndrome_o == 7'h4a) ^ in[21];
assign d_o[22] = (syndrome_o == 7'h32) ^ in[22];
assign d_o[23] = (syndrome_o == 7'h52) ^ in[23];
assign d_o[24] = (syndrome_o == 7'h62) ^ in[24];
assign d_o[25] = (syndrome_o == 7'h1c) ^ in[25];
assign d_o[26] = (syndrome_o == 7'h2c) ^ in[26];
assign d_o[27] = (syndrome_o == 7'h4c) ^ in[27];
assign d_o[28] = (syndrome_o == 7'h34) ^ in[28];
assign d_o[29] = (syndrome_o == 7'h54) ^ in[29];
assign d_o[30] = (syndrome_o == 7'h64) ^ in[30];
assign d_o[31] = (syndrome_o == 7'h38) ^ in[31];
assign d_o[32] = (syndrome_o == 7'h58) ^ in[32];
assign d_o[33] = (syndrome_o == 7'h68) ^ in[33];
assign d_o[34] = (syndrome_o == 7'h70) ^ in[34];
assign d_o[35] = (syndrome_o == 7'h1f) ^ in[35];
assign d_o[36] = (syndrome_o == 7'h2f) ^ in[36];
assign d_o[37] = (syndrome_o == 7'h4f) ^ in[37];
assign d_o[38] = (syndrome_o == 7'h37) ^ in[38];
assign d_o[39] = (syndrome_o == 7'h57) ^ in[39];
assign d_o[40] = (syndrome_o == 7'h67) ^ in[40];
assign d_o[41] = (syndrome_o == 7'h3b) ^ in[41];
assign d_o[42] = (syndrome_o == 7'h5b) ^ in[42];
assign d_o[43] = (syndrome_o == 7'h6b) ^ in[43];
assign d_o[44] = (syndrome_o == 7'h73) ^ in[44];
assign d_o[45] = (syndrome_o == 7'h3d) ^ in[45];
assign d_o[46] = (syndrome_o == 7'h5d) ^ in[46];
assign d_o[47] = (syndrome_o == 7'h6d) ^ in[47];
assign d_o[48] = (syndrome_o == 7'h75) ^ in[48];
assign d_o[49] = (syndrome_o == 7'h79) ^ in[49];
assign d_o[50] = (syndrome_o == 7'h3e) ^ in[50];
assign d_o[51] = (syndrome_o == 7'h5e) ^ in[51];
assign d_o[52] = (syndrome_o == 7'h6e) ^ in[52];
assign d_o[53] = (syndrome_o == 7'h76) ^ in[53];
assign d_o[54] = (syndrome_o == 7'h7a) ^ in[54];
assign d_o[55] = (syndrome_o == 7'h7c) ^ in[55];
assign d_o[56] = (syndrome_o == 7'h7f) ^ in[56];
assign data_o[0] = (syndrome_o == 7'h7) ^ data_i[0];
assign data_o[1] = (syndrome_o == 7'hb) ^ data_i[1];
assign data_o[2] = (syndrome_o == 7'h13) ^ data_i[2];
assign data_o[3] = (syndrome_o == 7'h23) ^ data_i[3];
assign data_o[4] = (syndrome_o == 7'h43) ^ data_i[4];
assign data_o[5] = (syndrome_o == 7'hd) ^ data_i[5];
assign data_o[6] = (syndrome_o == 7'h15) ^ data_i[6];
assign data_o[7] = (syndrome_o == 7'h25) ^ data_i[7];
assign data_o[8] = (syndrome_o == 7'h45) ^ data_i[8];
assign data_o[9] = (syndrome_o == 7'h19) ^ data_i[9];
assign data_o[10] = (syndrome_o == 7'h29) ^ data_i[10];
assign data_o[11] = (syndrome_o == 7'h49) ^ data_i[11];
assign data_o[12] = (syndrome_o == 7'h31) ^ data_i[12];
assign data_o[13] = (syndrome_o == 7'h51) ^ data_i[13];
assign data_o[14] = (syndrome_o == 7'h61) ^ data_i[14];
assign data_o[15] = (syndrome_o == 7'he) ^ data_i[15];
assign data_o[16] = (syndrome_o == 7'h16) ^ data_i[16];
assign data_o[17] = (syndrome_o == 7'h26) ^ data_i[17];
assign data_o[18] = (syndrome_o == 7'h46) ^ data_i[18];
assign data_o[19] = (syndrome_o == 7'h1a) ^ data_i[19];
assign data_o[20] = (syndrome_o == 7'h2a) ^ data_i[20];
assign data_o[21] = (syndrome_o == 7'h4a) ^ data_i[21];
assign data_o[22] = (syndrome_o == 7'h32) ^ data_i[22];
assign data_o[23] = (syndrome_o == 7'h52) ^ data_i[23];
assign data_o[24] = (syndrome_o == 7'h62) ^ data_i[24];
assign data_o[25] = (syndrome_o == 7'h1c) ^ data_i[25];
assign data_o[26] = (syndrome_o == 7'h2c) ^ data_i[26];
assign data_o[27] = (syndrome_o == 7'h4c) ^ data_i[27];
assign data_o[28] = (syndrome_o == 7'h34) ^ data_i[28];
assign data_o[29] = (syndrome_o == 7'h54) ^ data_i[29];
assign data_o[30] = (syndrome_o == 7'h64) ^ data_i[30];
assign data_o[31] = (syndrome_o == 7'h38) ^ data_i[31];
assign data_o[32] = (syndrome_o == 7'h58) ^ data_i[32];
assign data_o[33] = (syndrome_o == 7'h68) ^ data_i[33];
assign data_o[34] = (syndrome_o == 7'h70) ^ data_i[34];
assign data_o[35] = (syndrome_o == 7'h1f) ^ data_i[35];
assign data_o[36] = (syndrome_o == 7'h2f) ^ data_i[36];
assign data_o[37] = (syndrome_o == 7'h4f) ^ data_i[37];
assign data_o[38] = (syndrome_o == 7'h37) ^ data_i[38];
assign data_o[39] = (syndrome_o == 7'h57) ^ data_i[39];
assign data_o[40] = (syndrome_o == 7'h67) ^ data_i[40];
assign data_o[41] = (syndrome_o == 7'h3b) ^ data_i[41];
assign data_o[42] = (syndrome_o == 7'h5b) ^ data_i[42];
assign data_o[43] = (syndrome_o == 7'h6b) ^ data_i[43];
assign data_o[44] = (syndrome_o == 7'h73) ^ data_i[44];
assign data_o[45] = (syndrome_o == 7'h3d) ^ data_i[45];
assign data_o[46] = (syndrome_o == 7'h5d) ^ data_i[46];
assign data_o[47] = (syndrome_o == 7'h6d) ^ data_i[47];
assign data_o[48] = (syndrome_o == 7'h75) ^ data_i[48];
assign data_o[49] = (syndrome_o == 7'h79) ^ data_i[49];
assign data_o[50] = (syndrome_o == 7'h3e) ^ data_i[50];
assign data_o[51] = (syndrome_o == 7'h5e) ^ data_i[51];
assign data_o[52] = (syndrome_o == 7'h6e) ^ data_i[52];
assign data_o[53] = (syndrome_o == 7'h76) ^ data_i[53];
assign data_o[54] = (syndrome_o == 7'h7a) ^ data_i[54];
assign data_o[55] = (syndrome_o == 7'h7c) ^ data_i[55];
assign data_o[56] = (syndrome_o == 7'h7f) ^ data_i[56];
// err_o calc. bit0: single error, bit1: double error
assign single_error = ^syndrome_o;

View file

@ -2,23 +2,22 @@
// 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 -m 7 -k 57 -s 1592631616 -c hsiao
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_64_57_enc (
input [56:0] in,
output logic [63:0] out
input [56:0] data_i,
output logic [63:0] data_o
);
always_comb begin : p_encode
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);
data_o = 64'(data_i);
data_o[57] = ^(data_o & 64'h0103FFF800007FFF);
data_o[58] = ^(data_o & 64'h017C1FF801FF801F);
data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1);
data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22);
data_o[61] = ^(data_o & 64'h01EF76CDB2C93244);
data_o[62] = ^(data_o & 64'h01F7BB56D5525488);
data_o[63] = ^(data_o & 64'h01FBDDA769A46910);
end
endmodule : prim_secded_64_57_enc

View file

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hsiao
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_72_64_dec (
input [71:0] in,
output logic [63:0] d_o,
input [71:0] data_i,
output logic [63:0] data_o,
output logic [7:0] syndrome_o,
output logic [1:0] err_o
);
@ -15,80 +14,80 @@ module prim_secded_72_64_dec (
logic single_error;
// Syndrome calculation
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);
assign syndrome_o[0] = ^(data_i & 72'h01B9000000001FFFFF);
assign syndrome_o[1] = ^(data_i & 72'h025E00000FFFE0003F);
assign syndrome_o[2] = ^(data_i & 72'h0467003FF003E007C1);
assign syndrome_o[3] = ^(data_i & 72'h08CD0FC0F03C207842);
assign syndrome_o[4] = ^(data_i & 72'h10B671C711C4438884);
assign syndrome_o[5] = ^(data_i & 72'h20B5B65926488C9108);
assign syndrome_o[6] = ^(data_i & 72'h40CBDAAA4A91152210);
assign syndrome_o[7] = ^(data_i & 72'h807AED348D221A4420);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 8'h7) ^ in[0];
assign d_o[1] = (syndrome_o == 8'hb) ^ in[1];
assign d_o[2] = (syndrome_o == 8'h13) ^ in[2];
assign d_o[3] = (syndrome_o == 8'h23) ^ in[3];
assign d_o[4] = (syndrome_o == 8'h43) ^ in[4];
assign d_o[5] = (syndrome_o == 8'h83) ^ in[5];
assign d_o[6] = (syndrome_o == 8'hd) ^ in[6];
assign d_o[7] = (syndrome_o == 8'h15) ^ in[7];
assign d_o[8] = (syndrome_o == 8'h25) ^ in[8];
assign d_o[9] = (syndrome_o == 8'h45) ^ in[9];
assign d_o[10] = (syndrome_o == 8'h85) ^ in[10];
assign d_o[11] = (syndrome_o == 8'h19) ^ in[11];
assign d_o[12] = (syndrome_o == 8'h29) ^ in[12];
assign d_o[13] = (syndrome_o == 8'h49) ^ in[13];
assign d_o[14] = (syndrome_o == 8'h89) ^ in[14];
assign d_o[15] = (syndrome_o == 8'h31) ^ in[15];
assign d_o[16] = (syndrome_o == 8'h51) ^ in[16];
assign d_o[17] = (syndrome_o == 8'h91) ^ in[17];
assign d_o[18] = (syndrome_o == 8'h61) ^ in[18];
assign d_o[19] = (syndrome_o == 8'ha1) ^ in[19];
assign d_o[20] = (syndrome_o == 8'hc1) ^ in[20];
assign d_o[21] = (syndrome_o == 8'he) ^ in[21];
assign d_o[22] = (syndrome_o == 8'h16) ^ in[22];
assign d_o[23] = (syndrome_o == 8'h26) ^ in[23];
assign d_o[24] = (syndrome_o == 8'h46) ^ in[24];
assign d_o[25] = (syndrome_o == 8'h86) ^ in[25];
assign d_o[26] = (syndrome_o == 8'h1a) ^ in[26];
assign d_o[27] = (syndrome_o == 8'h2a) ^ in[27];
assign d_o[28] = (syndrome_o == 8'h4a) ^ in[28];
assign d_o[29] = (syndrome_o == 8'h8a) ^ in[29];
assign d_o[30] = (syndrome_o == 8'h32) ^ in[30];
assign d_o[31] = (syndrome_o == 8'h52) ^ in[31];
assign d_o[32] = (syndrome_o == 8'h92) ^ in[32];
assign d_o[33] = (syndrome_o == 8'h62) ^ in[33];
assign d_o[34] = (syndrome_o == 8'ha2) ^ in[34];
assign d_o[35] = (syndrome_o == 8'hc2) ^ in[35];
assign d_o[36] = (syndrome_o == 8'h1c) ^ in[36];
assign d_o[37] = (syndrome_o == 8'h2c) ^ in[37];
assign d_o[38] = (syndrome_o == 8'h4c) ^ in[38];
assign d_o[39] = (syndrome_o == 8'h8c) ^ in[39];
assign d_o[40] = (syndrome_o == 8'h34) ^ in[40];
assign d_o[41] = (syndrome_o == 8'h54) ^ in[41];
assign d_o[42] = (syndrome_o == 8'h94) ^ in[42];
assign d_o[43] = (syndrome_o == 8'h64) ^ in[43];
assign d_o[44] = (syndrome_o == 8'ha4) ^ in[44];
assign d_o[45] = (syndrome_o == 8'hc4) ^ in[45];
assign d_o[46] = (syndrome_o == 8'h38) ^ in[46];
assign d_o[47] = (syndrome_o == 8'h58) ^ in[47];
assign d_o[48] = (syndrome_o == 8'h98) ^ in[48];
assign d_o[49] = (syndrome_o == 8'h68) ^ in[49];
assign d_o[50] = (syndrome_o == 8'ha8) ^ in[50];
assign d_o[51] = (syndrome_o == 8'hc8) ^ in[51];
assign d_o[52] = (syndrome_o == 8'h70) ^ in[52];
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'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];
assign data_o[0] = (syndrome_o == 8'h7) ^ data_i[0];
assign data_o[1] = (syndrome_o == 8'hb) ^ data_i[1];
assign data_o[2] = (syndrome_o == 8'h13) ^ data_i[2];
assign data_o[3] = (syndrome_o == 8'h23) ^ data_i[3];
assign data_o[4] = (syndrome_o == 8'h43) ^ data_i[4];
assign data_o[5] = (syndrome_o == 8'h83) ^ data_i[5];
assign data_o[6] = (syndrome_o == 8'hd) ^ data_i[6];
assign data_o[7] = (syndrome_o == 8'h15) ^ data_i[7];
assign data_o[8] = (syndrome_o == 8'h25) ^ data_i[8];
assign data_o[9] = (syndrome_o == 8'h45) ^ data_i[9];
assign data_o[10] = (syndrome_o == 8'h85) ^ data_i[10];
assign data_o[11] = (syndrome_o == 8'h19) ^ data_i[11];
assign data_o[12] = (syndrome_o == 8'h29) ^ data_i[12];
assign data_o[13] = (syndrome_o == 8'h49) ^ data_i[13];
assign data_o[14] = (syndrome_o == 8'h89) ^ data_i[14];
assign data_o[15] = (syndrome_o == 8'h31) ^ data_i[15];
assign data_o[16] = (syndrome_o == 8'h51) ^ data_i[16];
assign data_o[17] = (syndrome_o == 8'h91) ^ data_i[17];
assign data_o[18] = (syndrome_o == 8'h61) ^ data_i[18];
assign data_o[19] = (syndrome_o == 8'ha1) ^ data_i[19];
assign data_o[20] = (syndrome_o == 8'hc1) ^ data_i[20];
assign data_o[21] = (syndrome_o == 8'he) ^ data_i[21];
assign data_o[22] = (syndrome_o == 8'h16) ^ data_i[22];
assign data_o[23] = (syndrome_o == 8'h26) ^ data_i[23];
assign data_o[24] = (syndrome_o == 8'h46) ^ data_i[24];
assign data_o[25] = (syndrome_o == 8'h86) ^ data_i[25];
assign data_o[26] = (syndrome_o == 8'h1a) ^ data_i[26];
assign data_o[27] = (syndrome_o == 8'h2a) ^ data_i[27];
assign data_o[28] = (syndrome_o == 8'h4a) ^ data_i[28];
assign data_o[29] = (syndrome_o == 8'h8a) ^ data_i[29];
assign data_o[30] = (syndrome_o == 8'h32) ^ data_i[30];
assign data_o[31] = (syndrome_o == 8'h52) ^ data_i[31];
assign data_o[32] = (syndrome_o == 8'h92) ^ data_i[32];
assign data_o[33] = (syndrome_o == 8'h62) ^ data_i[33];
assign data_o[34] = (syndrome_o == 8'ha2) ^ data_i[34];
assign data_o[35] = (syndrome_o == 8'hc2) ^ data_i[35];
assign data_o[36] = (syndrome_o == 8'h1c) ^ data_i[36];
assign data_o[37] = (syndrome_o == 8'h2c) ^ data_i[37];
assign data_o[38] = (syndrome_o == 8'h4c) ^ data_i[38];
assign data_o[39] = (syndrome_o == 8'h8c) ^ data_i[39];
assign data_o[40] = (syndrome_o == 8'h34) ^ data_i[40];
assign data_o[41] = (syndrome_o == 8'h54) ^ data_i[41];
assign data_o[42] = (syndrome_o == 8'h94) ^ data_i[42];
assign data_o[43] = (syndrome_o == 8'h64) ^ data_i[43];
assign data_o[44] = (syndrome_o == 8'ha4) ^ data_i[44];
assign data_o[45] = (syndrome_o == 8'hc4) ^ data_i[45];
assign data_o[46] = (syndrome_o == 8'h38) ^ data_i[46];
assign data_o[47] = (syndrome_o == 8'h58) ^ data_i[47];
assign data_o[48] = (syndrome_o == 8'h98) ^ data_i[48];
assign data_o[49] = (syndrome_o == 8'h68) ^ data_i[49];
assign data_o[50] = (syndrome_o == 8'ha8) ^ data_i[50];
assign data_o[51] = (syndrome_o == 8'hc8) ^ data_i[51];
assign data_o[52] = (syndrome_o == 8'h70) ^ data_i[52];
assign data_o[53] = (syndrome_o == 8'hb0) ^ data_i[53];
assign data_o[54] = (syndrome_o == 8'hd0) ^ data_i[54];
assign data_o[55] = (syndrome_o == 8'he0) ^ data_i[55];
assign data_o[56] = (syndrome_o == 8'h6d) ^ data_i[56];
assign data_o[57] = (syndrome_o == 8'hd6) ^ data_i[57];
assign data_o[58] = (syndrome_o == 8'h3e) ^ data_i[58];
assign data_o[59] = (syndrome_o == 8'hcb) ^ data_i[59];
assign data_o[60] = (syndrome_o == 8'hb3) ^ data_i[60];
assign data_o[61] = (syndrome_o == 8'hb5) ^ data_i[61];
assign data_o[62] = (syndrome_o == 8'hce) ^ data_i[62];
assign data_o[63] = (syndrome_o == 8'h79) ^ data_i[63];
// err_o calc. bit0: single error, bit1: double error
assign single_error = ^syndrome_o;

View file

@ -2,24 +2,23 @@
// 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 -m 8 -k 64 -s 1592631616 -c hsiao
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_72_64_enc (
input [63:0] in,
output logic [71:0] out
input [63:0] data_i,
output logic [71:0] data_o
);
always_comb begin : p_encode
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);
data_o = 72'(data_i);
data_o[64] = ^(data_o & 72'h00B9000000001FFFFF);
data_o[65] = ^(data_o & 72'h005E00000FFFE0003F);
data_o[66] = ^(data_o & 72'h0067003FF003E007C1);
data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842);
data_o[68] = ^(data_o & 72'h00B671C711C4438884);
data_o[69] = ^(data_o & 72'h00B5B65926488C9108);
data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210);
data_o[71] = ^(data_o & 72'h007AED348D221A4420);
end
endmodule : prim_secded_72_64_enc

View file

@ -2,42 +2,41 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hamming
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_hamming_22_16_dec (
input [21:0] in,
output logic [15:0] d_o,
input [21:0] data_i,
output logic [15:0] data_o,
output logic [5:0] syndrome_o,
output logic [1:0] err_o
);
// Syndrome calculation
assign syndrome_o[0] = ^(in & 22'h01AD5B);
assign syndrome_o[1] = ^(in & 22'h02366D);
assign syndrome_o[2] = ^(in & 22'h04C78E);
assign syndrome_o[3] = ^(in & 22'h0807F0);
assign syndrome_o[4] = ^(in & 22'h10F800);
assign syndrome_o[5] = ^(in & 22'h3FFFFF);
assign syndrome_o[0] = ^(data_i & 22'h01AD5B);
assign syndrome_o[1] = ^(data_i & 22'h02366D);
assign syndrome_o[2] = ^(data_i & 22'h04C78E);
assign syndrome_o[3] = ^(data_i & 22'h0807F0);
assign syndrome_o[4] = ^(data_i & 22'h10F800);
assign syndrome_o[5] = ^(data_i & 22'h3FFFFF);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 6'h23) ^ in[0];
assign d_o[1] = (syndrome_o == 6'h25) ^ in[1];
assign d_o[2] = (syndrome_o == 6'h26) ^ in[2];
assign d_o[3] = (syndrome_o == 6'h27) ^ in[3];
assign d_o[4] = (syndrome_o == 6'h29) ^ in[4];
assign d_o[5] = (syndrome_o == 6'h2a) ^ in[5];
assign d_o[6] = (syndrome_o == 6'h2b) ^ in[6];
assign d_o[7] = (syndrome_o == 6'h2c) ^ in[7];
assign d_o[8] = (syndrome_o == 6'h2d) ^ in[8];
assign d_o[9] = (syndrome_o == 6'h2e) ^ in[9];
assign d_o[10] = (syndrome_o == 6'h2f) ^ in[10];
assign d_o[11] = (syndrome_o == 6'h31) ^ in[11];
assign d_o[12] = (syndrome_o == 6'h32) ^ in[12];
assign d_o[13] = (syndrome_o == 6'h33) ^ in[13];
assign d_o[14] = (syndrome_o == 6'h34) ^ in[14];
assign d_o[15] = (syndrome_o == 6'h35) ^ in[15];
assign data_o[0] = (syndrome_o == 6'h23) ^ data_i[0];
assign data_o[1] = (syndrome_o == 6'h25) ^ data_i[1];
assign data_o[2] = (syndrome_o == 6'h26) ^ data_i[2];
assign data_o[3] = (syndrome_o == 6'h27) ^ data_i[3];
assign data_o[4] = (syndrome_o == 6'h29) ^ data_i[4];
assign data_o[5] = (syndrome_o == 6'h2a) ^ data_i[5];
assign data_o[6] = (syndrome_o == 6'h2b) ^ data_i[6];
assign data_o[7] = (syndrome_o == 6'h2c) ^ data_i[7];
assign data_o[8] = (syndrome_o == 6'h2d) ^ data_i[8];
assign data_o[9] = (syndrome_o == 6'h2e) ^ data_i[9];
assign data_o[10] = (syndrome_o == 6'h2f) ^ data_i[10];
assign data_o[11] = (syndrome_o == 6'h31) ^ data_i[11];
assign data_o[12] = (syndrome_o == 6'h32) ^ data_i[12];
assign data_o[13] = (syndrome_o == 6'h33) ^ data_i[13];
assign data_o[14] = (syndrome_o == 6'h34) ^ data_i[14];
assign data_o[15] = (syndrome_o == 6'h35) ^ data_i[15];
// err_o calc. bit0: single error, bit1: double error
assign err_o[0] = syndrome_o[5];

View file

@ -2,22 +2,21 @@
// 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 -m 6 -k 16 -s 1592631616 -c hamming
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_hamming_22_16_enc (
input [15:0] in,
output logic [21:0] out
input [15:0] data_i,
output logic [21:0] data_o
);
always_comb begin : p_encode
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);
data_o = 22'(data_i);
data_o[16] = ^(data_o & 22'h00AD5B);
data_o[17] = ^(data_o & 22'h00366D);
data_o[18] = ^(data_o & 22'h00C78E);
data_o[19] = ^(data_o & 22'h0007F0);
data_o[20] = ^(data_o & 22'h00F800);
data_o[21] = ^(data_o & 22'h1FFFFF);
end
endmodule : prim_secded_hamming_22_16_enc

View file

@ -2,59 +2,58 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hamming
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_hamming_39_32_dec (
input [38:0] in,
output logic [31:0] d_o,
input [38:0] data_i,
output logic [31:0] data_o,
output logic [6:0] syndrome_o,
output logic [1:0] err_o
);
// Syndrome calculation
assign syndrome_o[0] = ^(in & 39'h0156AAAD5B);
assign syndrome_o[1] = ^(in & 39'h029B33366D);
assign syndrome_o[2] = ^(in & 39'h04E3C3C78E);
assign syndrome_o[3] = ^(in & 39'h0803FC07F0);
assign syndrome_o[4] = ^(in & 39'h1003FFF800);
assign syndrome_o[5] = ^(in & 39'h20FC000000);
assign syndrome_o[6] = ^(in & 39'h7FFFFFFFFF);
assign syndrome_o[0] = ^(data_i & 39'h0156AAAD5B);
assign syndrome_o[1] = ^(data_i & 39'h029B33366D);
assign syndrome_o[2] = ^(data_i & 39'h04E3C3C78E);
assign syndrome_o[3] = ^(data_i & 39'h0803FC07F0);
assign syndrome_o[4] = ^(data_i & 39'h1003FFF800);
assign syndrome_o[5] = ^(data_i & 39'h20FC000000);
assign syndrome_o[6] = ^(data_i & 39'h7FFFFFFFFF);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 7'h43) ^ in[0];
assign d_o[1] = (syndrome_o == 7'h45) ^ in[1];
assign d_o[2] = (syndrome_o == 7'h46) ^ in[2];
assign d_o[3] = (syndrome_o == 7'h47) ^ in[3];
assign d_o[4] = (syndrome_o == 7'h49) ^ in[4];
assign d_o[5] = (syndrome_o == 7'h4a) ^ in[5];
assign d_o[6] = (syndrome_o == 7'h4b) ^ in[6];
assign d_o[7] = (syndrome_o == 7'h4c) ^ in[7];
assign d_o[8] = (syndrome_o == 7'h4d) ^ in[8];
assign d_o[9] = (syndrome_o == 7'h4e) ^ in[9];
assign d_o[10] = (syndrome_o == 7'h4f) ^ in[10];
assign d_o[11] = (syndrome_o == 7'h51) ^ in[11];
assign d_o[12] = (syndrome_o == 7'h52) ^ in[12];
assign d_o[13] = (syndrome_o == 7'h53) ^ in[13];
assign d_o[14] = (syndrome_o == 7'h54) ^ in[14];
assign d_o[15] = (syndrome_o == 7'h55) ^ in[15];
assign d_o[16] = (syndrome_o == 7'h56) ^ in[16];
assign d_o[17] = (syndrome_o == 7'h57) ^ in[17];
assign d_o[18] = (syndrome_o == 7'h58) ^ in[18];
assign d_o[19] = (syndrome_o == 7'h59) ^ in[19];
assign d_o[20] = (syndrome_o == 7'h5a) ^ in[20];
assign d_o[21] = (syndrome_o == 7'h5b) ^ in[21];
assign d_o[22] = (syndrome_o == 7'h5c) ^ in[22];
assign d_o[23] = (syndrome_o == 7'h5d) ^ in[23];
assign d_o[24] = (syndrome_o == 7'h5e) ^ in[24];
assign d_o[25] = (syndrome_o == 7'h5f) ^ in[25];
assign d_o[26] = (syndrome_o == 7'h61) ^ in[26];
assign d_o[27] = (syndrome_o == 7'h62) ^ in[27];
assign d_o[28] = (syndrome_o == 7'h63) ^ in[28];
assign d_o[29] = (syndrome_o == 7'h64) ^ in[29];
assign d_o[30] = (syndrome_o == 7'h65) ^ in[30];
assign d_o[31] = (syndrome_o == 7'h66) ^ in[31];
assign data_o[0] = (syndrome_o == 7'h43) ^ data_i[0];
assign data_o[1] = (syndrome_o == 7'h45) ^ data_i[1];
assign data_o[2] = (syndrome_o == 7'h46) ^ data_i[2];
assign data_o[3] = (syndrome_o == 7'h47) ^ data_i[3];
assign data_o[4] = (syndrome_o == 7'h49) ^ data_i[4];
assign data_o[5] = (syndrome_o == 7'h4a) ^ data_i[5];
assign data_o[6] = (syndrome_o == 7'h4b) ^ data_i[6];
assign data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7];
assign data_o[8] = (syndrome_o == 7'h4d) ^ data_i[8];
assign data_o[9] = (syndrome_o == 7'h4e) ^ data_i[9];
assign data_o[10] = (syndrome_o == 7'h4f) ^ data_i[10];
assign data_o[11] = (syndrome_o == 7'h51) ^ data_i[11];
assign data_o[12] = (syndrome_o == 7'h52) ^ data_i[12];
assign data_o[13] = (syndrome_o == 7'h53) ^ data_i[13];
assign data_o[14] = (syndrome_o == 7'h54) ^ data_i[14];
assign data_o[15] = (syndrome_o == 7'h55) ^ data_i[15];
assign data_o[16] = (syndrome_o == 7'h56) ^ data_i[16];
assign data_o[17] = (syndrome_o == 7'h57) ^ data_i[17];
assign data_o[18] = (syndrome_o == 7'h58) ^ data_i[18];
assign data_o[19] = (syndrome_o == 7'h59) ^ data_i[19];
assign data_o[20] = (syndrome_o == 7'h5a) ^ data_i[20];
assign data_o[21] = (syndrome_o == 7'h5b) ^ data_i[21];
assign data_o[22] = (syndrome_o == 7'h5c) ^ data_i[22];
assign data_o[23] = (syndrome_o == 7'h5d) ^ data_i[23];
assign data_o[24] = (syndrome_o == 7'h5e) ^ data_i[24];
assign data_o[25] = (syndrome_o == 7'h5f) ^ data_i[25];
assign data_o[26] = (syndrome_o == 7'h61) ^ data_i[26];
assign data_o[27] = (syndrome_o == 7'h62) ^ data_i[27];
assign data_o[28] = (syndrome_o == 7'h63) ^ data_i[28];
assign data_o[29] = (syndrome_o == 7'h64) ^ data_i[29];
assign data_o[30] = (syndrome_o == 7'h65) ^ data_i[30];
assign data_o[31] = (syndrome_o == 7'h66) ^ data_i[31];
// err_o calc. bit0: single error, bit1: double error
assign err_o[0] = syndrome_o[6];

View file

@ -2,23 +2,22 @@
// 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 -m 7 -k 32 -s 1592631616 -c hamming
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_hamming_39_32_enc (
input [31:0] in,
output logic [38:0] out
input [31:0] data_i,
output logic [38:0] data_o
);
always_comb begin : p_encode
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);
data_o = 39'(data_i);
data_o[32] = ^(data_o & 39'h0056AAAD5B);
data_o[33] = ^(data_o & 39'h009B33366D);
data_o[34] = ^(data_o & 39'h00E3C3C78E);
data_o[35] = ^(data_o & 39'h0003FC07F0);
data_o[36] = ^(data_o & 39'h0003FFF800);
data_o[37] = ^(data_o & 39'h00FC000000);
data_o[38] = ^(data_o & 39'h3FFFFFFFFF);
end
endmodule : prim_secded_hamming_39_32_enc

View file

@ -2,92 +2,91 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// SECDED Decoder generated by
// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hamming
// SECDED decoder generated by util/design/secded_gen.py
module prim_secded_hamming_72_64_dec (
input [71:0] in,
output logic [63:0] d_o,
input [71:0] data_i,
output logic [63:0] data_o,
output logic [7:0] syndrome_o,
output logic [1:0] err_o
);
// Syndrome calculation
assign syndrome_o[0] = ^(in & 72'h01AB55555556AAAD5B);
assign syndrome_o[1] = ^(in & 72'h02CD9999999B33366D);
assign syndrome_o[2] = ^(in & 72'h04F1E1E1E1E3C3C78E);
assign syndrome_o[3] = ^(in & 72'h0801FE01FE03FC07F0);
assign syndrome_o[4] = ^(in & 72'h1001FFFE0003FFF800);
assign syndrome_o[5] = ^(in & 72'h2001FFFFFFFC000000);
assign syndrome_o[6] = ^(in & 72'h40FE00000000000000);
assign syndrome_o[7] = ^(in & 72'hFFFFFFFFFFFFFFFFFF);
assign syndrome_o[0] = ^(data_i & 72'h01AB55555556AAAD5B);
assign syndrome_o[1] = ^(data_i & 72'h02CD9999999B33366D);
assign syndrome_o[2] = ^(data_i & 72'h04F1E1E1E1E3C3C78E);
assign syndrome_o[3] = ^(data_i & 72'h0801FE01FE03FC07F0);
assign syndrome_o[4] = ^(data_i & 72'h1001FFFE0003FFF800);
assign syndrome_o[5] = ^(data_i & 72'h2001FFFFFFFC000000);
assign syndrome_o[6] = ^(data_i & 72'h40FE00000000000000);
assign syndrome_o[7] = ^(data_i & 72'hFFFFFFFFFFFFFFFFFF);
// Corrected output calculation
assign d_o[0] = (syndrome_o == 8'h83) ^ in[0];
assign d_o[1] = (syndrome_o == 8'h85) ^ in[1];
assign d_o[2] = (syndrome_o == 8'h86) ^ in[2];
assign d_o[3] = (syndrome_o == 8'h87) ^ in[3];
assign d_o[4] = (syndrome_o == 8'h89) ^ in[4];
assign d_o[5] = (syndrome_o == 8'h8a) ^ in[5];
assign d_o[6] = (syndrome_o == 8'h8b) ^ in[6];
assign d_o[7] = (syndrome_o == 8'h8c) ^ in[7];
assign d_o[8] = (syndrome_o == 8'h8d) ^ in[8];
assign d_o[9] = (syndrome_o == 8'h8e) ^ in[9];
assign d_o[10] = (syndrome_o == 8'h8f) ^ in[10];
assign d_o[11] = (syndrome_o == 8'h91) ^ in[11];
assign d_o[12] = (syndrome_o == 8'h92) ^ in[12];
assign d_o[13] = (syndrome_o == 8'h93) ^ in[13];
assign d_o[14] = (syndrome_o == 8'h94) ^ in[14];
assign d_o[15] = (syndrome_o == 8'h95) ^ in[15];
assign d_o[16] = (syndrome_o == 8'h96) ^ in[16];
assign d_o[17] = (syndrome_o == 8'h97) ^ in[17];
assign d_o[18] = (syndrome_o == 8'h98) ^ in[18];
assign d_o[19] = (syndrome_o == 8'h99) ^ in[19];
assign d_o[20] = (syndrome_o == 8'h9a) ^ in[20];
assign d_o[21] = (syndrome_o == 8'h9b) ^ in[21];
assign d_o[22] = (syndrome_o == 8'h9c) ^ in[22];
assign d_o[23] = (syndrome_o == 8'h9d) ^ in[23];
assign d_o[24] = (syndrome_o == 8'h9e) ^ in[24];
assign d_o[25] = (syndrome_o == 8'h9f) ^ in[25];
assign d_o[26] = (syndrome_o == 8'ha1) ^ in[26];
assign d_o[27] = (syndrome_o == 8'ha2) ^ in[27];
assign d_o[28] = (syndrome_o == 8'ha3) ^ in[28];
assign d_o[29] = (syndrome_o == 8'ha4) ^ in[29];
assign d_o[30] = (syndrome_o == 8'ha5) ^ in[30];
assign d_o[31] = (syndrome_o == 8'ha6) ^ in[31];
assign d_o[32] = (syndrome_o == 8'ha7) ^ in[32];
assign d_o[33] = (syndrome_o == 8'ha8) ^ in[33];
assign d_o[34] = (syndrome_o == 8'ha9) ^ in[34];
assign d_o[35] = (syndrome_o == 8'haa) ^ in[35];
assign d_o[36] = (syndrome_o == 8'hab) ^ in[36];
assign d_o[37] = (syndrome_o == 8'hac) ^ in[37];
assign d_o[38] = (syndrome_o == 8'had) ^ in[38];
assign d_o[39] = (syndrome_o == 8'hae) ^ in[39];
assign d_o[40] = (syndrome_o == 8'haf) ^ in[40];
assign d_o[41] = (syndrome_o == 8'hb0) ^ in[41];
assign d_o[42] = (syndrome_o == 8'hb1) ^ in[42];
assign d_o[43] = (syndrome_o == 8'hb2) ^ in[43];
assign d_o[44] = (syndrome_o == 8'hb3) ^ in[44];
assign d_o[45] = (syndrome_o == 8'hb4) ^ in[45];
assign d_o[46] = (syndrome_o == 8'hb5) ^ in[46];
assign d_o[47] = (syndrome_o == 8'hb6) ^ in[47];
assign d_o[48] = (syndrome_o == 8'hb7) ^ in[48];
assign d_o[49] = (syndrome_o == 8'hb8) ^ in[49];
assign d_o[50] = (syndrome_o == 8'hb9) ^ in[50];
assign d_o[51] = (syndrome_o == 8'hba) ^ in[51];
assign d_o[52] = (syndrome_o == 8'hbb) ^ in[52];
assign d_o[53] = (syndrome_o == 8'hbc) ^ in[53];
assign d_o[54] = (syndrome_o == 8'hbd) ^ in[54];
assign d_o[55] = (syndrome_o == 8'hbe) ^ in[55];
assign d_o[56] = (syndrome_o == 8'hbf) ^ in[56];
assign d_o[57] = (syndrome_o == 8'hc1) ^ in[57];
assign d_o[58] = (syndrome_o == 8'hc2) ^ in[58];
assign d_o[59] = (syndrome_o == 8'hc3) ^ in[59];
assign d_o[60] = (syndrome_o == 8'hc4) ^ in[60];
assign d_o[61] = (syndrome_o == 8'hc5) ^ in[61];
assign d_o[62] = (syndrome_o == 8'hc6) ^ in[62];
assign d_o[63] = (syndrome_o == 8'hc7) ^ in[63];
assign data_o[0] = (syndrome_o == 8'h83) ^ data_i[0];
assign data_o[1] = (syndrome_o == 8'h85) ^ data_i[1];
assign data_o[2] = (syndrome_o == 8'h86) ^ data_i[2];
assign data_o[3] = (syndrome_o == 8'h87) ^ data_i[3];
assign data_o[4] = (syndrome_o == 8'h89) ^ data_i[4];
assign data_o[5] = (syndrome_o == 8'h8a) ^ data_i[5];
assign data_o[6] = (syndrome_o == 8'h8b) ^ data_i[6];
assign data_o[7] = (syndrome_o == 8'h8c) ^ data_i[7];
assign data_o[8] = (syndrome_o == 8'h8d) ^ data_i[8];
assign data_o[9] = (syndrome_o == 8'h8e) ^ data_i[9];
assign data_o[10] = (syndrome_o == 8'h8f) ^ data_i[10];
assign data_o[11] = (syndrome_o == 8'h91) ^ data_i[11];
assign data_o[12] = (syndrome_o == 8'h92) ^ data_i[12];
assign data_o[13] = (syndrome_o == 8'h93) ^ data_i[13];
assign data_o[14] = (syndrome_o == 8'h94) ^ data_i[14];
assign data_o[15] = (syndrome_o == 8'h95) ^ data_i[15];
assign data_o[16] = (syndrome_o == 8'h96) ^ data_i[16];
assign data_o[17] = (syndrome_o == 8'h97) ^ data_i[17];
assign data_o[18] = (syndrome_o == 8'h98) ^ data_i[18];
assign data_o[19] = (syndrome_o == 8'h99) ^ data_i[19];
assign data_o[20] = (syndrome_o == 8'h9a) ^ data_i[20];
assign data_o[21] = (syndrome_o == 8'h9b) ^ data_i[21];
assign data_o[22] = (syndrome_o == 8'h9c) ^ data_i[22];
assign data_o[23] = (syndrome_o == 8'h9d) ^ data_i[23];
assign data_o[24] = (syndrome_o == 8'h9e) ^ data_i[24];
assign data_o[25] = (syndrome_o == 8'h9f) ^ data_i[25];
assign data_o[26] = (syndrome_o == 8'ha1) ^ data_i[26];
assign data_o[27] = (syndrome_o == 8'ha2) ^ data_i[27];
assign data_o[28] = (syndrome_o == 8'ha3) ^ data_i[28];
assign data_o[29] = (syndrome_o == 8'ha4) ^ data_i[29];
assign data_o[30] = (syndrome_o == 8'ha5) ^ data_i[30];
assign data_o[31] = (syndrome_o == 8'ha6) ^ data_i[31];
assign data_o[32] = (syndrome_o == 8'ha7) ^ data_i[32];
assign data_o[33] = (syndrome_o == 8'ha8) ^ data_i[33];
assign data_o[34] = (syndrome_o == 8'ha9) ^ data_i[34];
assign data_o[35] = (syndrome_o == 8'haa) ^ data_i[35];
assign data_o[36] = (syndrome_o == 8'hab) ^ data_i[36];
assign data_o[37] = (syndrome_o == 8'hac) ^ data_i[37];
assign data_o[38] = (syndrome_o == 8'had) ^ data_i[38];
assign data_o[39] = (syndrome_o == 8'hae) ^ data_i[39];
assign data_o[40] = (syndrome_o == 8'haf) ^ data_i[40];
assign data_o[41] = (syndrome_o == 8'hb0) ^ data_i[41];
assign data_o[42] = (syndrome_o == 8'hb1) ^ data_i[42];
assign data_o[43] = (syndrome_o == 8'hb2) ^ data_i[43];
assign data_o[44] = (syndrome_o == 8'hb3) ^ data_i[44];
assign data_o[45] = (syndrome_o == 8'hb4) ^ data_i[45];
assign data_o[46] = (syndrome_o == 8'hb5) ^ data_i[46];
assign data_o[47] = (syndrome_o == 8'hb6) ^ data_i[47];
assign data_o[48] = (syndrome_o == 8'hb7) ^ data_i[48];
assign data_o[49] = (syndrome_o == 8'hb8) ^ data_i[49];
assign data_o[50] = (syndrome_o == 8'hb9) ^ data_i[50];
assign data_o[51] = (syndrome_o == 8'hba) ^ data_i[51];
assign data_o[52] = (syndrome_o == 8'hbb) ^ data_i[52];
assign data_o[53] = (syndrome_o == 8'hbc) ^ data_i[53];
assign data_o[54] = (syndrome_o == 8'hbd) ^ data_i[54];
assign data_o[55] = (syndrome_o == 8'hbe) ^ data_i[55];
assign data_o[56] = (syndrome_o == 8'hbf) ^ data_i[56];
assign data_o[57] = (syndrome_o == 8'hc1) ^ data_i[57];
assign data_o[58] = (syndrome_o == 8'hc2) ^ data_i[58];
assign data_o[59] = (syndrome_o == 8'hc3) ^ data_i[59];
assign data_o[60] = (syndrome_o == 8'hc4) ^ data_i[60];
assign data_o[61] = (syndrome_o == 8'hc5) ^ data_i[61];
assign data_o[62] = (syndrome_o == 8'hc6) ^ data_i[62];
assign data_o[63] = (syndrome_o == 8'hc7) ^ data_i[63];
// err_o calc. bit0: single error, bit1: double error
assign err_o[0] = syndrome_o[7];

View file

@ -2,24 +2,23 @@
// 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 -m 8 -k 64 -s 1592631616 -c hamming
// SECDED encoder generated by util/design/secded_gen.py
module prim_secded_hamming_72_64_enc (
input [63:0] in,
output logic [71:0] out
input [63:0] data_i,
output logic [71:0] data_o
);
always_comb begin : p_encode
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);
data_o = 72'(data_i);
data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B);
data_o[65] = ^(data_o & 72'h00CD9999999B33366D);
data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E);
data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0);
data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800);
data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000);
data_o[70] = ^(data_o & 72'h00FE00000000000000);
data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF);
end
endmodule : prim_secded_hamming_72_64_enc

File diff suppressed because it is too large Load diff

View file

@ -19,4 +19,5 @@ waive -rules Z_USE -regexp {Constant with 'Z literal value '1'bz' encountered} -
-comment "This z assignment is correct."
waive -rules PARAM_NOT_USED -regexp {Parameter 'Variant' not used in module 'prim_generic_pad_wrapper'} -location {prim_generic_pad_wrapper.sv} \
-comment "This parameter has been provisioned for later and is currently unused."
waive -rules PARAM_NOT_USED -regexp {Parameter 'ScanRole' not used in module 'prim_generic_pad_wrapper'} -location {prim_generic_pad_wrapper.sv} \
-comment "This parameter has been provisioned for later and is currently unused."

View file

@ -10,6 +10,7 @@ filesets:
depend:
- lowrisc:ip:tlul
- lowrisc:prim:ram_1p
- lowrisc:systems:ast_pkg
- lowrisc:ip:flash_ctrl_pkg
files:
- rtl/prim_generic_flash_bank.sv

View file

@ -0,0 +1,39 @@
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_generic:flop_en"
description: "generic enable flop"
filesets:
files_rtl:
files:
- rtl/prim_generic_flop_en.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -0,0 +1,44 @@
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_generic:pad_attr"
description: "Technology-independent pad attribute WARL module (for sim only!)"
filesets:
files_rtl:
depend:
- lowrisc:prim:assert
- lowrisc:prim:pad_wrapper_pkg
files:
- rtl/prim_generic_pad_attr.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
#- lint/prim_generic_pad_attr.vlt
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
#- lint/prim_generic_pad_attr.waiver
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -9,6 +9,7 @@ filesets:
files_rtl:
depend:
- lowrisc:prim:assert
- lowrisc:prim:pad_wrapper_pkg
files:
- rtl/prim_generic_pad_wrapper.sv
file_type: systemVerilogSource

View file

@ -0,0 +1,39 @@
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_generic:xor2"
description: "Generic 2-input xor"
filesets:
files_rtl:
files:
- rtl/prim_generic_xor2.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -4,11 +4,13 @@
`include "prim_assert.sv"
module prim_generic_buf (
input in_i,
output logic out_o
module prim_generic_buf #(
parameter int Width = 1
) (
input [Width-1:0] in_i,
output logic [Width-1:0] out_o
);
assign out_o = in_i;
endmodule : prim_generic_buf
endmodule

View file

@ -14,7 +14,7 @@ module prim_generic_flash #(
parameter int WordsPerPage = 256,// words per page
parameter int DataWidth = 32, // bits per word
parameter int MetaDataWidth = 12, // metadata such as ECC
parameter int TestModeWidth = 4
parameter int TestModeWidth = 2
) (
input clk_i,
input rst_ni,
@ -35,10 +35,7 @@ module prim_generic_flash #(
inout [TestModeWidth-1:0] flash_test_mode_a_io,
inout flash_test_voltage_h_io,
output logic flash_err_o,
output logic flash_alert_po,
output logic flash_alert_no,
input flash_alert_ack_i,
input flash_alert_trig_i,
output ast_pkg::ast_dif_t fl_alert_src_o,
input tlul_pkg::tl_h2d_t tl_i,
output tlul_pkg::tl_d2h_t tl_o,
input devmode_i
@ -148,6 +145,7 @@ module prim_generic_flash #(
.tl_o,
.en_ifetch_i(tlul_pkg::InstrDis),
.req_o(cfg_req),
.req_type_o(),
.gnt_i(1'b1),
.we_o(cfg_we),
.addr_o(cfg_addr),
@ -179,21 +177,9 @@ module prim_generic_flash #(
// open source model has no error response at the moment
assign flash_err_o = 1'b0;
logic alerts_active;
assign alerts_active = flash_alert_po | ~flash_alert_no;
// default alert assignments
assign fl_alert_src_o = '{p: '0, n: '1};
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
flash_alert_po <= 1'b0;
flash_alert_no <= 1'b1;
end else if (flash_alert_trig_i) begin
flash_alert_po <= 1'b1;
flash_alert_no <= 1'b0;
end else if (alerts_active && flash_alert_ack_i) begin
flash_alert_po <= 1'b0;
flash_alert_no <= 1'b1;
end
end

View file

@ -4,14 +4,13 @@
`include "prim_assert.sv"
module prim_generic_flop # (
parameter int Width = 1,
localparam int WidthSubOne = Width-1,
parameter logic [WidthSubOne:0] ResetValue = 0
module prim_generic_flop #(
parameter int Width = 1,
parameter logic [Width-1:0] ResetValue = 0
) (
input clk_i,
input rst_ni,
input [Width-1:0] d_i,
input clk_i,
input rst_ni,
input [Width-1:0] d_i,
output logic [Width-1:0] q_o
);
@ -23,4 +22,4 @@ module prim_generic_flop # (
end
end
endmodule // prim_generic_flop
endmodule

View file

@ -7,11 +7,10 @@
// for synchronization
module prim_generic_flop_2sync #(
parameter int Width = 16,
localparam int WidthSubOne = Width-1, // temp work around #2679
parameter logic [WidthSubOne:0] ResetValue = '0
parameter int Width = 16,
parameter logic [Width-1:0] ResetValue = '0
) (
input clk_i, // receive clock
input clk_i,
input rst_ni,
input [Width-1:0] d_i,
output logic [Width-1:0] q_o
@ -39,5 +38,4 @@ module prim_generic_flop_2sync #(
.q_o
);
endmodule

View file

@ -0,0 +1,26 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`include "prim_assert.sv"
module prim_generic_flop_en #(
parameter int Width = 1,
parameter logic [Width-1:0] ResetValue = 0
) (
input clk_i,
input rst_ni,
input en_i,
input [Width-1:0] d_i,
output logic [Width-1:0] q_o
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
q_o <= ResetValue;
end else if (en_i) begin
q_o <= d_i;
end
end
endmodule

View file

@ -39,7 +39,18 @@ module prim_generic_otp
// Response channel
output logic valid_o,
output logic [IfWidth-1:0] rdata_o,
output err_e err_o
output err_e err_o,
// External programming voltage
inout wire ext_voltage_io, //TODO enable it after the change in prim_otp file
input ext_voltage_en_i, // TODO
//// alert indication
//////////////////////////
output ast_pkg::ast_dif_t otp_alert_src_o,
// Scan
input lc_ctrl_pkg::lc_tx_t scanmode_i, // Scan Mode input
input scan_en_i, // Scan Shift
input scan_rst_ni // Scan Reset
);
// Not supported in open-source emulation model.
@ -47,6 +58,16 @@ module prim_generic_otp
assign unused_pwr_seq_h = pwr_seq_h_i;
assign pwr_seq_o = '0;
wire unused_ext_voltage;
assign unused_ext_voltage = ext_voltage_io;
logic unused_ext_voltage_en;
assign unused_ext_voltage_en = ext_voltage_en_i;
logic unused_scan;
assign unused_scan = ^{scanmode_i, scan_en_i, scan_rst_ni};
assign otp_alert_src_o = '{p: '0, n: '1};
////////////////////////////////////
// TL-UL Test Interface Emulation //
////////////////////////////////////
@ -81,7 +102,8 @@ module prim_generic_otp
.intg_error_o( ),
.rdata_i ( tlul_rdata_q ),
.rvalid_i ( tlul_rvalid_q ),
.rerror_i ( '0 )
.rerror_i ( '0 ),
.req_type_o ( )
);
always_ff @(posedge clk_i or negedge rst_ni) begin : p_tlul_testreg

View file

@ -0,0 +1,70 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
`include "prim_assert.sv"
module prim_generic_pad_attr
import prim_pad_wrapper_pkg::*;
#(
parameter pad_type_e PadType = BidirStd // currently ignored in the generic model
) (
output pad_attr_t attr_warl_o
);
// Currently supported pad attributes of the generic pad library:
//
// Input-only:
//
// - inversion
// - pullup / pulldown
//
// Bidirectional:
//
// - inversion
// - virtual open drain
// - keeper
// - pullup / pulldown
// - 1 driving strength bit
//
// Note that the last three attributes are not supported on Verilator.
if (PadType == InputStd) begin : gen_input_only_warl
always_comb begin : p_attr
attr_warl_o = '0;
attr_warl_o.invert = 1'b1;
// Driving strength and pulls are not supported by Verilator
`ifndef VERILATOR
attr_warl_o.pull_en = 1'b1;
attr_warl_o.pull_select = 1'b1;
`endif
end
end else if (PadType == BidirStd ||
PadType == BidirTol ||
PadType == BidirOd) begin : gen_bidir_warl
always_comb begin : p_attr
attr_warl_o = '0;
attr_warl_o.invert = 1'b1;
attr_warl_o.virt_od_en = 1'b1;
attr_warl_o.keep_en = 1'b1;
// Driving strength and pulls are not supported by Verilator
`ifndef VERILATOR
attr_warl_o.pull_en = 1'b1;
attr_warl_o.pull_select = 1'b1;
// Only one driving strength bit is supported.
attr_warl_o.drive_strength[0] = 1'b1;
`endif
end
end else if (PadType == AnalogIn0) begin : gen_analog0_warl
// The analog pad type is basically just a feedthrough,
// and does hence not support any of the attributes.
always_comb begin : p_attr
attr_warl_o = '0;
end
end else begin : gen_invalid_config
// this should throw link warnings in elaboration
assert_static_in_generate_config_not_available
assert_static_in_generate_config_not_available();
end
endmodule : prim_generic_pad_attr

View file

@ -7,87 +7,93 @@
`include "prim_assert.sv"
module prim_generic_pad_wrapper #(
parameter int Variant = 0, // currently ignored
parameter int AttrDw = 10,
parameter bit WarlOnly = 0 // If set to 1, no pad is instantiated and only warl_o is driven
module prim_generic_pad_wrapper
import prim_pad_wrapper_pkg::*;
#(
// These parameters are ignored in this model.
parameter pad_type_e PadType = BidirStd,
parameter scan_role_e ScanRole = NoScan
) (
// This is only used for scanmode (not used in generic models)
input clk_scan_i,
input scanmode_i,
// Power sequencing signals (not used in generic models)
input pad_pok_t pok_i,
// Main Pad signals
inout wire inout_io, // bidirectional pad
output logic in_o, // input data
output logic in_raw_o, // uninverted output data
input ie_i, // input enable
input out_i, // output data
input oe_i, // output enable
// additional attributes
input [AttrDw-1:0] attr_i,
output logic [AttrDw-1:0] warl_o
input pad_attr_t attr_i // additional pad attributes
);
// Supported attributes:
// [x] Bit 0: input/output inversion,
// [x] Bit 1: Virtual open drain enable.
// [x] Bit 2: Pull enable.
// [x] Bit 3: Pull select (0: pull down, 1: pull up).
// [x] Bit 4: Keeper enable.
// [ ] Bit 5: Schmitt trigger enable.
// [ ] Bit 6: Slew rate (0: slow, 1: fast).
// [x] Bit 7/8: Drive strength (00: weakest, 11: strongest).
// [ ] Bit 9: Reserved.
assign warl_o = AttrDw'(10'h19F);
// analog pads cannot have a scan role.
`ASSERT_INIT(AnalogNoScan_A, PadType != AnalogIn0 || ScanRole == NoScan)
if (WarlOnly) begin : gen_warl
assign inout_io = 1'bz;
assign in_o = 1'b0;
// not all signals are used here.
logic unused_sigs;
assign unused_sigs = ^{attr_i.slew_rate,
attr_i.drive_strength[3:1],
attr_i.od_en,
attr_i.schmitt_en,
scanmode_i,
pok_i};
logic [AttrDw-1:0] unused_attr;
logic unused_ie, unused_oe, unused_out, unused_inout;
assign unused_ie = ie_i;
assign unused_oe = oe_i;
assign unused_out = out_i;
assign unused_attr = attr_i;
assign unused_inout = inout_io;
end else begin : gen_pad
// get pad attributes
logic unused_sm, kp, unused_sr, ps, pe, od, inv;
typedef enum logic [1:0] {DRIVE_00 = 2'b00,
DRIVE_01 = 2'b01,
DRIVE_10 = 2'b10,
DRIVE_11 = 2'b11} drv_e;
drv_e drv;
assign {drv, unused_sr, unused_sm, kp, ps, pe, od, inv} = attr_i[8:0];
if (AttrDw > 9) begin : gen_unused_attr
logic [AttrDw-9-1:0] unused_attr;
assign unused_attr = attr_i[AttrDw-1:9];
end
if (PadType == InputStd) begin : gen_input_only
logic unused_in_sigs;
assign unused_in_sigs = ^{out_i,
oe_i,
attr_i.virt_od_en,
attr_i.drive_strength};
assign in_raw_o = (ie_i) ? inout_io : 1'bz;
// input inversion
logic in;
assign in = inv ^ inout_io;
assign in_o = attr_i.invert ^ in_raw_o;
// pulls are not supported by verilator
`ifndef VERILATOR
// pullup / pulldown termination
assign (weak0, weak1) inout_io = attr_i.pull_en ? attr_i.pull_select : 1'bz;
`endif
end else if (PadType == BidirTol ||
PadType == BidirOd ||
PadType == BidirStd) begin : gen_bidir
assign in_raw_o = (ie_i) ? inout_io : 1'bz;
// input inversion
assign in_o = attr_i.invert ^ in_raw_o;
// virtual open drain emulation
logic oe, out;
assign out = out_i ^ inv;
assign oe = oe_i & ((od & ~out) | ~od);
assign out = out_i ^ attr_i.invert;
assign oe = oe_i & ((attr_i.virt_od_en & ~out) | ~attr_i.virt_od_en);
// driving strength attributes are not supported by verilator
`ifdef VERILATOR
// drive strength attributes are not supported by verilator
`ifdef VERILATOR
assign inout_io = (oe) ? out : 1'bz;
// received data driver
assign in_o = (ie_i) ? in : 1'bz;
`else
`else
// different driver types
assign (strong0, strong1) inout_io = (oe && drv != DRIVE_00) ? out : 1'bz;
assign (pull0, pull1) inout_io = (oe && drv == DRIVE_00) ? out : 1'bz;
assign (strong0, strong1) inout_io = (oe && attr_i.drive_strength[0]) ? out : 1'bz;
assign (pull0, pull1) inout_io = (oe && !attr_i.drive_strength[0]) ? out : 1'bz;
// pullup / pulldown termination
assign (weak0, weak1) inout_io = pe ? ps : 1'bz;
assign (weak0, weak1) inout_io = attr_i.pull_en ? attr_i.pull_select : 1'bz;
// fake trireg emulation
assign (weak0, weak1) inout_io = (kp) ? inout_io : 1'bz;
// received data driver
assign in_o = (ie_i) ? in : 1'bz;
`endif
assign (weak0, weak1) inout_io = (attr_i.keep_en) ? inout_io : 1'bz;
`endif
end else if (PadType == AnalogIn0) begin : gen_analog0
logic unused_ana_sigs;
assign unused_ana_sigs = ^{attr_i, out_i, oe_i, ie_i};
assign in_o = inout_io;
assign in_raw_o = inout_io;
end else begin : gen_invalid_config
// this should throw link warnings in elaboration
assert_static_in_generate_config_not_available
assert_static_in_generate_config_not_available();
end
// assertions
`ASSERT_INIT(AttrDwCheck_A, AttrDw >= 9)
endmodule : prim_generic_pad_wrapper

View file

@ -24,9 +24,11 @@ module prim_generic_usb_diff_rx #(
logic unused_pullup_p_en, unused_pullup_n_en;
logic [CalibW-1:0] unused_calibration;
logic unused_core_pok;
assign unused_calibration = calibration_i;
assign unused_pullup_p_en = pullup_p_en_i;
assign unused_pullup_n_en = pullup_n_en_i;
assign unused_core_pok = core_pok_i;
endmodule : prim_generic_usb_diff_rx

View file

@ -0,0 +1,17 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`include "prim_assert.sv"
module prim_generic_xor2 #(
parameter int Width = 1
) (
input [Width-1:0] in0_i,
input [Width-1:0] in1_i,
output logic [Width-1:0] out_o
);
assign out_o = in0_i ^ in1_i;
endmodule

View file

@ -4,7 +4,7 @@ CAPI=2:
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:prim_xilinx:flop"
description: "generic flop"
description: "Xilinx flop"
filesets:
files_rtl:
files:

View file

@ -0,0 +1,39 @@
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_xilinx:flop_en"
description: "Xilinx enable flop"
filesets:
files_rtl:
files:
- rtl/prim_xilinx_flop_en.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -0,0 +1,44 @@
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_xilinx:pad_attr"
description: "Pad attribute WARL module for Xilinx pads"
filesets:
files_rtl:
depend:
- lowrisc:prim:assert
- lowrisc:prim:pad_wrapper_pkg
files:
- rtl/prim_xilinx_pad_attr.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
#- lint/prim_xilinx_pad_attr.vlt
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
#- lint/prim_xilinx_pad_attr.waiver
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -7,6 +7,9 @@ name: "lowrisc:prim_xilinx:pad_wrapper"
description: "prim"
filesets:
files_rtl:
depend:
- lowrisc:prim:assert
- lowrisc:prim:pad_wrapper_pkg
files:
- rtl/prim_xilinx_pad_wrapper.sv
file_type: systemVerilogSource

View file

@ -0,0 +1,39 @@
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_xilinx:xor2"
description: "Xilinx 2-input xor"
filesets:
files_rtl:
files:
- rtl/prim_xilinx_xor2.sv
file_type: systemVerilogSource
files_verilator_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: vlt
files_ascentlint_waiver:
depend:
# common waivers
- lowrisc:lint:common
files:
file_type: waiver
files_veriblelint_waiver:
depend:
# common waivers
- lowrisc:lint:common
targets:
default:
filesets:
- tool_verilator ? (files_verilator_waiver)
- tool_ascentlint ? (files_ascentlint_waiver)
- tool_veriblelint ? (files_veriblelint_waiver)
- files_rtl

View file

@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
module prim_xilinx_buf (
input in_i,
(* keep = "true" *) output logic out_o
module prim_xilinx_buf #(
parameter int Width = 1
) (
input [Width-1:0] in_i,
(* keep = "true" *) output logic [Width-1:0] out_o
);
assign out_o = in_i;
endmodule : prim_xilinx_buf
endmodule

View file

@ -8,8 +8,8 @@ module prim_xilinx_clock_buf (
);
BUFG bufg_i (
.I (clk_i),
.O (clk_o)
.I(clk_i),
.O(clk_o)
);
endmodule

View file

@ -15,9 +15,9 @@ module prim_xilinx_clock_gating #(
assign clk_o = clk_i;
end else begin : gen_gate
BUFGCE u_bufgce (
.I (clk_i),
.CE (en_i | test_en_i),
.O (clk_o)
.I (clk_i),
.CE(en_i | test_en_i),
.O (clk_o)
);
end

View file

@ -20,11 +20,11 @@ module prim_xilinx_clock_mux2 #(
// ug953-vivado-7series-libraries.pdf
// ug974-vivado-ultrascale-libraries.pdf
BUFGMUX bufgmux_i (
.S ( sel_i ),
.I0 ( clk0_i ),
.I1 ( clk1_i ),
.O ( clk_o )
);
.S (sel_i),
.I0(clk0_i),
.I1(clk1_i),
.O (clk_o)
);
end
// make sure sel is never X (including during reset)

View file

@ -4,10 +4,9 @@
`include "prim_assert.sv"
module prim_xilinx_flop # (
parameter int Width = 1,
localparam int WidthSubOne = Width-1,
parameter logic [WidthSubOne:0] ResetValue = 0
module prim_xilinx_flop #(
parameter int Width = 1,
parameter logic [Width-1:0] ResetValue = 0
) (
input clk_i,
input rst_ni,
@ -24,4 +23,4 @@ module prim_xilinx_flop # (
end
end
endmodule // prim_xilinx_flop
endmodule

View file

@ -0,0 +1,28 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`include "prim_assert.sv"
module prim_xilinx_flop_en #(
parameter int Width = 1,
parameter logic [Width-1:0] ResetValue = 0
) (
input clk_i,
input rst_ni,
// Prevent Vivado from optimizing this signal away.
(* keep = "true" *) input en_i,
input [Width-1:0] d_i,
// Prevent Vivado from optimizing this signal away.
(* keep = "true" *) output logic [Width-1:0] q_o
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
q_o <= ResetValue;
end else if (en_i) begin
q_o <= d_i;
end
end
endmodule

View file

@ -0,0 +1,54 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
`include "prim_assert.sv"
module prim_xilinx_pad_attr
import prim_pad_wrapper_pkg::*;
#(
// This parameter is ignored in this Xilinx variant.
parameter pad_type_e PadType = BidirStd
) (
output pad_attr_t attr_warl_o
);
// Currently supported pad attributes of the Xilinx pad library.
//
// Input-only:
//
// - inversion
//
// Bidirectional:
//
// - inversion
// - virtual open drain
//
if (PadType == InputStd) begin : gen_input_only_warl
always_comb begin : p_attr
attr_warl_o = '0;
attr_warl_o.invert = 1'b1;
end
end else if (PadType == BidirStd ||
PadType == BidirTol ||
PadType == BidirOd) begin : gen_bidir_warl
always_comb begin : p_attr
attr_warl_o = '0;
attr_warl_o.invert = 1'b1;
attr_warl_o.virt_od_en = 1'b1;
end
end else if (PadType == AnalogIn0) begin : gen_analog0_warl
// The analog pad type is basically just a feedthrough,
// and does hence not support any of the attributes.
always_comb begin : p_attr
attr_warl_o = '0;
end
end else begin : gen_invalid_config
// this should throw link warnings in elaboration
assert_static_in_generate_config_not_available
assert_static_in_generate_config_not_available();
end
endmodule : prim_xilinx_pad_attr

View file

@ -6,73 +6,100 @@
// virtual open drain feature.
module prim_xilinx_pad_wrapper #(
parameter int Variant = 0, // currently ignored
parameter int AttrDw = 10,
parameter bit WarlOnly = 0 // If set to 1, no pad is instantiated and only warl_o is driven
module prim_xilinx_pad_wrapper
import prim_pad_wrapper_pkg::*;
#(
// These parameters are ignored in this Xilinx variant.
parameter pad_type_e PadType = BidirStd,
parameter scan_role_e ScanRole = NoScan
) (
// This is only used for scanmode (not used in this Xilinx variant)
input clk_scan_i,
input scanmode_i,
// Power sequencing signals (not used in this Xilinx variant)
input pad_pok_t pok_i,
// Main Pad signals
inout wire inout_io, // bidirectional pad
output logic in_o, // input data
output logic in_raw_o, // uninverted output data
input ie_i, // input enable
input out_i, // output data
input oe_i, // output enable
// additional attributes
input [AttrDw-1:0] attr_i,
output logic [AttrDw-1:0] warl_o
input pad_attr_t attr_i // additional pad attributes
);
// Supported attributes:
// [x] Bit 0: input/output inversion,
// [x] Bit 1: Virtual open drain enable.
// [ ] Bit 2: Pull enable.
// [ ] Bit 3: Pull select (0: pull down, 1: pull up).
// [ ] Bit 4: Keeper enable.
// [ ] Bit 5: Schmitt trigger enable.
// [ ] Bit 6: Slew rate (0: slow, 1: fast).
// [ ] Bit 7/8: Drive strength (00: weakest, 11: strongest).
// [ ] Bit 9: Reserved.
assign warl_o = AttrDw'(2'h3);
// analog pads cannot have a scan role.
`ASSERT_INIT(AnalogNoScan_A, PadType != AnalogIn0 || ScanRole == NoScan)
if (WarlOnly) begin : gen_warl
assign inout_io = 1'bz;
assign in_o = 1'b0;
// not all signals are used here.
logic unused_sigs;
assign unused_sigs = ^{attr_i.slew_rate,
attr_i.drive_strength,
attr_i.od_en,
attr_i.schmitt_en,
attr_i.keep_en,
attr_i.pull_en,
attr_i.pull_select,
scanmode_i,
pok_i};
logic [AttrDw-1:0] unused_attr;
logic unused_ie, unused_oe, unused_out, unused_inout;
assign unused_ie = ie_i;
assign unused_oe = oe_i;
assign unused_out = out_i;
assign unused_attr = attr_i;
assign unused_inout = inout_io;
end else begin : gen_pad
// get pad attributes
logic od, inv;
assign {od, inv} = attr_i[1:0];
if (PadType == InputStd) begin : gen_input_only
logic unused_sigs;
assign unused_sigs = ^{out_i,
oe_i,
attr_i.virt_od_en};
if (AttrDw > 9) begin : gen_unused_attr
logic [AttrDw-9-1:0] unused_attr;
assign unused_attr = attr_i[AttrDw-1:9];
end
// input inversion and buffer
// input inversion
logic in;
assign in_o = (ie_i) ? inv ^ in : 1'bz;
assign in_raw_o = (ie_i) ? in : 1'bz;
assign in_o = attr_i.invert ^ in_raw_o;
IBUF u_ibuf (
.I ( inout_io ),
.O ( in )
);
end else if (PadType == BidirTol ||
PadType == BidirOd ||
PadType == BidirStd) begin : gen_bidir
// input inversion
logic in;
assign in_raw_o = (ie_i) ? in : 1'bz;
assign in_o = attr_i.invert ^ in_raw_o;
// virtual open drain emulation
logic oe_n, out;
assign out = out_i ^ inv;
assign out = out_i ^ attr_i.invert;
// oe_n = 0: enable driver
// oe_n = 1: disable driver
assign oe_n = ~oe_i | (out & od);
assign oe_n = ~oe_i | (out & attr_i.virt_od_en);
// driver
IOBUF i_iobuf (
IOBUF u_iobuf (
.T ( oe_n ),
.I ( out ),
.O ( in ),
.IO ( inout_io )
);
end else if (PadType == AnalogIn0) begin : gen_analog0
logic unused_sigs;
assign unused_sigs = ^{out_i,
oe_i,
attr_i.invert,
attr_i.virt_od_en};
// this is currently modeled as a logic feed through.
IBUF u_ibuf (
.I ( inout_io ),
.O ( in_raw_o )
);
assign in_raw_o = inout_io;
end else begin : gen_invalid_config
// this should throw link warnings in elaboration
assert_static_in_generate_config_not_available
assert_static_in_generate_config_not_available();
end
endmodule : prim_xilinx_pad_wrapper

View 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
`include "prim_assert.sv"
module prim_xilinx_xor2 #(
parameter int Width = 1
) (
input [Width-1:0] in0_i,
input [Width-1:0] in1_i,
// Prevent Vivado from optimizing this signal away.
(* keep = "true" *) output logic [Width-1:0] out_o
);
assign out_o = in0_i ^ in1_i;
endmodule

View file

@ -79,14 +79,14 @@ All three linting tools mentioned above have been integrated with the `dvsim` re
In order to manually invoke any of the linting tools on a specific block, make sure that the corresponding linting tool is properly installed, step into the project root and call
```console
$ cd $REPO_TOP
$ util/dvsim/dvsim.py hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson --tool (ascentlint|verilator|veriblelint) --purge --select-cfgs <lint-config-name>
$ util/dvsim/dvsim.py hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson --tool (ascentlint|verilator|veriblelint) --local --purge --select-cfgs <lint-config-name>
```
where `<lint-config-name>` is the name of the linting configuration as defined in the `top_earlgrey_lint_cfgs.hjson` regression list (currently that file contains a lint configuration for all available comportable IPs and the top-level).
In order to run all defined configs in `top_earlgrey_lint_cfgs.hjson` as a batch regression, just omit the `--select-cfgs` switch as follows:
```console
$ cd $REPO_TOP
$ util/dvsim/dvsim.py hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson --tool (ascentlint|verilator|veriblelint) --purge
$ util/dvsim/dvsim.py hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson --tool (ascentlint|verilator|veriblelint) --local --purge
```
The `purge` option ensures that the scratch directory is fully erased before starting the build.
Depending on the number of AscentLint licenses that can be checked out at a time, you may also want to set the number of parallel workers to one using `--max-parallel <number>`.

View file

@ -4,10 +4,7 @@
#
# OpenTitan-specific style lint rule configurations
# line length currently set to 150 to remove clutter in reports.
# set this back to 100 once we can waive this rule for generated
# files or once the file generators can respect this constraint
line-length=length:150
line-length=length:100
# we allow "classic" verilog string parameters without explicit type
explicit-parameter-storage-type=exempt_type:string

View file

@ -6,6 +6,7 @@ import logging as log
import pprint
import random
import shlex
from pathlib import Path
from LauncherFactory import get_launcher
from sim_utils import get_cov_summary_table
@ -143,8 +144,11 @@ class Deploy():
# 'aes:default', 'uart:default' builds.
self.full_name = self.sim_cfg.name + ":" + self.qual_name
# Job name is used to group the job by cfg and target.
self.job_name = "{}_{}".format(self.sim_cfg.name, self.target)
# Job name is used to group the job by cfg and target. The scratch path
# directory name is assumed to be uniquified, in case there are more
# than one sim_cfgs with the same name.
self.job_name = "{}_{}".format(
Path(self.sim_cfg.scratch_path).name, self.target)
# Input directories (other than self) this job depends on.
self.input_dirs = []
@ -203,9 +207,9 @@ class Deploy():
def _construct_cmd(self):
"""Construct the command that will eventually be launched."""
args = ["make", "-f", self.flow_makefile, self.target]
cmd = "make -f {} {}".format(self.flow_makefile, self.target)
if self.dry_run is True:
args += ["-n"]
cmd += " -n"
for attr in sorted(self.mandatory_cmd_attrs.keys()):
value = getattr(self, attr)
if type(value) is list:
@ -217,8 +221,8 @@ class Deploy():
value = int(value)
if type(value) is str:
value = value.strip()
args += ["{}={}".format(attr, shlex.quote(value))]
return " ".join(args)
cmd += " {}={}".format(attr, shlex.quote(value))
return cmd
def is_equivalent_job(self, item):
"""Checks if job that would be dispatched with 'item' is equivalent to
@ -316,8 +320,7 @@ class CompileSim(Deploy):
# 'build_mode' is used as a substitution variable in the HJson.
self.build_mode = self.name
self.job_name = "{}_{}_{}".format(self.sim_cfg.name, self.target,
self.build_mode)
self.job_name += f"_{self.build_mode}"
if self.sim_cfg.cov:
self.output_dirs += [self.cov_db_dir]
self.pass_patterns = self.build_pass_patterns
@ -362,9 +365,7 @@ class CompileOneShot(Deploy):
"report_opts": False
})
self.mandatory_misc_attrs.update({
"build_fail_patterns": False
})
self.mandatory_misc_attrs.update({"build_fail_patterns": False})
def _set_attrs(self):
super()._extract_attrs(self.build_mode_obj.__dict__)
@ -372,8 +373,7 @@ class CompileOneShot(Deploy):
# 'build_mode' is used as a substitution variable in the HJson.
self.build_mode = self.name
self.job_name = "{}_{}_{}".format(self.sim_cfg.name, self.target,
self.build_mode)
self.job_name += f"_{self.build_mode}"
self.fail_patterns = self.build_fail_patterns
@ -435,8 +435,7 @@ class RunTest(Deploy):
self.build_mode = self.test_obj.build_mode.name
self.qual_name = self.run_dir_name + "." + str(self.seed)
self.full_name = self.sim_cfg.name + ":" + self.qual_name
self.job_name = "{}_{}_{}".format(self.sim_cfg.name, self.target,
self.build_mode)
self.job_name += f"_{self.build_mode}"
if self.sim_cfg.cov:
self.output_dirs += [self.cov_db_test_dir]

View file

@ -12,6 +12,7 @@ from shutil import which
import hjson
from CfgJson import set_target_attribute
from LauncherFactory import get_launcher_cls
from Scheduler import Scheduler
from utils import (VERBOSE, find_and_substitute_wildcards, md_results_to_html,
rm_path, subst_wildcards)
@ -371,7 +372,7 @@ class FlowCfg():
log.fatal("Nothing to run!")
sys.exit(1)
return Scheduler(deploy).run()
return Scheduler(deploy, get_launcher_cls()).run()
def _gen_results(self, results):
'''

View file

@ -22,8 +22,15 @@ class FormalCfg(OneShotCfg):
super().__init__(flow_cfg_file, hjson_data, args, mk_config)
self.header = ["name", "errors", "warnings", "proven", "cex", "undetermined",
"covered", "unreachable", "pass_rate", "cov_rate"]
# Default not to publish child cfg results.
if "publish_report" in hjson_data:
self.publish_report = hjson_data["publish_report"]
else:
self.publish_report = False
self.sub_flow = hjson_data['sub_flow']
self.summary_header = ["name", "pass_rate", "stimuli_cov", "coi_cov", "prove_cov"]
self.results_title = self.name.upper() + " Formal Results"
self.results_title = self.name.upper() + " Formal " + self.sub_flow.upper() + " Results"
def parse_dict_to_str(self, input_dict, excl_keys = []):
# This is a helper function to parse dictionary items into a string.
@ -242,7 +249,7 @@ class FormalCfg(OneShotCfg):
}
}
results_str += "\n\n## Formal Results\n"
results_str += "\n\n## Formal " + self.sub_flow.upper() + " Results\n"
formal_result_str, formal_summary = self.get_summary(self.result)
results_str += formal_result_str
summary += formal_summary
@ -259,7 +266,7 @@ class FormalCfg(OneShotCfg):
if results[mode] != "P":
results_str += "\n## List of Failures\n" + ''.join(
mode.launcher.fail_msg)
mode.launcher.fail_msg.message)
messages = self.result.get("messages")
if messages is not None:
@ -278,9 +285,16 @@ class FormalCfg(OneShotCfg):
return self.results_md
def _publish_results(self):
'''This does nothing: detailed messages from the logfile are not published
Our agreement with tool vendors allows us to publish the summary
''' our agreement with tool vendors allows us to publish the summary
results (as in gen_results_summary).
In default this method does nothing: detailed messages from each child
cfg will not be published.
If the publish_report argument is set to true, this method will only
publish a result summary of the child cfg.
'''
return
if self.publish_report:
self.publish_results_md = self.gen_results_summary()
super()._publish_results()
else:
return

View file

@ -2,9 +2,11 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import collections
import logging as log
import os
import re
import sys
from pathlib import Path
from utils import VERBOSE, clean_odirs, rm_path
@ -15,6 +17,20 @@ class LauncherError(Exception):
self.msg = msg
class ErrorMessage(
collections.namedtuple(
'ErrorMessage',
['line_number', 'message', 'context'],
)):
"""Contains error-related information.
This support classification of failures into buckets. The message field
is used to generate the bucket, and context contains a list of lines in
the failing log that can be useful for quick diagnostics.
"""
pass
class Launcher:
"""
Abstraction for launching and maintaining a job.
@ -28,6 +44,15 @@ class Launcher:
# Type of launcher used as string.
variant = None
# Max jobs running at one time
max_parallel = sys.maxsize
# Max jobs polled at one time
max_poll = 10000
# Poll job's completion status every this many seconds
poll_freq = 1
# Points to the python virtual env area.
pyvenv = None
@ -119,11 +144,6 @@ class Launcher:
# create a new one.
self.renew_odir = False
# Error message if the job 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."""
@ -208,7 +228,8 @@ class Launcher:
Returns (status, err_msg) extracted from the log, where the status is
"P" if the it passed, "F" otherwise. This is invoked by poll() just
after the job finishes.
after the job finishes. err_msg is an instance of the named tuple
ErrorMessage.
"""
def _find_patterns(patterns, line):
"""Helper function that returns the pattern if any of the given
@ -221,18 +242,11 @@ class Launcher:
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 "P", None
# Only one fail pattern needs to be seen.
failed = False
chk_failed = bool(self.deploy.fail_patterns)
err_msg = None
# All pass patterns need to be seen, so we replicate the list and remove
# patterns as we encounter them.
@ -240,60 +254,57 @@ class Launcher:
chk_passed = bool(pass_patterns) and (self.exit_code == 0)
try:
with open(self.deploy.get_log_path(), "r", encoding="UTF-8",
with open(self.deploy.get_log_path(),
"r",
encoding="UTF-8",
errors="surrogateescape") as f:
lines = f.readlines()
except OSError as e:
err_msg = "Error opening file {}:\n{}".format(
self.deploy.get_log_path(), e)
return "F", err_msg
return "F", ErrorMessage(
line_number=None,
message="Error opening file {}:\n{}".format(
self.deploy.get_log_path(), e),
context=[],
)
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.
err_msg = "```\n{}\n```\n".format(_get_n_lines(cnt, 5))
failed = True
chk_failed = False
chk_passed = False
if _find_patterns(self.deploy.fail_patterns, line):
# If failed, then nothing else to do. Just return.
# Privide some extra lines for context.
return "F", ErrorMessage(line_number=cnt + 1,
message=line.strip(),
context=lines[cnt:cnt + 5])
if chk_passed:
pattern = _find_patterns(pass_patterns, line)
if pattern is not None:
if pattern:
pass_patterns.remove(pattern)
chk_passed = bool(pass_patterns)
# If failed, then nothing else to do. Just return.
if failed:
assert err_msg is not None
return "F", err_msg
# 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:
err_msg = ("Job returned non-zero exit code:\nLast 10 lines:\n"
"```\n{}\n```\n")
err_msg = err_msg.format(''.join(lines[-10:]).strip())
return "F", err_msg
# Ensure all pass patterns were seen.
return "F", ErrorMessage(line_number=None,
message="Job returned non-zero exit code",
context=lines[-10:])
if chk_passed:
err_msg = ("Some pass patterns missing:\n{}\nLast 10 lines:\n"
"```\n{}\n```\n")
err_msg = err_msg.format(pass_patterns,
''.join(lines[-10:]).strip())
return "F", err_msg
assert err_msg is None
return "F", ErrorMessage(
line_number=None,
message=f"Some pass patterns missing: {pass_patterns}",
context=lines[-10:],
)
return "P", None
def _post_finish(self, status, err_msg):
"""Do post-completion activities, such as preparing the results.
Must be invoked by poll(), after the job outcome is determined.
status is the status of the job, either 'P', 'F' or 'K'.
err_msg is an instance of the named tuple ErrorMessage.
"""
assert status in ['P', 'F', 'K']
@ -302,14 +313,6 @@ class Launcher:
self.deploy.post_finish(status)
log.debug("Item %s has completed execution: %s", self, status)
if status != "P":
self._log_fail_msg(err_msg)
def _log_fail_msg(self, msg):
"""Logs the fail msg for the final report.
Invoked in _post_finish() only if the job did not pass.
"""
assert msg is not None
self.fail_msg += msg
log.log(VERBOSE, msg)
assert err_msg and isinstance(err_msg, ErrorMessage)
self.fail_msg = err_msg
log.log(VERBOSE, err_msg.message)

View file

@ -4,21 +4,19 @@
import logging as log
import os
import sys
from Launcher import Launcher
from LocalLauncher import LocalLauncher
from LsfLauncher import LsfLauncher
from Scheduler import Scheduler
try:
from EdaCloudLauncher import EdaCloudLauncher
from edacloudlauncher.EdaCloudLauncher import EdaCloudLauncher
EDACLOUD_LAUNCHER_EXISTS = True
except ImportError:
EDACLOUD_LAUNCHER_EXISTS = False
# The chosen launcher class.
launcher_cls = None
_LAUNCHER_CLS = None
def set_launcher_type(is_local=False):
@ -36,29 +34,29 @@ def set_launcher_type(is_local=False):
launcher = "local"
Launcher.variant = launcher
global launcher_cls
global _LAUNCHER_CLS
if launcher == "local":
launcher_cls = LocalLauncher
_LAUNCHER_CLS = LocalLauncher
elif launcher == "lsf":
launcher_cls = LsfLauncher
# The max_parallel setting is not relevant when dispatching with LSF.
Scheduler.max_parallel = sys.maxsize
_LAUNCHER_CLS = LsfLauncher
# These custom launchers are site specific. They may not be committed to
# the open source repo.
elif launcher == "edacloud" and EDACLOUD_LAUNCHER_EXISTS:
launcher_cls = EdaCloudLauncher
# The max_parallel setting is not relevant when dispatching with
# EDACloud.
Scheduler.max_parallel = sys.maxsize
_LAUNCHER_CLS = EdaCloudLauncher
else:
log.error("Launcher {} set using DVSIM_LAUNCHER env var does not "
"exist. Using local launcher instead.".format(launcher))
launcher_cls = LocalLauncher
_LAUNCHER_CLS = LocalLauncher
def get_launcher_cls():
'''Returns the chosen launcher class.'''
assert _LAUNCHER_CLS is not None
return _LAUNCHER_CLS
def get_launcher(deploy):
@ -67,6 +65,5 @@ def get_launcher(deploy):
'deploy' is an instance of the deploy class to with the launcher is paired.
'''
global launcher_cls
assert launcher_cls is not None
return launcher_cls(deploy)
assert _LAUNCHER_CLS is not None
return _LAUNCHER_CLS(deploy)

View file

@ -6,7 +6,7 @@ import os
import shlex
import subprocess
from Launcher import Launcher, LauncherError
from Launcher import ErrorMessage, Launcher, LauncherError
class LocalLauncher(Launcher):
@ -42,7 +42,6 @@ class LocalLauncher(Launcher):
self._dump_env_vars(exports)
args = shlex.split(self.deploy.cmd)
try:
f = open(self.deploy.get_log_path(),
"w",
@ -50,7 +49,7 @@ class LocalLauncher(Launcher):
errors="surrogateescape")
f.write("[Executing]:\n{}\n\n".format(self.deploy.cmd))
f.flush()
self.process = subprocess.Popen(args,
self.process = subprocess.Popen(shlex.split(self.deploy.cmd),
bufsize=4096,
universal_newlines=True,
stdout=f,
@ -100,7 +99,9 @@ class LocalLauncher(Launcher):
except subprocess.TimeoutExpired:
self.process.kill()
self._post_finish('K', 'Job killed!')
self._post_finish('K', ErrorMessage(line_number=None,
message='Job killed!',
context=[]))
def _post_finish(self, status, err_msg):
super()._post_finish(status, err_msg)

View file

@ -9,7 +9,7 @@ import subprocess
import tarfile
from pathlib import Path
from Launcher import Launcher, LauncherError
from Launcher import ErrorMessage, Launcher, LauncherError
from utils import VERBOSE, clean_odirs
@ -264,7 +264,11 @@ class LsfLauncher(Launcher):
except IOError as e:
self._post_finish(
"F",
"ERROR: Failed to open {}\n{}.".format(self.bsub_out, e))
ErrorMessage(
line_number=None,
message="ERROR: Failed to open {}\n{}.".format(
self.bsub_out, e),
context=[]))
return "F"
# Now that the job has completed, we need to determine its status.
@ -299,7 +303,9 @@ class LsfLauncher(Launcher):
status, err_msg = self._check_status()
# Prioritize error messages from bsub over the job's log file.
if self.bsub_out_err_msg:
err_msg = self.bsub_out_err_msg
err_msg = ErrorMessage(line_number=None,
message=self.bsub_out_err_msg,
context=[])
self._post_finish(status, err_msg)
return status
@ -396,4 +402,6 @@ class LsfLauncher(Launcher):
err_msg is the error message indicating the cause of failure.'''
for job in LsfLauncher.jobs[cfg][job_name]:
job._post_finish("F", err_msg)
job._post_finish("F", ErrorMessage(line_number=None,
message=err_msg,
context=[]))

View file

@ -19,13 +19,35 @@ def sum_dict_lists(d):
return sum([len(d[k]) for k in d])
def get_next_item(arr, index):
'''Perpetually get an item from a list.
Returns the next item on the list by advancing the index by 1. If the index
is already the last item on the list, it loops back to the start, thus
implementing a circular list.
arr is a subscriptable list.
index is the index of the last item returned.
Returns (item, index) if successful.
Raises IndexError if arr is empty.
'''
index += 1
try:
item = arr[index]
except IndexError:
index = 0
try:
item = arr[index]
except IndexError:
raise IndexError("List is empty!")
return item, index
class Scheduler:
'''An object that runs one or more Deploy items'''
# Max jobs running at one time
max_parallel = 16
def __init__(self, items):
def __init__(self, items, launcher_cls):
self.items = items
# 'scheduled[target][cfg]' is a list of Deploy objects for the chosen
@ -48,19 +70,29 @@ class Scheduler:
# _queued is a list so that we dispatch things in order (relevant
# for things like tests where we have ordered things cleverly to
# try to see failures early). They are maintained for each target.
# The list of available targets and the list of running items in each
# target are polled in a circular fashion, looping back to the start.
# This is done to allow us to poll a smaller subset of jobs rather than
# the entire regression. We keep rotating through our list of running
# items, picking up where we left off on the last poll.
self._targets = list(self._scheduled.keys())
self._queued = {}
self._running = {}
self._passed = {}
self._failed = {}
self._killed = {}
self._total = {}
self.last_target_polled_idx = -1
self.last_item_polled_idx = {}
for target in self._scheduled:
self._queued[target] = []
self._running[target] = set()
self._running[target] = []
self._passed[target] = set()
self._failed[target] = set()
self._killed[target] = set()
self._total[target] = sum_dict_lists(self._scheduled[target])
self.last_item_polled_idx[target] = -1
# Stuff for printing the status.
width = len(str(self._total[target]))
@ -76,6 +108,10 @@ class Scheduler:
# per-target.
self.item_to_status = {}
# The chosen launcher class. This allows us to access launcher
# variant-specific settings such as max parallel jobs & poll rate.
self.launcher_cls = launcher_cls
def run(self):
'''Run all scheduled jobs and return the results.
@ -122,7 +158,8 @@ class Scheduler:
# polling loop. But we do it with a bounded wait on stop_now so
# that we jump back to the polling loop immediately on a
# signal.
stop_now.wait(timeout=1)
stop_now.wait(timeout=self.launcher_cls.poll_freq)
finally:
signal(SIGINT, old_handler)
@ -302,50 +339,61 @@ class Scheduler:
Returns True if something changed.
'''
max_poll = min(self.launcher_cls.max_poll,
sum_dict_lists(self._running))
# If there are no jobs running, we are likely done (possibly because
# of a SIGINT). Since poll() was called anyway, signal that something
# has indeed changed.
if not max_poll:
return True
changed = False
for target in self._scheduled:
to_pass = []
to_fail = []
for item in self._running[target]:
while max_poll:
target, self.last_target_polled_idx = get_next_item(
self._targets, self.last_target_polled_idx)
while self._running[target] and max_poll:
max_poll -= 1
item, self.last_item_polled_idx[target] = get_next_item(
self._running[target], self.last_item_polled_idx[target])
status = item.launcher.poll()
assert status in ['D', 'P', 'F']
level = VERBOSE
assert status in ['D', 'P', 'F', 'K']
if status == 'D':
# Still running
continue
elif status == 'P':
log.log(VERBOSE, "[%s]: [%s]: [status] [%s: P]", hms,
target, item.full_name)
to_pass.append(item)
self._passed[target].add(item)
elif status == 'F':
self._failed[target].add(item)
level = log.ERROR
else:
log.error("[%s]: [%s]: [status] [%s: F]", hms, target,
item.full_name)
to_fail.append(item)
self._killed[target].add(item)
level = log.ERROR
for item in to_pass:
self._passed[target].add(item)
self._running[target].remove(item)
self.item_to_status[item] = 'P'
self._enqueue_successors(item)
self._running[target].pop(self.last_item_polled_idx[target])
self.last_item_polled_idx[target] -= 1
self.item_to_status[item] = status
log.log(level, "[%s]: [%s]: [status] [%s: %s]", hms, target,
item.full_name, status)
for item in to_fail:
self._failed[target].add(item)
self._running[target].remove(item)
self.item_to_status[item] = 'F'
# Enqueue item's successors regardless of its status.
#
# It may be possible that a failed item's successor may not
# need all of its dependents to pass (if it has other dependent
# jobs). Hence we enqueue all successors rather than canceling
# them right here. We leave it to `_dispatch()` to figure out
# them right here. We leave it to _dispatch() to figure out
# whether an enqueued item can be run or not.
self._enqueue_successors(item)
changed = changed or to_pass or to_fail
changed = True
return changed
def _dispatch(self, hms):
'''Dispatch some queued items if possible.'''
slots = Scheduler.max_parallel - sum_dict_lists(self._running)
slots = self.launcher_cls.max_parallel - sum_dict_lists(self._running)
if slots <= 0:
return
@ -404,7 +452,7 @@ class Scheduler:
", ".join(item.full_name for item in to_dispatch))
for item in to_dispatch:
self._running[target].add(item)
self._running[target].append(item)
self.item_to_status[item] = 'D'
try:
item.launcher.launch()
@ -423,7 +471,7 @@ class Scheduler:
# Kill any running items. Again, take a copy of the set to avoid
# modifying it while iterating over it.
for target in self._queued:
for target in self._running:
for item in [item for item in self._running[target]]:
self._kill_item(item)

View file

@ -5,6 +5,7 @@ r"""
Class describing simulation configuration object
"""
import collections
import logging as log
import os
import shutil
@ -15,12 +16,18 @@ from collections import OrderedDict
from Deploy import CompileSim, CovAnalyze, CovMerge, CovReport, CovUnr, RunTest
from FlowCfg import FlowCfg
from Modes import BuildModes, Modes, Regressions, RunModes, Tests
from SimResults import SimResults
from tabulate import tabulate
from testplanner.class_defs import Testplan, TestResult
from testplanner.class_defs import Testplan
from testplanner.testplan_utils import parse_testplan
from utils import VERBOSE, rm_path
# This affects the bucketizer failure report.
_MAX_UNIQUE_TESTS = 5
_MAX_TEST_RESEEDS = 2
def pick_wave_format(fmts):
'''Pick a supported wave format from a list.
@ -41,46 +48,6 @@ def pick_wave_format(fmts):
return fmt
class Results:
'''An object wrapping up a table of results for some tests
self.table is a list of TestResult objects, each of which
corresponds to one or more runs of the test with a given name.
self.fail_msgs is a list of error messages, one per failing run.
'''
def __init__(self, items, results):
self.table = []
self.fail_msgs = []
self._name_to_row = {}
for item in items:
self._add_item(item, results)
def _add_item(self, item, results):
'''Recursively add a single item to the table of results'''
status = results[item]
if status == "F":
self.fail_msgs.append(item.launcher.fail_msg)
# Runs get added to the table directly
if item.target == "run":
self._add_run(item, status)
def _add_run(self, item, status):
'''Add an entry to table for item'''
row = self._name_to_row.get(item.name)
if row is None:
row = TestResult(item.name)
self.table.append(row)
self._name_to_row[item.name] = row
if status == 'P':
row.passing += 1
row.total += 1
class SimCfg(FlowCfg):
"""Simulation configuration object
@ -576,13 +543,69 @@ class SimCfg(FlowCfg):
is enabled, then the summary coverage report is also generated. The final
result is in markdown format.
'''
def indent_by(level):
return " " * (4 * level)
def create_failure_message(test, line, context):
message = [f"{indent_by(2)}* {test.qual_name}\\"]
if line:
message.append(
f"{indent_by(2)} Line {line}, in log " +
test.get_log_path())
else:
message.append(f"{indent_by(2)} Log {test.get_log_path()}")
if context:
message.append("")
lines = [f"{indent_by(4)}{c.rstrip()}" for c in context]
message.extend(lines)
message.append("")
return message
def create_bucket_report(buckets):
"""Creates a report based on the given buckets.
The buckets are sorted by descending number of failures. Within
buckets this also group tests by unqualified name, and just a few
failures are shown per unqualified name.
Args:
buckets: A dictionary by bucket containing triples
(test, line, context).
Returns:
A list of text lines for the report.
"""
by_tests = sorted(buckets.items(),
key=lambda i: len(i[1]),
reverse=True)
fail_msgs = ["\n## Failure Buckets", ""]
for bucket, tests in by_tests:
fail_msgs.append(f"* `{bucket}` has {len(tests)} failures:")
unique_tests = collections.defaultdict(list)
for (test, line, context) in tests:
unique_tests[test.name].append((test, line, context))
for name, test_reseeds in list(unique_tests.items())[
:_MAX_UNIQUE_TESTS]:
fail_msgs.append(f"{indent_by(1)}* Test {name} has "
f"{len(test_reseeds)} failures.")
for test, line, context in test_reseeds[:_MAX_TEST_RESEEDS]:
fail_msgs.extend(
create_failure_message(test, line, context))
if len(test_reseeds) > _MAX_TEST_RESEEDS:
fail_msgs.append(
f"{indent_by(2)}* ... and "
f"{len(test_reseeds) - _MAX_TEST_RESEEDS} "
"more failures.")
if len(unique_tests) > _MAX_UNIQUE_TESTS:
fail_msgs.append(
f"{indent_by(1)}* ... and "
f"{len(unique_tests) - _MAX_UNIQUE_TESTS} more tests.")
fail_msgs.append("")
return fail_msgs
deployed_items = self.deploy
results = Results(deployed_items, run_results)
# Set a flag if anything failed
if results.fail_msgs:
self.errors_seen = True
results = SimResults(deployed_items, run_results)
# Generate results table for runs.
results_str = "## " + self.results_title + "\n"
@ -616,7 +639,7 @@ class SimCfg(FlowCfg):
results_str += "\n"
self.results_summary = self.testplan.results_summary
# Append coverage results of coverage was enabled.
# Append coverage results if coverage was enabled.
if self.cov_report_deploy is not None:
report_status = run_results[self.cov_report_deploy]
if report_status == "P":
@ -640,10 +663,9 @@ class SimCfg(FlowCfg):
self.results_summary["Name"] = self._get_results_page_link(
self.results_summary["Name"])
# Append failures for triage
if results.fail_msgs:
fail_msgs = "\n## List of Failures\n" + ''.join(results.fail_msgs)
results_str += fail_msgs
if results.buckets:
self.errors_seen = True
results_str += "\n".join(create_bucket_report(results.buckets))
self.results_md = results_str
@ -657,32 +679,45 @@ class SimCfg(FlowCfg):
return results_str
def gen_results_summary(self):
'''Generate the summary results table.
# sim summary result has 5 columns from each SimCfg.results_summary
header = ["Name", "Passing", "Total", "Pass Rate"]
if self.cov_report_deploy is not None:
header.append('Coverage')
table = []
colalign = ("center", ) * len(header)
for item in self.cfgs:
row = []
for title in item.results_summary:
row.append(item.results_summary[title])
if row:
table.append(row)
self.results_summary_md = "## " + self.results_title + " (Summary)\n"
self.results_summary_md += "### " + self.timestamp_long + "\n"
This method is specific to the primary cfg. It summarizes the results
from each individual cfg in a markdown table.
Prints the generated summary markdown text to stdout and returns it.
'''
lines = [f"## {self.results_title} (Summary)"]
lines += [f"### {self.timestamp_long}"]
if self.revision:
self.results_summary_md += "### " + self.revision + "\n"
self.results_summary_md += "### Branch: " + self.branch + "\n"
if table:
self.results_summary_md += tabulate(table,
headers=header,
tablefmt="pipe",
colalign=colalign)
else:
self.results_summary_md += "\nNo results to display.\n"
lines += [f"### {self.revision}"]
lines += [f"### Branch: {self.branch}"]
table = []
header = []
for cfg in self.cfgs:
row = cfg.results_summary.values()
if row:
# If header is set, ensure its the same for all cfgs.
if header:
assert header == cfg.results_summary.keys()
else:
header = cfg.results_summary.keys()
table.append(row)
if table:
assert header
colalign = ("center", ) * len(header)
table_txt = tabulate(table,
headers=header,
tablefmt="pipe",
colalign=colalign)
lines += ["", table_txt, ""]
else:
lines += ["\nNo results to display.\n"]
self.results_summary_md = "\n".join(lines)
print(self.results_summary_md)
return self.results_summary_md

Some files were not shown because too many files have changed in this diff Show more