URL
https://opencores.org/ocsvn/openhmc/openhmc/trunk
Subversion Repositories openhmc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openhmc
- from Rev 14 to Rev 15
- ↔ Reverse comparison
Rev 14 → Rev 15
/trunk/openHMC/rtl/include/hmc_field_functions.h
73,17 → 73,41
end |
endfunction |
|
function is_flow; |
function is_req_flow; |
input [127:0] flit; |
begin |
if(flit[5:3]) begin |
is_flow = 0; |
//according to spec it should check for bits [5:2]. However, all regular requests have bit 3,4 or 5 set so we reduce logic by checking only these |
if(flit[5:3]) begin |
is_req_flow = 0; |
end else begin |
is_flow = 1; |
is_req_flow = 1; |
end |
end |
endfunction |
|
function is_rsp_flow; |
input [127:0] flit; |
begin |
//according to spec it should check for bits [5:2]. However, all responses have bit 5 set so we reduce logic by only checking this single bit |
if(flit[5]) begin |
is_rsp_flow = 0; |
end else begin |
is_rsp_flow = 1; |
end |
end |
endfunction |
|
function lng_dln_equal; |
input [127:0] flit; |
begin |
if(!(lng(flit)^dln(flit))) begin |
lng_dln_equal = 1; |
end else begin |
lng_dln_equal = 0; |
end |
end |
endfunction |
|
function irtry_start_retry_flag; |
input [127:0] flit; |
|
/trunk/openHMC/rtl/building_blocks/counter/counter48.v
File deleted
\ No newline at end of file
/trunk/openHMC/rtl/building_blocks/counter/openhmc_counter48_wrapper_xilinx.v
0,0 → 1,171
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_counter48_wrapper_xilinx |
*/ |
|
`default_nettype none |
|
module openhmc_counter48_wrapper_xilinx #( |
parameter DATASIZE = 48, // width of the counter, must be <=48 bits! |
parameter INC_SIZE = 1, // must be <= 18bits |
parameter PIPELINED = 1 |
) ( |
input wire clk, |
input wire res_n, |
input wire [INC_SIZE-1:0] inc_value, |
output wire [DATASIZE-1:0] value |
); |
|
`ifdef SIMULATION |
initial |
begin |
if (DATASIZE > 48) |
begin |
$display ("unsupported DATASIZE parameter in counter48.\nMax value is 48, actual value is %2d", DATASIZE); |
$stop; |
end |
end |
`endif |
|
wire [47:0] value_w; |
|
DSP48E1 #( |
.ACASCREG(0), // Number of pipeline registers between A/ACIN input and ACOUT output, |
// 0, 1, or 2 |
.ADREG(PIPELINED), // Number of pipeline registers on pre-adder output, 0 or 1 |
.ALUMODEREG(PIPELINED), // Number of pipeline registers on ALUMODE input, 0 or 1 |
.AREG(0), // Number of pipeline registers on the A input, 0, 1 or 2 |
.AUTORESET_PATDET("NO_RESET"), // NO_RESET, RESET_MATCH, RESET_NOT_MATCH |
.A_INPUT("DIRECT"), // Selects A input used, "DIRECT" (A port) or "CASCADE" (ACIN port) |
.BCASCREG(PIPELINED), // Number of pipeline registers between B/BCIN input and BCOUT output, |
// 0, 1, or 2 |
.BREG(PIPELINED), // Number of pipeline registers on the B input, 0, 1 or 2 |
.B_INPUT("DIRECT"), // Selects B input used, "DIRECT" (B port) or "CASCADE" (BCIN port) |
.CARRYINREG(1), // Number of pipeline registers for the CARRYIN input, 0 or 1 |
.CARRYINSELREG(1), // Number of pipeline registers for the CARRYINSEL input, 0 or 1 |
.CREG(0), // Number of pipeline registers on the C input, 0 or 1 |
.DREG(0), // Number of pipeline registers on the D input, 0 or 1 |
.INMODEREG(1), // Number of pipeline registers on INMODE input, 0 or 1 |
.MASK(48'h3fffffffffff), // 48-bit Mask value for pattern detect |
.MREG(0), // Number of multiplier pipeline registers, 0 or 1 |
.OPMODEREG(1), // Number of pipeline registers on OPMODE input, 0 or 1 |
.PATTERN(48'h000000000000), // 48-bit Pattern match for pattern detect |
.PREG(1), // Number of pipeline registers on the P output, 0 or 1 |
.SEL_MASK("MASK"), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2" |
.SEL_PATTERN("PATTERN"), // Select pattern value between the "PATTERN" value or the value on the |
// "C" port |
.USE_DPORT("FALSE"), // Select D port usage, TRUE or FALSE |
.USE_MULT("NONE"), // Select multiplier usage, "MULTIPLY", "DYNAMIC", or "NONE" (no multiplier) |
.USE_PATTERN_DETECT("NO_PATDET"), // Enable pattern detect, "PATDET", "NO_PATDET" |
.USE_SIMD("ONE48") // SIMD selection, "ONE48", "TWO24", "FOUR12" |
) DSP48E1_inst ( |
// Cascade: 30-bit (each) Cascade |
.ACOUT(), // 30-bit A port cascade output |
.BCOUT(), // 18-bit B port cascade output |
.CARRYCASCOUT(), // 1-bit cascade carry output |
.MULTSIGNOUT(), // 1-bit multiplier sign cascade output |
.PCOUT(), // 48-bit cascade output |
// Control: 1-bit (each) Control |
.OVERFLOW(), // 1-bit overflow in add/acc output |
.PATTERNBDETECT(), // 1-bit active high pattern bar detect output |
.PATTERNDETECT(), // 1-bit active high pattern detect output |
.UNDERFLOW(), // 1-bit active high underflow in add/acc output |
// Data: 4-bit (each) Data |
.CARRYOUT(), // 4-bit carry output |
.P(value_w), // 48-bit output |
// Cascade: 30-bit (each) Cascade |
.ACIN(30'b0), // 30-bit A cascade data input |
.BCIN(18'b0), // 18-bit B cascade input |
.CARRYCASCIN(1'b0), // 1-bit cascade carry input |
.MULTSIGNIN(1'b0), // 1-bit multiplier sign input |
.PCIN(48'b0), // 48-bit P cascade input |
// Control: 4-bit (each) Control |
.ALUMODE(4'b0000), // 4-bit ALU control input |
.CARRYINSEL(3'b000), // 3-bit carry select input |
.CEINMODE(1'b0), // 1-bit active high clock enable input for INMODE registers |
.CLK(clk), // 1-bit Clock input |
.INMODE(5'b00000), // 5-bit INMODE control input |
.OPMODE({1'b0, 1'b1, 1'b0, 4'b0011}), // 7-bit operation mode input |
.RSTINMODE(!res_n), // 1-bit reset input for INMODE pipeline registers |
// Data: 30-bit (each) Data |
.A(30'b0), // 30-bit A data input |
.B({{18-INC_SIZE{1'b0}}, inc_value}), // 18-bit B data input |
.C(48'h0), // 48-bit C data input |
.CARRYIN(1'b0), // 1-bit carry input signal |
.D(25'b0), // 25-bit D data input |
// Reset/Clock Enable: 1-bit (each) Reset/Clock Enable |
.CEA1(1'b0), // 1-bit active high clock enable input for 1st stage A registers |
.CEA2(1'b0), // 1-bit active high clock enable input for 2nd stage A registers |
.CEAD(1'b0), // 1-bit active high clock enable input for pre-adder output registers |
.CEALUMODE(1'b1), // 1-bit active high clock enable input for ALUMODE registers |
.CEB1(1'b0), // 1-bit active high clock enable input for 1st stage B registers |
.CEB2(1'b1), // 1-bit active high clock enable input for 2nd stage B registers |
.CEC(1'b0), // 1-bit active high clock enable input for C registers |
.CECARRYIN(1'b0), // 1-bit active high clock enable input for CARRYIN register |
.CECTRL(1'b1), // 1-bit active high clock enable input for OPMODE and carry registers |
.CED(1'b0), // 1-bit active high clock enable input for D registers |
.CEM(1'b0), // 1-bit active high clock enable input for multiplier registers |
.CEP(1'b1), // 1-bit active high clock enable input for P registers |
.RSTA(1'b0), // 1-bit reset input for A pipeline registers |
.RSTALLCARRYIN(1'b0), // 1-bit reset input for carry pipeline registers |
.RSTALUMODE(1'b0), // 1-bit reset input for ALUMODE pipeline registers |
.RSTB(!res_n), // 1-bit reset input for B pipeline registers |
.RSTC(1'b0), // 1-bit reset input for C pipeline registers |
.RSTCTRL(!res_n), // 1-bit reset input for OPMODE pipeline registers |
.RSTD(1'b0), // 1-bit reset input for D pipeline registers |
.RSTM(1'b0), // 1-bit reset input for multiplier registers |
.RSTP(!res_n) // 1-bit reset input for P pipeline registers |
); |
|
|
|
generate |
if(PIPELINED==1) begin |
reg [DATASIZE-1:0] value_temp; |
always @(posedge clk) begin |
value_temp <= value_w[DATASIZE-1:0]; |
end |
assign value=value_temp; |
end else begin |
assign value = value_w[DATASIZE-1:0]; |
end |
endgenerate |
|
endmodule |
|
`default_nettype wire |
/trunk/openHMC/rtl/building_blocks/counter/openhmc_counter48.v
0,0 → 1,82
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_counter48 |
* |
*/ |
|
`default_nettype none |
|
module openhmc_counter48 #( |
parameter DATASIZE = 16 // width of the counter, must be <=48 bits! |
) ( |
input wire clk, |
input wire res_n, |
input wire increment, |
input wire load_enable, |
output wire [DATASIZE-1:0] value |
); |
|
reg [DATASIZE-1:0] value_reg; |
reg load_enable_reg; |
|
assign value = value_reg; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
if(!res_n) begin |
value_reg <= {DATASIZE{1'b0}}; |
load_enable_reg <= 1'b0; |
end else begin |
load_enable_reg <= load_enable; |
case ({load_enable_reg,increment}) |
2'b00: |
value_reg <= value_reg; |
2'b01: |
value_reg <= (value_reg + 1'b1); |
2'b10: |
value_reg <= {DATASIZE{1'b0}}; |
2'b11: |
value_reg <= {DATASIZE{1'b0}} + 1'b1; |
endcase |
end |
end |
|
endmodule |
`default_nettype wire |
/trunk/openHMC/rtl/building_blocks/rams/openhmc_ram.v
44,7 → 44,7
module openhmc_ram #( |
parameter DATASIZE = 78, // Memory data word width |
parameter ADDRSIZE = 9, // Number of memory address bits |
parameter PIPELINED = 0 |
parameter PIPELINED = 0 |
) ( |
//---------------------------------- |
//----SYSTEM INTERFACE |
93,12 → 93,11
endgenerate |
|
reg [DATASIZE-1:0] MEM [0:(2**ADDRSIZE)-1]; |
|
reg [DATASIZE-1:0] data_out; |
|
assign rdata_ram = data_out; |
|
|
|
always @(posedge clk) |
begin |
if (wen) |
/trunk/openHMC/rtl/building_blocks/fifos/sync/openhmc_sync_fifos.f
1,2 → 1,3
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/openhmc_sync_fifo.v |
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/openhmc_sync_fifo_reg_stage.v |
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/openhmc_sync_fifo_reg_stage.v |
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/openhmc_sync_fifo_reg_based.v |
/trunk/openHMC/rtl/building_blocks/fifos/sync/openhmc_sync_fifo_reg_based.v
0,0 → 1,200
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_sync_fifo_reg_based |
* |
*/ |
|
`default_nettype none |
|
module openhmc_sync_fifo_reg_based #( |
`ifdef CAG_ASSERTIONS |
parameter DISABLE_EMPTY_ASSERT = 0, |
parameter DISABLE_FULL_ASSERT = 0, |
parameter DISABLE_SHIFT_OUT_ASSERT = 0, |
parameter DISABLE_XCHECK_ASSERT = 0, |
`endif |
parameter DWIDTH = 8, |
parameter ENTRIES = 4 |
) ( |
input wire clk, |
input wire res_n, |
input wire shift_in, |
input wire shift_out, |
input wire [DWIDTH-1:0] d_in, |
|
output wire[DWIDTH-1:0] d_out, |
output reg full, |
output reg empty, |
output reg almost_full, |
output reg almost_empty |
); |
|
//the fifo_reg can currently only have up to 2047 entries |
localparam LG_ENTRIES = (ENTRIES <= 2) ? 1 : |
(ENTRIES <= 4) ? 2 : |
(ENTRIES <= 8) ? 3 : |
(ENTRIES <= 16) ? 4 : |
(ENTRIES <= 32) ? 5 : |
(ENTRIES <= 64) ? 6 : 7; |
|
reg [DWIDTH-1:0] entry [0:ENTRIES-1]; |
reg [LG_ENTRIES:0] wp; |
|
integer i; |
|
wire shiftout_clean, shiftin_clean; |
|
// first stage of fifo is output |
assign d_out = entry[0]; |
|
assign shiftout_clean = shift_out && !empty; |
assign shiftin_clean = shift_in && !full; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
|
if(!res_n) begin |
wp <= {LG_ENTRIES+1 {1'b0}}; |
full <= 1'b0; |
empty <= 1'b1; |
almost_empty <= 1'b1; |
almost_full <= 1'b0; |
`ifdef FULL_RES |
for (i=0; i<ENTRIES; i=i+1) |
entry[i] <= {DWIDTH {1'b0}}; |
`endif |
end else begin |
case ({shiftin_clean, shiftout_clean}) |
2'b01: // only shift-out, move entries, decrement WP if not already 0 and check status signals |
begin |
for (i=1; i<ENTRIES; i=i+1) |
entry[i-1] <= entry[i]; |
|
if (|wp) |
wp <= wp - 1'b1; |
|
empty <= (wp == {{LG_ENTRIES {1'b0}}, 1'b1}); |
full <= 1'b0; |
almost_full <= (wp >= ENTRIES+1-1); |
almost_empty <= (wp < 1 + 2); |
end |
|
2'b10: // only shift-in, write at next free entry, increment WP and check status signals |
begin |
entry[wp[LG_ENTRIES-1:0]] <= d_in; |
wp <= wp + 1'b1; |
empty <= 1'b0; |
full <= (wp >= ENTRIES - 1); |
almost_full <= (wp >= ENTRIES-1-1); |
almost_empty <= (wp < 1); |
end |
|
2'b11: //simultaneous shift-in and -out, move entries through shift registers |
begin |
for (i=1; i<ENTRIES; i=i+1) |
entry[i-1] <= entry[i]; |
|
entry[wp[LG_ENTRIES-1:0]-1'b1] <= d_in; |
end |
default: begin |
end |
endcase |
end |
end |
|
`ifdef CAG_COVERAGE |
full_cov: cover property (@(posedge clk) disable iff(!res_n) (full == 1'b1)); |
almost_full_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_full == 1'b1)); |
empty_cov: cover property (@(posedge clk) disable iff(!res_n) (empty == 1'b1)); |
almost_empty_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_empty == 1'b1)); |
|
covergroup shift_in_and_out @(posedge clk); |
shift_in_and_out_cp: coverpoint ({shift_in, shift_out}) iff (shift_in || shift_out) |
{ |
bins count[] = {[1:3]}; |
} |
endgroup |
shift_in_and_out shift_in_and_out_I; |
initial begin |
shift_in_and_out_I = new(); |
shift_in_and_out_I.set_inst_name("shift_in_and_out_I"); |
end |
`endif // CAG_COVERAGE |
|
`ifdef CAG_ASSERTIONS |
|
// when the FIFO signals empty, it must logically also be almost empty |
empty_means_aempty : assert property (@(posedge clk) disable iff(!res_n) empty |-> almost_empty); |
|
wp_eq_0_means_empty_A : assert property (@(posedge clk) disable iff(!res_n) (wp==0) |-> empty); |
wp_eq_0_means_empty_B : assert property (@(posedge clk) disable iff(!res_n) empty |-> (wp==0)); |
|
aempty_condition_A : assert property (@(posedge clk) disable iff(!res_n) (wp>1) |-> !almost_empty); |
aempty_condition_B : assert property (@(posedge clk) disable iff(!res_n) !almost_empty |-> (wp>1)); |
|
shift_in_and_full: assert property (@(posedge clk) disable iff(!res_n) (shift_in |-> !full)); |
|
if (DISABLE_SHIFT_OUT_ASSERT == 0) |
shift_out_and_empty: assert property (@(posedge clk) disable iff(!res_n) (shift_out |-> !empty)); |
|
if (DISABLE_XCHECK_ASSERT == 0) |
dout_known: assert property (@(posedge clk) disable iff(!res_n) (!empty |-> !$isunknown(d_out))); |
|
|
final |
begin |
if (DISABLE_FULL_ASSERT == 0) |
begin |
assert_full_set: assert (!full); |
assert_almost_full_set: assert (!almost_full); |
end |
|
if (DISABLE_EMPTY_ASSERT == 0) |
begin |
assert_write_pointer_not_zero: assert (wp == 0); |
assert_almost_empty_not_set: assert (almost_empty); |
assert_empty_not_set: assert (empty); |
end |
end |
`endif // CAG_ASSERTIONS |
|
endmodule |
|
`default_nettype wire |
/trunk/openHMC/rtl/building_blocks/fifos/sync/xilinx/openhmc_srl_fifo_16.v
0,0 → 1,154
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_srl_fifo_16 |
* |
*/ |
|
`default_nettype none |
|
module openhmc_srl_fifo_16 #( |
`ifdef CAG_ASSERTIONS |
parameter DISABLE_EMPTY_ASSERT = 0, |
parameter DISABLE_FULL_ASSERT = 0, |
`endif |
parameter DWIDTH = 8 |
) ( |
input wire clk, |
input wire res_n, |
input wire [DWIDTH-1:0] d_in, |
input wire shift_in, |
input wire shift_out, |
|
output wire [DWIDTH-1:0]d_out, |
output reg full, |
output reg empty, |
output reg almost_full, |
output reg almost_empty |
); |
|
reg [3:0] count; |
wire shift_out_notempty; |
wire shift_in_notfull; |
|
genvar i; |
|
assign shift_out_notempty = (shift_out && !empty); |
assign shift_in_notfull = (shift_in && !full); |
|
generate |
for (i=0; i < DWIDTH; i=i+1) |
begin: generate_SRL16 |
SRL16E #(.INIT(16'h0000)) SRL16_I ( |
.Q(d_out[i]), // SRL data output |
.A0(count[0]), // Select[0] input |
.A1(count[1]), // Select[1] input |
.A2(count[2]), // Select[2] input |
.A3(count[3]), // Select[3] input |
.CLK(clk), |
.D(d_in[i]), // SRL data input |
.CE(shift_in_notfull) |
); |
end |
endgenerate |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
if (!res_n) |
begin |
count <= 4'b0; |
full <= 1'b0; |
almost_full <= 1'b0; |
empty <= 1'b1; |
almost_empty <= 1'b1; |
end |
else |
begin |
case ({shift_in_notfull, shift_out_notempty}) |
2'b00: ; // nothing to do |
2'b01: |
begin |
if (|count) |
count <= count - 1'b1; |
empty <= !(|count); |
almost_empty <= (count <= 1); |
full <= 1'b0; |
almost_full <= (count > (4'd15 - 1)); |
end |
2'b10: |
begin |
if (!empty) |
count <= count + 1'b1; |
empty <= 1'b0; |
almost_empty <= empty; |
full <= (count > 4'd13); |
almost_full <= (count > (4'd13 - 1)); |
end |
2'b11: ; |
endcase |
end |
end |
|
`ifdef CAG_COVERAGE |
full_cov: cover property (@(posedge clk) disable iff(!res_n) (full == 1'b1)); |
almost_full_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_full == 1'b1)); |
empty_cov: cover property (@(posedge clk) disable iff(!res_n) (empty == 1'b1)); |
almost_empty_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_empty == 1'b1)); |
`endif // CAG_COVERAGE |
|
`ifdef CAG_ASSERTIONS |
final |
begin |
if (DISABLE_FULL_ASSERT == 0) |
begin |
full_set_assert: assert (!full); |
almost_full_set_assert: assert (!almost_full); |
end |
|
if (DISABLE_EMPTY_ASSERT == 0) |
begin |
almost_empty_not_set_assert: assert (almost_empty); |
empty_not_set_assert: assert (empty); |
end |
end |
`endif // CAG_ASSERTIONS |
|
endmodule |
|
`default_nettype wire |
/trunk/openHMC/rtl/building_blocks/fifos/sync/xilinx/openhmc_sync_fifo_xilinx.v
0,0 → 1,159
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_sync_fifo_xilinx |
* |
*/ |
|
`default_nettype none |
|
module openhmc_sync_fifo_xilinx #( |
`ifdef CAG_ASSERTIONS |
parameter DISABLE_EMPTY_ASSERT = 0, |
parameter DISABLE_FULL_ASSERT = 0, |
parameter DISABLE_SHIFT_OUT_ASSERT = 0, |
parameter DISABLE_XCHECK_ASSERT = 0, |
`endif |
parameter DWIDTH = 8 |
) ( |
input wire clk, |
input wire res_n, |
input wire [DWIDTH-1:0] d_in, |
input wire shift_in, |
input wire shift_out, |
output reg [DWIDTH-1:0] d_out, |
output wire full, |
output reg empty, |
output wire almost_full, |
output wire almost_empty |
); |
|
wire [DWIDTH-1:0] d_out_w; |
wire empty_w; |
wire shift_out_w; |
wire shift_in_w; |
|
assign shift_out_w = !empty_w && (empty || shift_out); |
assign shift_in_w = shift_in; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk ) `endif |
begin |
if (!res_n) |
begin |
empty <= 1'b1; |
d_out <= {DWIDTH {1'b0}}; |
end |
else |
begin |
if (!empty_w && (empty || shift_out)) |
begin |
d_out <= d_out_w; |
empty <= 1'b0; |
end |
else if (shift_out) |
empty <= 1'b1; |
end |
end |
|
openhmc_srl_fifo_16 #( |
`ifdef CAG_ASSERTIONS |
.DISABLE_EMPTY_ASSERT(DISABLE_EMPTY_ASSERT), |
.DISABLE_FULL_ASSERT(DISABLE_FULL_ASSERT), |
`endif |
.DWIDTH(DWIDTH) |
) srl_fifo_I ( |
.clk(clk), |
.res_n(res_n), |
.d_in(d_in), |
.d_out(d_out_w), |
.shift_out(shift_out_w), |
.shift_in(shift_in_w), |
.full(full), |
.almost_full(almost_full), |
.empty(empty_w), |
.almost_empty(almost_empty) |
); |
|
`ifdef CAG_COVERAGE |
full_cov: cover property (@(posedge clk) disable iff(!res_n) (full == 1'b1)); |
almost_full_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_full == 1'b1)); |
empty_cov: cover property (@(posedge clk) disable iff(!res_n) (empty == 1'b1)); |
almost_empty_cov: cover property (@(posedge clk) disable iff(!res_n) (almost_empty == 1'b1)); |
|
covergroup shift_in_and_out @(posedge clk); |
shift_in_and_out_cp: coverpoint ({shift_in, shift_out}) iff (shift_in || shift_out) |
{ |
bins count[] = {[1:3]}; |
} |
endgroup |
shift_in_and_out shift_in_and_out_I; |
initial begin |
shift_in_and_out_I = new(); |
shift_in_and_out_I.set_inst_name("shift_in_and_out_I"); |
end |
`endif // CAG_COVERAGE |
|
`ifdef CAG_ASSERTIONS |
shift_in_and_full: assert property (@(posedge clk) disable iff(!res_n) (shift_in |-> !full)); |
|
if (DISABLE_SHIFT_OUT_ASSERT == 0) |
shift_out_and_empty: assert property (@(posedge clk) disable iff(!res_n) (shift_out |-> !empty)); |
|
if (DISABLE_XCHECK_ASSERT == 0) |
d_out_known: assert property (@(posedge clk) disable iff(!res_n) (!empty |-> !$isunknown(d_out))); |
|
final |
begin |
if (DISABLE_FULL_ASSERT == 0) |
begin |
assert_full_set: assert (!full); |
assert_almost_full_set: assert (!almost_full); |
end |
|
if (DISABLE_EMPTY_ASSERT == 0) |
begin |
assert_almost_empty_not_set: assert (almost_empty); |
assert_empty_not_set: assert (empty); |
end |
end |
`endif // CAG_ASSERTIONS |
|
endmodule |
|
`default_nettype wire |
/trunk/openHMC/rtl/building_blocks/fifos/sync/xilinx/openhmc_fifos_xilinx.f
0,0 → 1,2
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/xilinx/openhmc_sync_fifo_xilinx.v |
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/xilinx/openhmc_srl_fifo_16.v |
/trunk/openHMC/rtl/building_blocks/fifos/sync/openhmc_sync_fifo.v
62,7 → 62,6
input wire [DATASIZE-1:0] d_in, |
input wire shift_in, |
input wire shift_out, |
input wire next_stage_full, // Set to 1 if not chained |
output wire [DATASIZE-1:0] d_out, |
output wire empty |
); |
/trunk/openHMC/rtl/hmc_controller/openhmc_top.f
62,11 → 62,14
${OPENHMC_PATH}/rtl/hmc_controller/crc/crc_accu.v |
|
####Register File |
${OPENHMC_PATH}/rtl/hmc_controller/register_file/openhmc_8x_rf.v |
${OPENHMC_PATH}/rtl/hmc_controller/register_file/openhmc_16x_rf.v |
${OPENHMC_PATH}/rtl/hmc_controller/register_file/openhmc_rf.v |
|
####Building blocks |
-f ${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/openhmc_sync_fifos.f |
${OPENHMC_PATH}/rtl/building_blocks/fifos/async/openhmc_async_fifo.v |
${OPENHMC_PATH}/rtl/building_blocks/counter/counter48.v |
${OPENHMC_PATH}/rtl/building_blocks/counter/openhmc_counter48.v |
${OPENHMC_PATH}/rtl/building_blocks/rams/openhmc_ram.v |
|
|
####Include this if using XILINX |
#${OPENHMC_PATH}/rtl/building_blocks/counter/openhmc_counter48_wrapper_xilinx.v |
/trunk/openHMC/rtl/hmc_controller/openhmc_top.v
35,8 → 35,18
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: hmc_controller_top |
* Module name: openhmc_top |
* |
* |
* |
* |
* DESIGN CONTROL: Use the following defines if desired: |
* `define XILINX |
* Uses Xilinx DSP48 as counter in the Register File |
* `define ASYNC_RES |
* Define the active low reset to be asynchronous |
* `define RESET_ALL |
* Use Reset values for all registers |
*/ |
|
`default_nettype none |
43,8 → 53,8
|
module openhmc_top #( |
//Define width of the datapath |
parameter LOG_FPW = 2, //Legal Values: 1,2,3 |
parameter FPW = 4, //Legal Values: 2,4,6,8 |
parameter LOG_FPW = 2, //Legal Values: 1 for FPW=2 ,2 for FPW=4 ,3 for FPW=6/8 |
parameter DWIDTH = FPW*128, //Leave untouched |
//Define HMC interface width |
parameter LOG_NUM_LANES = 3, //Set 3 for half-width, 4 for full-width |
51,26 → 61,37
parameter NUM_LANES = 2**LOG_NUM_LANES, //Leave untouched |
parameter NUM_DATA_BYTES = FPW*16, //Leave untouched |
//Define width of the register file |
parameter HMC_RF_WWIDTH = 64, |
parameter HMC_RF_RWIDTH = 64, |
parameter HMC_RF_AWIDTH = 4, |
parameter HMC_RF_WWIDTH = 64, //Leave untouched |
parameter HMC_RF_RWIDTH = 64, //Leave untouched |
parameter HMC_RF_AWIDTH = 4, //Leave untouched |
//Configure the Functionality |
parameter LOG_MAX_RTC = 8, //Set the depth of the RX input buffer. Must be >= LOG(rf_rx_buffer_rtc) in the RF |
parameter HMC_RX_AC_COUPLED = 1, //Set to 0 to remove the run length limiter, saves logic and 1 cycle delay |
parameter LOG_MAX_RX_TOKENS = 8, //Set the depth of the RX input buffer. Must be >= LOG(rf_rx_buffer_rtc) in the RF. Dont't care if OPEN_RSP_MODE=1 |
parameter LOG_MAX_HMC_TOKENS = 10, //Set the depth of the HMC input buffer. Must be >= LOG of the corresponding field in the HMC internal register |
parameter HMC_RX_AC_COUPLED = 1, //Set to 0 to bypass the run length limiter, saves logic and 1 cycle delay |
parameter DETECT_LANE_POLARITY = 1, //Set to 0 if lane polarity is not applicable, saves logic |
parameter CTRL_LANE_POLARITY = 1, //Set to 0 if lane polarity is not applicable or performed by the transceivers, saves logic and 1 cycle delay |
//If set to 1: Only valid if DETECT_LANE_POLARITY==1, otherwise tied to zero |
parameter CTRL_LANE_REVERSAL = 1, //Set to 0 if lane reversal is not applicable or performed by the transceivers, saves logic |
parameter CTRL_SCRAMBLERS = 1, //Set to 0 to remove the option to disable (de-)scramblers for debugging, saves logic |
parameter OPEN_RSP_MODE = 0, //Set to 1 if running response open loop mode, bypasses the RX input buffer |
parameter RX_RELAX_INIT_TIMING = 1, //Per default, incoming TS1 sequences are only checked for the lane independent h'F0 sequence. Save resources and |
//eases timing closure. !Lane reversal is still detected |
parameter RX_BIT_SLIP_CNT_LOG = 5, //Define the number of cycles between bit slips. Refer to the transceiver user guide |
//Example: RX_BIT_SLIP_CNT_LOG=5 results in 2^5=32 cycles between two bit slips |
parameter SYNC_AXI4_IF = 0, //Set to 1 if AXI IF is synchronous to clk_hmc to use simple fifos |
parameter XIL_CNT_PIPELINED = 1, //If Xilinx counters are used, set to 1 to enabled output register pipelining |
//Set the direction of bitslip. Set to 1 if bitslip performs a shift right, otherwise set to 0 (see the corresponding transceiver user guide) |
parameter BITSLIP_SHIFT_RIGHT = 1, |
//Debug Params |
parameter DBG_RX_TOKEN_MON = 1 //Remove the RX Link token monitor, saves logic |
parameter DBG_RX_TOKEN_MON = 1 //Set to 0 to remove the RX Link token monitor, saves logic |
) ( |
//---------------------------------- |
//----SYSTEM INTERFACES |
//---------------------------------- |
input wire clk_user, |
input wire clk_hmc, |
input wire res_n_user, |
input wire res_n_hmc, |
input wire clk_user, //Connect if SYNC_AXI4_IF==0 |
input wire clk_hmc, //Connect! |
input wire res_n_user, //Connect if SYNC_AXI4_IF==0 |
input wire res_n_hmc, //Connect! |
|
//---------------------------------- |
//----Connect AXI Ports |
89,19 → 110,21
//---------------------------------- |
//----Connect Transceiver |
//---------------------------------- |
output wire [DWIDTH-1:0] phy_data_tx_link2phy, |
input wire [DWIDTH-1:0] phy_data_rx_phy2link, |
output wire [NUM_LANES-1:0] phy_bit_slip, |
output wire [DWIDTH-1:0] phy_data_tx_link2phy,//Connect! |
input wire [DWIDTH-1:0] phy_data_rx_phy2link,//Connect! |
output wire [NUM_LANES-1:0] phy_bit_slip, //Must be connected if DETECT_LANE_POLARITY==1 AND CTRL_LANE_POLARITY=0 |
output wire [NUM_LANES-1:0] phy_lane_polarity, //All 0 if CTRL_LANE_POLARITY=1 |
input wire phy_ready, |
input wire phy_tx_ready, //Optional information to RF |
input wire phy_rx_ready, //Release RX descrambler reset when PHY ready |
output wire phy_init_cont_set, //Can be used to release transceiver reset if used |
|
//---------------------------------- |
//----Connect HMC |
//---------------------------------- |
output wire P_RST_N, |
output wire hmc_LxRXPS, |
input wire hmc_LxTXPS, |
input wire FERR_N, //Not connected |
output wire LXRXPS, |
input wire LXTXPS, |
input wire FERR_N, |
|
//---------------------------------- |
//----Connect RF |
122,14 → 145,23
//----------------------------------------------------------------------------------------------------- |
//===================================================================================================== |
|
localparam MAX_RTC_RET_LOG = (FPW == 2) ? 6 : |
(FPW == 4) ? 7 : |
8; |
|
`ifdef XILINX |
localparam RF_COUNTER_SIZE = 48; |
`else |
localparam RF_COUNTER_SIZE = 64; |
`endif |
|
// ----Assign AXI interface wires |
wire [4*FPW-1:0] m_axis_rx_TUSER_temp; |
assign m_axis_rx_TUSER = {{NUM_DATA_BYTES-(4*FPW){1'b0}}, m_axis_rx_TUSER_temp}; |
|
wire s_axis_tx_TREADY_n; |
wire s_axis_tx_TREADY_n; |
assign s_axis_tx_TREADY = ~s_axis_tx_TREADY_n; |
|
wire m_axis_rx_TVALID_n; |
wire m_axis_rx_TVALID_n; |
assign m_axis_rx_TVALID = ~m_axis_rx_TVALID_n; |
|
// ----TX FIFO Wires |
142,7 → 174,6
// ----RX FIFO Wires |
wire [DWIDTH-1:0] rx_d_in_data; |
wire rx_shift_in; |
wire rx_full; |
wire rx_a_full; |
wire [4*FPW-1:0] rx_d_in_ctrl; |
|
152,7 → 183,7
wire rx2tx_error_abort_mode_cleared; |
wire [7:0] rx2tx_hmc_frp; |
wire [7:0] rx2tx_rrp; |
wire [7:0] rx2tx_returned_tokens; |
wire [MAX_RTC_RET_LOG-1:0]rx2tx_returned_tokens; |
wire [LOG_FPW:0] rx2tx_hmc_tokens_to_return; |
wire [LOG_FPW:0] rx2tx_hmc_poisoned_tokens_to_return; |
|
161,40 → 192,52
wire rf_cnt_retry; |
wire rf_run_length_bit_flip; |
wire rf_error_abort_not_cleared; |
wire [HMC_RF_RWIDTH-1:0] rf_cnt_poisoned; |
wire [HMC_RF_RWIDTH-1:0] rf_cnt_p; |
wire [HMC_RF_RWIDTH-1:0] rf_cnt_np; |
wire [HMC_RF_RWIDTH-1:0] rf_cnt_r; |
wire [HMC_RF_RWIDTH-1:0] rf_cnt_rsp_rcvd; |
wire [RF_COUNTER_SIZE-1:0] rf_cnt_poisoned; |
wire [RF_COUNTER_SIZE-1:0] rf_cnt_p; |
wire [RF_COUNTER_SIZE-1:0] rf_cnt_np; |
wire [RF_COUNTER_SIZE-1:0] rf_cnt_r; |
wire [RF_COUNTER_SIZE-1:0] rf_cnt_rsp_rcvd; |
//Status |
wire [1:0] rf_link_status; |
wire [2:0] rf_hmc_init_status; |
wire rf_link_up; |
wire [2:0] rf_rx_init_status; |
wire [1:0] rf_tx_init_status; |
wire [9:0] rf_hmc_tokens_av; |
wire [9:0] rf_rx_tokens_av; |
wire rf_hmc_sleep; |
wire [LOG_MAX_HMC_TOKENS-1:0]rf_hmc_tokens_av; |
wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_tokens_av; |
//Init Status |
wire rf_all_descramblers_aligned; |
wire [NUM_LANES-1:0] rf_descrambler_aligned; |
wire [NUM_LANES-1:0] rf_descrambler_part_aligned; |
//Control |
wire [5:0] rf_bit_slip_time; |
wire rf_hmc_init_cont_set; |
wire rf_set_hmc_sleep; |
wire rf_warm_reset; |
wire rf_scrambler_disable; |
wire [NUM_LANES-1:0] rf_lane_polarity; |
wire [NUM_LANES-1:0] rf_descramblers_locked; |
wire [9:0] rf_rx_buffer_rtc; |
wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_buffer_rtc; |
wire rf_lane_reversal_detected; |
wire [4:0] rf_irtry_received_threshold; |
wire [4:0] rf_irtry_to_send; |
wire rf_run_length_enable; |
wire [2:0] rf_first_cube_ID; |
//Debug |
wire rf_dbg_dont_send_tret; |
wire rf_dbg_halt_on_error_abort; |
wire rf_dbg_halt_on_tx_retry; |
|
assign phy_init_cont_set = rf_hmc_init_cont_set; |
|
//Generate |
wire rf_scrambler_disable_temp; |
wire [LOG_MAX_RX_TOKENS-1:0] rf_rx_buffer_rtc_temp; |
generate |
if(CTRL_SCRAMBLERS==1) begin : ctrl_scramblers |
assign rf_scrambler_disable = rf_scrambler_disable_temp; |
end else begin : remove_scrambler_disable_bit |
assign rf_scrambler_disable = 1'b0; |
end |
if(OPEN_RSP_MODE==1) begin : remove_rx_tokens_rsp_open_loop_mode |
assign rf_rx_buffer_rtc = {LOG_MAX_RX_TOKENS{1'b0}}; |
end else begin : regular_mode_use_rx_tokens |
assign rf_rx_buffer_rtc = rf_rx_buffer_rtc_temp; |
end |
endgenerate |
|
// ----Assign PHY wires |
assign phy_lane_polarity = (CTRL_LANE_POLARITY==1) ? {NUM_LANES{1'b0}} : rf_lane_polarity; |
|
206,39 → 249,90
//---------------------------------------------------------------------- |
//-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX |
//---------------------------------------------------------------------- |
generate |
if(SYNC_AXI4_IF==0) begin : async_axi4_tx_fifo |
openhmc_async_fifo #( |
.DWIDTH(DWIDTH+(FPW*3)), |
.ENTRIES(16) |
) fifo_tx_data ( |
//System |
.si_clk(clk_user), |
.so_clk(clk_hmc), |
.si_res_n(res_n_user), |
.so_res_n(res_n_hmc), |
|
openhmc_async_fifo #( |
.DWIDTH(DWIDTH+(FPW*3)), |
.ENTRIES(16) |
) fifo_tx_data ( |
//System |
.si_clk(clk_user), |
.so_clk(clk_hmc), |
.si_res_n(res_n_user), |
.so_res_n(res_n_hmc), |
//From AXI-4 TX IF |
.d_in({s_axis_tx_TUSER[(FPW*3)-1:0],s_axis_tx_TDATA}), |
.shift_in(s_axis_tx_TVALID && s_axis_tx_TREADY), |
.full(s_axis_tx_TREADY_n), |
.almost_full(), |
|
//From AXI-4 TX IF |
.d_in({s_axis_tx_TUSER[(FPW*3)-1:0],s_axis_tx_TDATA}), |
.shift_in(s_axis_tx_TVALID && s_axis_tx_TREADY), |
.full(s_axis_tx_TREADY_n), |
.almost_full(), |
//To TX Link Logic |
.d_out({tx_d_in_ctrl,tx_d_in_data}), |
.shift_out(tx_shift_out), |
.empty(tx_empty), |
.almost_empty(tx_a_empty) |
); |
end else begin : synchronous_axi4_tx_fifo |
`ifdef XILINX |
openhmc_sync_fifo_xilinx #( |
.DWIDTH(DWIDTH+(FPW*3)) |
) fifo_tx_data_sync_xilinx( |
//System |
.clk(clk_hmc), |
.res_n(res_n_hmc), |
|
//To TX Link Logic |
.d_out({tx_d_in_ctrl,tx_d_in_data}), |
.shift_out(tx_shift_out), |
.empty(tx_empty), |
.almost_empty(tx_a_empty) |
); |
//To RX LINK Logic |
.d_in({s_axis_tx_TUSER[(FPW*3)-1:0],s_axis_tx_TDATA}), |
.shift_in(s_axis_tx_TVALID && s_axis_tx_TREADY), |
.full(s_axis_tx_TREADY_n), |
.almost_full(), |
|
//AXI-4 RX IF |
.d_out({tx_d_in_ctrl,tx_d_in_data}), |
.shift_out(tx_shift_out), |
.empty(tx_empty), |
.almost_empty(tx_a_empty) |
); |
`else |
openhmc_sync_fifo_reg_based #( |
.DWIDTH(DWIDTH+(FPW*3)), |
.ENTRIES(4) |
) fifo_tx_data_sync( |
//System |
.clk(clk_hmc), |
.res_n(res_n_hmc), |
|
//To RX LINK Logic |
.d_in({s_axis_tx_TUSER[(FPW*3)-1:0],s_axis_tx_TDATA}), |
.shift_in(s_axis_tx_TVALID && s_axis_tx_TREADY), |
.full(s_axis_tx_TREADY_n), |
.almost_full(), |
|
//AXI-4 RX IF |
.d_out({tx_d_in_ctrl,tx_d_in_data}), |
.shift_out(tx_shift_out), |
.empty(tx_empty), |
.almost_empty(tx_a_empty) |
); |
`endif |
end |
endgenerate |
|
|
tx_link #( |
.LOG_FPW(LOG_FPW), |
.FPW(FPW), |
.NUM_LANES(NUM_LANES), |
.HMC_PTR_SIZE(8), |
.HMC_RF_RWIDTH(HMC_RF_RWIDTH), |
.RF_COUNTER_SIZE(RF_COUNTER_SIZE), |
.HMC_RX_AC_COUPLED(HMC_RX_AC_COUPLED), |
.MAX_RTC_RET_LOG(MAX_RTC_RET_LOG), |
.LOG_MAX_RX_TOKENS(LOG_MAX_RX_TOKENS), |
.LOG_MAX_HMC_TOKENS(LOG_MAX_HMC_TOKENS), |
.XIL_CNT_PIPELINED(XIL_CNT_PIPELINED), |
//Debug |
.DBG_RX_TOKEN_MON(DBG_RX_TOKEN_MON) |
.DBG_RX_TOKEN_MON(DBG_RX_TOKEN_MON), |
.OPEN_RSP_MODE(OPEN_RSP_MODE) |
) tx_link_I( |
|
//---------------------------------- |
255,8 → 349,8
//---------------------------------- |
//----HMC IF |
//---------------------------------- |
.hmc_LxRXPS(hmc_LxRXPS), |
.hmc_LxTXPS(hmc_LxTXPS), |
.LXRXPS(LXRXPS), |
.LXTXPS(LXTXPS), |
|
//---------------------------------- |
//----FROM HMC_TX_HTAX_LOGIC |
292,9 → 386,8
.rf_run_length_bit_flip(rf_run_length_bit_flip), |
.rf_error_abort_not_cleared(rf_error_abort_not_cleared), |
//Status |
.rf_hmc_is_in_sleep(rf_hmc_sleep), |
.rf_hmc_received_init_null(rf_hmc_init_status[0]), |
.rf_link_is_up(rf_link_status[1]), |
.rf_hmc_received_init_null(rf_rx_init_status==3'b010), |
.rf_link_is_up(rf_link_up), |
.rf_descramblers_aligned(rf_all_descramblers_aligned), |
.rf_tx_init_status(rf_tx_init_status), |
.rf_hmc_tokens_av(rf_hmc_tokens_av), |
301,16 → 394,11
.rf_rx_tokens_av(rf_rx_tokens_av), |
//Control |
.rf_hmc_sleep_requested(rf_set_hmc_sleep), |
.rf_hmc_init_cont_set(rf_hmc_init_cont_set), |
.rf_warm_reset(rf_warm_reset), |
.rf_scrambler_disable(rf_scrambler_disable), |
.rf_rx_buffer_rtc(rf_rx_buffer_rtc), |
.rf_first_cube_ID(rf_first_cube_ID), |
.rf_irtry_to_send(rf_irtry_to_send), |
.rf_run_length_enable(rf_run_length_enable), |
//Debug |
.rf_dbg_dont_send_tret(rf_dbg_dont_send_tret), |
.rf_dbg_halt_on_error_abort(rf_dbg_halt_on_error_abort), |
.rf_dbg_halt_on_tx_retry(rf_dbg_halt_on_tx_retry) |
.rf_run_length_enable(rf_run_length_enable) |
|
); |
|
321,12 → 409,18
.LOG_FPW(LOG_FPW), |
.FPW(FPW), |
.LOG_NUM_LANES(LOG_NUM_LANES), |
.HMC_RF_RWIDTH(HMC_RF_RWIDTH), |
.RF_COUNTER_SIZE(RF_COUNTER_SIZE), |
//Configure the functionality |
.LOG_MAX_RTC(LOG_MAX_RTC), |
.XIL_CNT_PIPELINED(XIL_CNT_PIPELINED), |
.LOG_MAX_RX_TOKENS(LOG_MAX_RX_TOKENS), |
.MAX_RTC_RET_LOG(MAX_RTC_RET_LOG), |
.RX_BIT_SLIP_CNT_LOG(RX_BIT_SLIP_CNT_LOG), |
.CTRL_LANE_POLARITY(CTRL_LANE_POLARITY), |
.DETECT_LANE_POLARITY(DETECT_LANE_POLARITY), |
.CTRL_LANE_REVERSAL(CTRL_LANE_REVERSAL), |
.BITSLIP_SHIFT_RIGHT(BITSLIP_SHIFT_RIGHT) |
.BITSLIP_SHIFT_RIGHT(BITSLIP_SHIFT_RIGHT), |
.OPEN_RSP_MODE(OPEN_RSP_MODE), |
.RX_RELAX_INIT_TIMING(RX_RELAX_INIT_TIMING) |
) rx_link_I ( |
|
//---------------------------------- |
339,13 → 433,13
//----TO HMC PHY |
//---------------------------------- |
.phy_scrambled_data_in(phy_data_rx_phy2link), |
.init_bit_slip(phy_bit_slip), |
.phy_bit_slip(phy_bit_slip), |
.run_rx(phy_rx_ready), |
|
//---------------------------------- |
//----FROM TO RX HTAX FIFO |
//---------------------------------- |
.d_out_fifo_data(rx_d_in_data), |
.d_out_fifo_full(rx_full), |
.d_out_fifo_a_full(rx_a_full), |
.d_out_fifo_shift_in(rx_shift_in), |
.d_out_fifo_ctrl(rx_d_in_ctrl), |
369,18 → 463,15
.rf_cnt_poisoned(rf_cnt_poisoned), |
.rf_cnt_rsp(rf_cnt_rsp_rcvd), |
//Status |
.rf_link_status(rf_link_status), |
.rf_hmc_init_status(rf_hmc_init_status), |
.rf_hmc_sleep(rf_hmc_sleep), |
.rf_link_up(rf_link_up), |
.rf_rx_init_status(rf_rx_init_status), |
.rf_hmc_sleep(~LXTXPS), |
//Init Status |
.rf_all_descramblers_aligned(rf_all_descramblers_aligned), |
.rf_descrambler_aligned(rf_descrambler_aligned), |
.rf_descrambler_part_aligned(rf_descrambler_part_aligned), |
.rf_descramblers_locked(rf_descramblers_locked), |
.rf_tx_sends_ts1(rf_tx_init_status[1] && !rf_tx_init_status[0]), |
//Control |
.rf_bit_slip_time(rf_bit_slip_time), |
.rf_hmc_init_cont_set(rf_hmc_init_cont_set), |
.rf_lane_polarity(rf_lane_polarity), |
.rf_scrambler_disable(rf_scrambler_disable), |
.rf_lane_reversal_detected(rf_lane_reversal_detected), |
387,161 → 478,148
.rf_irtry_received_threshold(rf_irtry_received_threshold) |
); |
|
openhmc_async_fifo #( |
.DWIDTH(DWIDTH+(FPW*4)), |
.ENTRIES(16) |
) fifo_rx_data( |
//System |
.si_clk(clk_hmc), |
.so_clk(clk_user), |
.si_res_n(res_n_hmc), |
.so_res_n(res_n_user), |
generate |
if(SYNC_AXI4_IF==0) begin : async_axi4_rx_fifo |
openhmc_async_fifo #( |
.DWIDTH(DWIDTH+(FPW*4)), |
.ENTRIES(16) |
) fifo_rx_data( |
//System |
.si_clk(clk_hmc), |
.so_clk(clk_user), |
.si_res_n(res_n_hmc), |
.so_res_n(res_n_user), |
|
//To RX LINK Logic |
.d_in({rx_d_in_ctrl,rx_d_in_data}), |
.shift_in(rx_shift_in), |
.full(rx_full), |
.almost_full(rx_a_full), |
//To RX LINK Logic |
.d_in({rx_d_in_ctrl,rx_d_in_data}), |
.shift_in(rx_shift_in), |
.full(), |
.almost_full(rx_a_full), |
|
//AXI-4 RX IF |
.d_out({m_axis_rx_TUSER_temp,m_axis_rx_TDATA}), |
.shift_out(m_axis_rx_TVALID && m_axis_rx_TREADY), |
.empty(m_axis_rx_TVALID_n), |
.almost_empty() |
//AXI-4 RX IF |
.d_out({m_axis_rx_TUSER_temp,m_axis_rx_TDATA}), |
.shift_out(m_axis_rx_TVALID && m_axis_rx_TREADY), |
.empty(m_axis_rx_TVALID_n), |
.almost_empty() |
|
); |
|
//---------------------------------------------------------------------- |
//---Register File---Register File---Register File---Register File---Reg |
//---------------------------------------------------------------------- |
//Instantiate register file depending on the number of lanes |
generate |
if(NUM_LANES==8) begin : register_file_8x |
openhmc_8x_rf openhmc_rf_I ( |
//system IF |
); |
end else begin : synchronous_axi4_rx_fifo |
`ifdef XILINX |
openhmc_sync_fifo_xilinx #( |
.DWIDTH(DWIDTH+(FPW*4)) |
) fifo_rx_data_sync_xilinx( |
//System |
.clk(clk_hmc), |
.res_n(res_n_hmc), |
.clk(clk_hmc), |
|
//rf access |
.address(rf_address), |
.read_data(rf_read_data), |
.invalid_address(rf_invalid_address), |
.access_complete(rf_access_complete), |
.read_en(rf_read_en), |
.write_en(rf_write_en), |
.write_data(rf_write_data), |
//To RX LINK Logic |
.d_in({rx_d_in_ctrl,rx_d_in_data}), |
.shift_in(rx_shift_in), |
.full(), |
.almost_full(rx_a_full), |
|
//status registers |
.status_general_link_up_next(rf_link_status[1]), |
.status_general_link_training_next(rf_link_status[0]), |
.status_general_sleep_mode_next(rf_hmc_sleep), |
.status_general_phy_ready_next(phy_ready), |
.status_general_lanes_reversed_next(rf_lane_reversal_detected), |
.status_general_hmc_tokens_remaining_next(rf_hmc_tokens_av), |
.status_general_rx_tokens_remaining_next(rf_rx_tokens_av), |
.status_general_lane_polarity_reversed_next(rf_lane_polarity), |
//AXI-4 RX IF |
.d_out({m_axis_rx_TUSER_temp,m_axis_rx_TDATA}), |
.shift_out(m_axis_rx_TVALID && m_axis_rx_TREADY), |
.empty(m_axis_rx_TVALID_n), |
.almost_empty() |
); |
`else |
openhmc_sync_fifo_reg_based #( |
.DWIDTH(DWIDTH+(FPW*4)), |
.ENTRIES(4) |
) fifo_rx_data_sync( |
//System |
.clk(clk_hmc), |
.res_n(res_n_hmc), |
|
//init status |
.status_init_lane_descramblers_locked_next(rf_descramblers_locked), |
.status_init_descrambler_part_aligned_next(rf_descrambler_part_aligned), |
.status_init_descrambler_aligned_next(rf_descrambler_aligned), |
.status_init_all_descramblers_aligned_next(rf_all_descramblers_aligned), |
.status_init_tx_init_status_next(rf_tx_init_status), |
.status_init_hmc_init_TS1_next(rf_hmc_init_status[0]), |
//To RX LINK Logic |
.d_in({rx_d_in_ctrl,rx_d_in_data}), |
.shift_in(rx_shift_in), |
.full(), |
.almost_full(rx_a_full), |
|
//counters |
.sent_np_cnt_next(rf_cnt_np), |
.sent_p_cnt_next(rf_cnt_p), |
.sent_r_cnt_next(rf_cnt_r), |
.poisoned_packets_cnt_next(rf_cnt_poisoned), |
.rcvd_rsp_cnt_next(rf_cnt_rsp_rcvd), |
//AXI-4 RX IF |
.d_out({m_axis_rx_TUSER_temp,m_axis_rx_TDATA}), |
.shift_out(m_axis_rx_TVALID && m_axis_rx_TREADY), |
.empty(m_axis_rx_TVALID_n), |
.almost_empty() |
); |
`endif |
end |
endgenerate |
|
//Single bit counter |
.tx_link_retries_count_countup(rf_cnt_retry), |
.errors_on_rx_count_countup(rx2tx_error_abort_mode_cleared), |
.run_length_bit_flip_count_countup(rf_run_length_bit_flip), |
.error_abort_not_cleared_count_countup(rf_error_abort_not_cleared), |
//---------------------------------------------------------------------- |
//---Register File---Register File---Register File---Register File---Reg |
//---------------------------------------------------------------------- |
openhmc_rf #( |
.NUM_LANES(NUM_LANES), |
.XIL_CNT_PIPELINED(XIL_CNT_PIPELINED), |
.LOG_MAX_RX_TOKENS(LOG_MAX_RX_TOKENS), |
.LOG_MAX_HMC_TOKENS(LOG_MAX_HMC_TOKENS), |
.RF_COUNTER_SIZE(RF_COUNTER_SIZE), |
.HMC_RF_WWIDTH(HMC_RF_WWIDTH), |
.HMC_RF_AWIDTH(HMC_RF_AWIDTH), |
.HMC_RF_RWIDTH(HMC_RF_RWIDTH) |
) openhmc_rf_I ( |
//system IF |
.res_n(res_n_hmc), |
.clk(clk_hmc), |
|
//control |
.control_p_rst_n(P_RST_N), |
.control_hmc_init_cont_set(rf_hmc_init_cont_set), |
.control_set_hmc_sleep(rf_set_hmc_sleep), |
.control_scrambler_disable(rf_scrambler_disable), |
.control_run_length_enable(rf_run_length_enable), |
.control_first_cube_ID(rf_first_cube_ID), |
.control_debug_dont_send_tret(rf_dbg_dont_send_tret), |
.control_debug_halt_on_error_abort(rf_dbg_halt_on_error_abort), |
.control_debug_halt_on_tx_retry(rf_dbg_halt_on_tx_retry), |
.control_rx_token_count(rf_rx_buffer_rtc), |
.control_irtry_received_threshold(rf_irtry_received_threshold), |
.control_irtry_to_send(rf_irtry_to_send), |
.control_bit_slip_time(rf_bit_slip_time) |
//rf access |
.address(rf_address), |
.read_data(rf_read_data), |
.invalid_address(rf_invalid_address), |
.access_complete(rf_access_complete), |
.read_en(rf_read_en), |
.write_en(rf_write_en), |
.write_data(rf_write_data), |
|
); |
end else begin : register_file_16x |
openhmc_16x_rf openhmc_rf_I ( |
//system IF |
.res_n(res_n_hmc), |
.clk(clk_hmc), |
//status registers |
.status_general_link_up_next(rf_link_up), |
.status_general_link_training_next(~rf_link_up), |
.status_general_sleep_mode_next(~LXTXPS), |
.status_general_FERR_N_next(FERR_N), |
.status_general_phy_tx_ready_next(phy_tx_ready), |
.status_general_phy_rx_ready_next(phy_rx_ready), |
.status_general_lanes_reversed_next(rf_lane_reversal_detected), |
.status_general_hmc_tokens_remaining_next(rf_hmc_tokens_av), |
.status_general_rx_tokens_remaining_next(rf_rx_tokens_av), |
.status_general_lane_polarity_reversed_next(rf_lane_polarity), |
|
//rf access |
.address(rf_address), |
.read_data(rf_read_data), |
.invalid_address(rf_invalid_address), |
.access_complete(rf_access_complete), |
.read_en(rf_read_en), |
.write_en(rf_write_en), |
.write_data(rf_write_data), |
//init status |
.status_init_lane_descramblers_locked_next(rf_descramblers_locked), |
.status_init_descrambler_part_aligned_next(rf_descrambler_part_aligned), |
.status_init_descrambler_aligned_next(rf_descrambler_aligned), |
.status_init_all_descramblers_aligned_next(rf_all_descramblers_aligned), |
.status_init_rx_init_state_next(rf_rx_init_status), |
.status_init_tx_init_state_next(rf_tx_init_status), |
|
//status registers |
.status_general_link_up_next(rf_link_status[1]), |
.status_general_link_training_next(rf_link_status[0]), |
.status_general_sleep_mode_next(rf_hmc_sleep), |
.status_general_phy_ready_next(phy_ready), |
.status_general_lanes_reversed_next(rf_lane_reversal_detected), |
.status_general_hmc_tokens_remaining_next(rf_hmc_tokens_av), |
.status_general_rx_tokens_remaining_next(rf_rx_tokens_av), |
.status_general_lane_polarity_reversed_next(rf_lane_polarity), |
//counters |
.sent_np_cnt_next(rf_cnt_np), |
.sent_p_cnt_next(rf_cnt_p), |
.sent_r_cnt_next(rf_cnt_r), |
.poisoned_packets_cnt_next(rf_cnt_poisoned), |
.rcvd_rsp_cnt_next(rf_cnt_rsp_rcvd), |
|
//init status |
.status_init_lane_descramblers_locked_next(rf_descramblers_locked), |
.status_init_descrambler_part_aligned_next(rf_descrambler_part_aligned), |
.status_init_descrambler_aligned_next(rf_descrambler_aligned), |
.status_init_all_descramblers_aligned_next(rf_all_descramblers_aligned), |
.status_init_tx_init_status_next(rf_tx_init_status), |
.status_init_hmc_init_TS1_next(rf_hmc_init_status[0]), |
//Single bit counter |
.tx_link_retries_count_countup(rf_cnt_retry), |
.errors_on_rx_count_countup(rx2tx_error_abort_mode_cleared), |
.run_length_bit_flip_count_countup(rf_run_length_bit_flip), |
.error_abort_not_cleared_count_countup(rf_error_abort_not_cleared), |
|
//counters |
.sent_np_cnt_next(rf_cnt_np), |
.sent_p_cnt_next(rf_cnt_p), |
.sent_r_cnt_next(rf_cnt_r), |
.poisoned_packets_cnt_next(rf_cnt_poisoned), |
.rcvd_rsp_cnt_next(rf_cnt_rsp_rcvd), |
//control |
.control_p_rst_n(P_RST_N), |
.control_hmc_init_cont_set(rf_hmc_init_cont_set), |
.control_set_hmc_sleep(rf_set_hmc_sleep), |
.control_warm_reset(rf_warm_reset), |
.control_scrambler_disable(rf_scrambler_disable_temp), |
.control_run_length_enable(rf_run_length_enable), |
.control_rx_token_count(rf_rx_buffer_rtc_temp), |
.control_irtry_received_threshold(rf_irtry_received_threshold), |
.control_irtry_to_send(rf_irtry_to_send) |
); |
|
//Single bit counter |
.tx_link_retries_count_countup(rf_cnt_retry), |
.errors_on_rx_count_countup(rx2tx_error_abort_mode_cleared), |
.run_length_bit_flip_count_countup(rf_run_length_bit_flip), |
.error_abort_not_cleared_count_countup(rf_error_abort_not_cleared), |
|
//control |
.control_p_rst_n(P_RST_N), |
.control_hmc_init_cont_set(rf_hmc_init_cont_set), |
.control_set_hmc_sleep(rf_set_hmc_sleep), |
.control_scrambler_disable(rf_scrambler_disable), |
.control_run_length_enable(rf_run_length_enable), |
.control_first_cube_ID(rf_first_cube_ID), |
.control_debug_dont_send_tret(rf_dbg_dont_send_tret), |
.control_debug_halt_on_error_abort(rf_dbg_halt_on_error_abort), |
.control_debug_halt_on_tx_retry(rf_dbg_halt_on_tx_retry), |
.control_rx_token_count(rf_rx_buffer_rtc), |
.control_irtry_received_threshold(rf_irtry_received_threshold), |
.control_irtry_to_send(rf_irtry_to_send), |
.control_bit_slip_time(rf_bit_slip_time) |
); |
end |
endgenerate |
|
endmodule |
|
`default_nettype wire |
`default_nettype wire |
/trunk/openHMC/rtl/hmc_controller/register_file/openhmc_16x_rf.v
File deleted
\ No newline at end of file
/trunk/openHMC/rtl/hmc_controller/register_file/openhmc_8x_rf.v
File deleted
\ No newline at end of file
/trunk/openHMC/rtl/hmc_controller/register_file/openhmc_rf.v
0,0 → 1,598
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
* Module name: openhmc_rf |
* |
*/ |
|
`default_nettype none |
|
module openhmc_rf #( |
parameter NUM_LANES = 8, |
parameter XIL_CNT_PIPELINED = 1, |
parameter LOG_MAX_RX_TOKENS = 8, |
parameter LOG_MAX_HMC_TOKENS= 8, |
parameter RF_COUNTER_SIZE = 64, |
parameter HMC_RF_RWIDTH = 0, |
parameter HMC_RF_AWIDTH = 0, |
parameter HMC_RF_WWIDTH = 0 |
) ( |
input wire clk, |
input wire res_n, |
input wire [HMC_RF_AWIDTH-1:0] address, |
output reg invalid_address, |
output reg access_complete, |
input wire read_en, |
output reg[HMC_RF_RWIDTH-1:0] read_data, |
input wire write_en, |
input wire[HMC_RF_WWIDTH-1:0] write_data, |
input wire status_general_link_up_next, |
input wire status_general_link_training_next, |
input wire status_general_sleep_mode_next, |
input wire status_general_FERR_N_next, |
input wire status_general_lanes_reversed_next, |
input wire status_general_phy_tx_ready_next, |
input wire status_general_phy_rx_ready_next, |
input wire[LOG_MAX_HMC_TOKENS-1:0] status_general_hmc_tokens_remaining_next, |
input wire[LOG_MAX_RX_TOKENS-1:0] status_general_rx_tokens_remaining_next, |
input wire[NUM_LANES-1:0] status_general_lane_polarity_reversed_next, |
input wire[NUM_LANES-1:0] status_init_lane_descramblers_locked_next, |
input wire[NUM_LANES-1:0] status_init_descrambler_part_aligned_next, |
input wire[NUM_LANES-1:0] status_init_descrambler_aligned_next, |
input wire status_init_all_descramblers_aligned_next, |
input wire[2:0] status_init_rx_init_state_next, |
input wire[1:0] status_init_tx_init_state_next, |
output reg control_p_rst_n, |
output reg control_hmc_init_cont_set, |
output reg control_set_hmc_sleep, |
output reg control_warm_reset, |
output reg control_scrambler_disable, |
output reg control_run_length_enable, |
output reg[LOG_MAX_RX_TOKENS-1:0] control_rx_token_count, |
output reg[4:0] control_irtry_received_threshold, |
output reg[4:0] control_irtry_to_send, |
input wire[RF_COUNTER_SIZE-1:0] sent_p_cnt_next, |
input wire[RF_COUNTER_SIZE-1:0] sent_np_cnt_next, |
input wire[RF_COUNTER_SIZE-1:0] sent_r_cnt_next, |
input wire[RF_COUNTER_SIZE-1:0] poisoned_packets_cnt_next, |
input wire[RF_COUNTER_SIZE-1:0] rcvd_rsp_cnt_next, |
input wire tx_link_retries_count_countup, |
input wire errors_on_rx_count_countup, |
input wire run_length_bit_flip_count_countup, |
input wire error_abort_not_cleared_count_countup |
); |
reg status_general_link_up; |
reg status_general_link_training; |
reg status_general_sleep_mode; |
reg status_general_FERR_N; |
reg status_general_lanes_reversed; |
reg status_general_phy_tx_ready; |
reg status_general_phy_rx_ready; |
reg[LOG_MAX_HMC_TOKENS-1:0] status_general_hmc_tokens_remaining; |
reg[LOG_MAX_RX_TOKENS-1:0] status_general_rx_tokens_remaining; |
reg[NUM_LANES-1:0] status_general_lane_polarity_reversed; |
reg[NUM_LANES-1:0] status_init_lane_descramblers_locked; |
reg[NUM_LANES-1:0] status_init_descrambler_part_aligned; |
reg[NUM_LANES-1:0] status_init_descrambler_aligned; |
reg status_init_all_descramblers_aligned; |
reg[2:0] status_init_rx_init_state; |
reg[1:0] status_init_tx_init_state; |
reg[RF_COUNTER_SIZE-1:0] sent_p_cnt; |
reg[RF_COUNTER_SIZE-1:0] sent_np_cnt; |
reg[RF_COUNTER_SIZE-1:0] sent_r_cnt; |
reg[RF_COUNTER_SIZE-1:0] poisoned_packets_cnt; |
reg[RF_COUNTER_SIZE-1:0] rcvd_rsp_cnt; |
reg rreinit; |
wire[47:0] tx_link_retries_count; |
wire[47:0] errors_on_rx_count; |
wire[47:0] run_length_bit_flip_count; |
wire[47:0] error_abort_not_cleared_count; |
|
`ifdef XILINX |
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) tx_link_retries_count_I ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(tx_link_retries_count_countup), |
.value(tx_link_retries_count) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) errors_on_rx_count_I ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(errors_on_rx_count_countup), |
.value(errors_on_rx_count) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) run_length_bit_flip_count_I ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(run_length_bit_flip_count_countup), |
.value(run_length_bit_flip_count) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) error_abort_not_cleared_count_I ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(error_abort_not_cleared_count_countup), |
.value(error_abort_not_cleared_count) |
); |
`else |
openhmc_counter48 #( |
.DATASIZE(48) |
) tx_link_retries_count_I ( |
.clk(clk), |
.res_n(res_n), |
.increment(tx_link_retries_count_countup), |
.load_enable(rreinit), |
.value(tx_link_retries_count) |
); |
|
openhmc_counter48 #( |
.DATASIZE(48) |
) errors_on_rx_count_I ( |
.clk(clk), |
.res_n(res_n), |
.increment(errors_on_rx_count_countup), |
.load_enable(rreinit), |
.value(errors_on_rx_count) |
); |
|
openhmc_counter48 #( |
.DATASIZE(48) |
) run_length_bit_flip_count_I ( |
.clk(clk), |
.res_n(res_n), |
.increment(run_length_bit_flip_count_countup), |
.load_enable(rreinit), |
.value(run_length_bit_flip_count) |
); |
|
openhmc_counter48 #( |
.DATASIZE(48) |
) error_abort_not_cleared_count_I ( |
.clk(clk), |
.res_n(res_n), |
.increment(error_abort_not_cleared_count_countup), |
.load_enable(rreinit), |
.value(error_abort_not_cleared_count) |
); |
`endif |
|
//Register: status_general |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
status_general_link_up <= 1'h0; |
status_general_link_training <= 1'h0; |
status_general_sleep_mode <= 1'h0; |
status_general_FERR_N <= 1'h0; |
status_general_lanes_reversed <= 1'h0; |
status_general_phy_tx_ready <= 1'h0; |
status_general_phy_rx_ready <= 1'h0; |
status_general_hmc_tokens_remaining <= {LOG_MAX_HMC_TOKENS{1'b0}}; |
status_general_rx_tokens_remaining <= {LOG_MAX_RX_TOKENS{1'b0}}; |
status_general_lane_polarity_reversed <= {NUM_LANES{1'b0}}; |
end |
else |
`endif |
begin |
status_general_link_up <= status_general_link_up_next; |
status_general_link_training<= status_general_link_training_next; |
status_general_sleep_mode <= status_general_sleep_mode_next; |
status_general_FERR_N <= status_general_FERR_N_next; |
status_general_lanes_reversed <= status_general_lanes_reversed_next; |
status_general_phy_tx_ready <= status_general_phy_tx_ready_next; |
status_general_phy_rx_ready <= status_general_phy_rx_ready_next; |
status_general_hmc_tokens_remaining <= status_general_hmc_tokens_remaining_next; |
status_general_rx_tokens_remaining <= status_general_rx_tokens_remaining_next; |
status_general_lane_polarity_reversed <= status_general_lane_polarity_reversed_next; |
end |
|
end |
|
//Register: status_init |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
status_init_lane_descramblers_locked<= {NUM_LANES{1'b0}}; |
status_init_descrambler_part_aligned<= {NUM_LANES{1'b0}}; |
status_init_descrambler_aligned <= {NUM_LANES{1'b0}}; |
status_init_all_descramblers_aligned<= 1'h0; |
status_init_rx_init_state <= 3'h0; |
status_init_tx_init_state <= 2'h0; |
end |
else |
`endif |
begin |
status_init_lane_descramblers_locked<= status_init_lane_descramblers_locked_next; |
status_init_descrambler_part_aligned<= status_init_descrambler_part_aligned_next; |
status_init_descrambler_aligned <= status_init_descrambler_aligned_next; |
status_init_all_descramblers_aligned<= status_init_all_descramblers_aligned_next; |
status_init_rx_init_state <= status_init_rx_init_state_next; |
status_init_tx_init_state <= status_init_tx_init_state_next; |
end |
|
end |
|
//Register: control |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
|
if(!res_n) |
begin |
control_p_rst_n <= 1'h0; |
control_hmc_init_cont_set <= 1'b0; |
control_set_hmc_sleep <= 1'h0; |
control_warm_reset <= 1'h0; |
control_scrambler_disable <= 1'h0; |
control_run_length_enable <= 1'h0; |
control_rx_token_count <= {LOG_MAX_RX_TOKENS{1'b1}}; |
control_irtry_received_threshold <= 5'h10; |
control_irtry_to_send <= 5'h18; |
end |
else |
begin |
|
if((address == 2) && write_en) |
begin |
control_p_rst_n <= write_data[0:0]; |
end |
|
if((address == 2) && write_en) |
begin |
control_hmc_init_cont_set <= write_data[1:1]; |
end |
|
if((address == 2) && write_en) |
begin |
control_set_hmc_sleep <= write_data[2:2]; |
end |
|
if((address == 2) && write_en) |
begin |
control_warm_reset <= write_data[3:3]; |
end |
|
if((address == 2) && write_en) |
begin |
control_scrambler_disable <= write_data[4:4]; |
end |
|
if((address == 2) && write_en) |
begin |
control_run_length_enable <= write_data[5:5]; |
end |
|
if((address == 2) && write_en) |
begin |
control_rx_token_count <= write_data[16+LOG_MAX_RX_TOKENS-1:16]; |
end |
|
if((address == 2) && write_en) |
begin |
control_irtry_received_threshold <= write_data[36:32]; |
end |
|
if((address == 2) && write_en) |
begin |
control_irtry_to_send <= write_data[44:40]; |
end |
|
end |
|
end |
|
//Register: sent_p |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
sent_p_cnt <= {RF_COUNTER_SIZE{1'b0}}; |
end |
else |
`endif |
begin |
sent_p_cnt <= sent_p_cnt_next; |
end |
|
end |
|
//Register: sent_np |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
sent_np_cnt <= {RF_COUNTER_SIZE{1'b0}}; |
end |
else |
`endif |
begin |
sent_np_cnt <= sent_np_cnt_next; |
end |
|
end |
|
//Register: sent_r |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
sent_r_cnt <= {RF_COUNTER_SIZE{1'b0}}; |
end |
else |
`endif |
begin |
sent_r_cnt <= sent_r_cnt_next; |
end |
|
end |
|
//Register: poisoned_packets |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
poisoned_packets_cnt <= {RF_COUNTER_SIZE{1'b0}}; |
end |
else |
`endif |
begin |
poisoned_packets_cnt <= poisoned_packets_cnt_next; |
end |
|
end |
|
//Register: rcvd_rsp |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if(!res_n) |
begin |
rcvd_rsp_cnt <= {RF_COUNTER_SIZE{1'b0}}; |
end |
else |
`endif |
begin |
rcvd_rsp_cnt <= rcvd_rsp_cnt_next; |
end |
|
end |
|
//Register: counter_reset |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
|
if(!res_n) |
begin |
rreinit <= 1'b0; |
end |
else |
begin |
|
if((address == 8) && write_en) |
begin |
rreinit <= 1'b1; |
end |
else |
begin |
rreinit <= 1'b0; |
end |
end |
|
end |
|
//Address Decoder Software Read: |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
|
if(!res_n) |
begin |
invalid_address <= 1'b0; |
access_complete <= 1'b0; |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
end |
else |
begin |
|
casex(address) |
4'h0: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[0:0] <= status_general_link_up; |
read_data[1:1] <= status_general_link_training; |
read_data[2:2] <= status_general_sleep_mode; |
read_data[3:3] <= status_general_FERR_N; |
read_data[4:4] <= status_general_lanes_reversed; |
read_data[8:8] <= status_general_phy_tx_ready; |
read_data[9:9] <= status_general_phy_rx_ready; |
read_data[16+LOG_MAX_HMC_TOKENS-1:16] <= status_general_hmc_tokens_remaining; |
read_data[32+LOG_MAX_RX_TOKENS-1:32] <= status_general_rx_tokens_remaining; |
read_data[63:48] <= status_general_lane_polarity_reversed; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h1: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[NUM_LANES-1:0] <= status_init_lane_descramblers_locked; |
read_data[16+NUM_LANES-1:16] <= status_init_descrambler_part_aligned; |
read_data[32+NUM_LANES-1:32] <= status_init_descrambler_aligned; |
read_data[48:48] <= status_init_all_descramblers_aligned; |
read_data[51:49] <= status_init_rx_init_state; |
read_data[53:52] <= status_init_tx_init_state; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h2: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[0:0] <= control_p_rst_n; |
read_data[1:1] <= control_hmc_init_cont_set; |
read_data[2:2] <= control_set_hmc_sleep; |
read_data[3:3] <= control_warm_reset; |
read_data[4:4] <= control_scrambler_disable; |
read_data[5:5] <= control_run_length_enable; |
read_data[16+LOG_MAX_RX_TOKENS-1:16] <= control_rx_token_count; |
read_data[36:32] <= control_irtry_received_threshold; |
read_data[44:40] <= control_irtry_to_send; |
invalid_address <= 1'b0; |
access_complete <= read_en || write_en; |
end |
4'h3: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[RF_COUNTER_SIZE-1:0] <= sent_p_cnt; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h4: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[RF_COUNTER_SIZE-1:0] <= sent_np_cnt; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h5: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[RF_COUNTER_SIZE-1:0] <= sent_r_cnt; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h6: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[RF_COUNTER_SIZE-1:0] <= poisoned_packets_cnt; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h7: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[RF_COUNTER_SIZE-1:0] <= rcvd_rsp_cnt; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'h8: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
invalid_address <= read_en; |
access_complete <= read_en || write_en; |
end |
4'h9: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[47:0] <= tx_link_retries_count; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'ha: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[47:0] <= errors_on_rx_count; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'hb: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[47:0] <= run_length_bit_flip_count; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
4'hc: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
read_data[47:0] <= error_abort_not_cleared_count; |
invalid_address <= write_en; |
access_complete <= read_en || write_en; |
end |
default: |
begin |
read_data <= {HMC_RF_RWIDTH{1'b0}}; |
invalid_address <= read_en || write_en; |
access_complete <= read_en || write_en; |
end |
|
endcase |
end |
|
end |
|
endmodule |
|
`default_nettype wire |
/trunk/openHMC/rtl/hmc_controller/crc/crc_accu.v
42,15 → 42,14
//---------------------------------- |
//----SYSTEM INTERFACE |
//---------------------------------- |
input wire clk , |
input wire res_n , |
input wire clk, |
input wire res_n, |
|
//---------------------------------- |
//----Input |
//---------------------------------- |
input wire [FPW-1:0] tail , |
input wire [(FPW*32)-1:0] d_in , |
input wire [FPW-1:0] valid , |
input wire [FPW-1:0] tail, |
input wire [(FPW*32)-1:0] d_in, |
|
//---------------------------------- |
//----Output |
76,63 → 75,67
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
if (!res_n) begin |
crc_out <= 32'h0; |
crc_temp[0] <= 32'h0; |
end |
else begin |
`ifdef RESET_ALL |
if (!res_n) begin |
crc_out <= 32'h0; |
end else |
`endif |
begin |
crc_out <= 32'h0; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
if(tail[i_f]) begin |
crc_out <= crc_temp[i_f+1]; |
end |
end |
end |
end |
|
if(|tail) begin |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
if (!res_n) |
crc_temp[0] <= 32'h0; |
end else begin |
crc_temp[0] <= crc_temp[FPW]; |
end |
else |
crc_temp[0] <= |tail ? 32'h0 : crc_temp[FPW]; |
end |
end |
|
always @(*) |
begin |
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
crc_temp[i_f+1][31] = in[i_f][31] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][29]; |
crc_temp[i_f+1][30] = in[i_f][30] ^ crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][28]; |
crc_temp[i_f+1][29] = in[i_f][29] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]; |
crc_temp[i_f+1][28] = in[i_f][28] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][27] = in[i_f][27] ^ crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][26] = in[i_f][26] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][25] = in[i_f][25] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][24] = in[i_f][24] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][23] = in[i_f][23] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][29]; |
crc_temp[i_f+1][22] = in[i_f][22] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28]; |
crc_temp[i_f+1][21] = in[i_f][21] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]; |
crc_temp[i_f+1][20] = in[i_f][20] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][31]; |
crc_temp[i_f+1][19] = in[i_f][19] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][18] = in[i_f][18] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28]; |
crc_temp[i_f+1][17] = in[i_f][17] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][31]; |
crc_temp[i_f+1][16] = in[i_f][16] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][15] = in[i_f][15] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][9]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][14] = in[i_f][14] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][13] = in[i_f][13] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][12] = in[i_f][12] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][11] = in[i_f][11] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][10] = in[i_f][10] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27]; |
crc_temp[i_f+1][ 9] = in[i_f][ 9] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 8] = in[i_f][ 8] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][ 7] = in[i_f][ 7] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 6] = in[i_f][ 6] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 5] = in[i_f][ 5] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][ 4] = in[i_f][ 4] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 3] = in[i_f][ 3] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 2] = in[i_f][ 2] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][10]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 1] = in[i_f][ 1] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 0] = in[i_f][ 0] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][27]^crc_temp[i_f][30]; |
end |
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
crc_temp[i_f+1][31] = in[i_f][31] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][29]; |
crc_temp[i_f+1][30] = in[i_f][30] ^ crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][28]; |
crc_temp[i_f+1][29] = in[i_f][29] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]; |
crc_temp[i_f+1][28] = in[i_f][28] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][27] = in[i_f][27] ^ crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][26] = in[i_f][26] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][25] = in[i_f][25] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][24] = in[i_f][24] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][23] = in[i_f][23] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][29]; |
crc_temp[i_f+1][22] = in[i_f][22] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28]; |
crc_temp[i_f+1][21] = in[i_f][21] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]; |
crc_temp[i_f+1][20] = in[i_f][20] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][31]; |
crc_temp[i_f+1][19] = in[i_f][19] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][18] = in[i_f][18] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28]; |
crc_temp[i_f+1][17] = in[i_f][17] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][31]; |
crc_temp[i_f+1][16] = in[i_f][16] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][15] = in[i_f][15] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][9]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][14] = in[i_f][14] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][13] = in[i_f][13] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30]; |
crc_temp[i_f+1][12] = in[i_f][12] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][11] = in[i_f][11] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][10] = in[i_f][10] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27]; |
crc_temp[i_f+1][ 9] = in[i_f][ 9] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 8] = in[i_f][ 8] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][ 7] = in[i_f][ 7] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 6] = in[i_f][ 6] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 5] = in[i_f][ 5] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]; |
crc_temp[i_f+1][ 4] = in[i_f][ 4] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 3] = in[i_f][ 3] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 2] = in[i_f][ 2] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][10]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 1] = in[i_f][ 1] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31]; |
crc_temp[i_f+1][ 0] = in[i_f][ 0] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][27]^crc_temp[i_f][30]; |
end |
end |
|
endmodule |
/trunk/openHMC/rtl/hmc_controller/crc/crc_128_init.v
43,13 → 43,15
//---------------------------------- |
//----SYSTEM INTERFACE |
//---------------------------------- |
input wire clk , |
input wire res_n , |
input wire clk, |
`ifdef RESET_ALL |
input wire res_n, |
`endif |
|
//---------------------------------- |
//----Input |
//---------------------------------- |
input wire [127:0] inData , |
input wire [127:0] inData, |
|
//---------------------------------- |
//----Output |
61,10 → 63,12
always @(posedge clk or negedge res_n) `else |
always @(posedge clk) `endif |
begin |
`ifdef RESET_ALL |
if (!res_n) begin |
crc <= 32'h0; |
end |
else begin |
crc <= 32'h0; |
end else |
`endif |
begin |
crc[31] <= inData[2]^inData[5]^inData[10]^inData[12]^inData[13]^inData[14]^inData[16]^inData[17]^inData[20]^inData[21]^inData[23]^inData[25]^inData[26]^inData[28]^inData[32]^inData[34]^inData[36]^inData[40]^inData[41]^inData[43]^inData[45]^inData[47]^inData[49]^inData[51]^inData[53]^inData[54]^inData[57]^inData[58]^inData[60]^inData[61]^inData[64]^inData[65]^inData[66]^inData[71]^inData[74]^inData[76]^inData[77]^inData[78]^inData[80]^inData[81]^inData[82]^inData[84]^inData[92]^inData[93]^inData[94]^inData[100]^inData[102]^inData[103]^inData[104]^inData[105]^inData[106]^inData[108]^inData[111]^inData[115]^inData[116]^inData[119]^inData[121]^inData[122]^inData[125]^inData[126]; |
crc[30] <= inData[3]^inData[6]^inData[11]^inData[13]^inData[14]^inData[15]^inData[17]^inData[18]^inData[21]^inData[22]^inData[24]^inData[26]^inData[27]^inData[29]^inData[33]^inData[35]^inData[37]^inData[41]^inData[42]^inData[44]^inData[46]^inData[48]^inData[50]^inData[52]^inData[54]^inData[55]^inData[58]^inData[59]^inData[61]^inData[62]^inData[65]^inData[66]^inData[67]^inData[72]^inData[75]^inData[77]^inData[78]^inData[79]^inData[81]^inData[82]^inData[83]^inData[85]^inData[93]^inData[94]^inData[95]^inData[101]^inData[103]^inData[104]^inData[105]^inData[106]^inData[107]^inData[109]^inData[112]^inData[116]^inData[117]^inData[120]^inData[122]^inData[123]^inData[126]^inData[127]; |
crc[29] <= inData[2]^inData[4]^inData[5]^inData[7]^inData[10]^inData[13]^inData[15]^inData[17]^inData[18]^inData[19]^inData[20]^inData[21]^inData[22]^inData[26]^inData[27]^inData[30]^inData[32]^inData[38]^inData[40]^inData[41]^inData[42]^inData[54]^inData[55]^inData[56]^inData[57]^inData[58]^inData[59]^inData[61]^inData[62]^inData[63]^inData[64]^inData[65]^inData[67]^inData[68]^inData[71]^inData[73]^inData[74]^inData[77]^inData[79]^inData[81]^inData[83]^inData[86]^inData[92]^inData[93]^inData[95]^inData[96]^inData[100]^inData[103]^inData[107]^inData[110]^inData[111]^inData[113]^inData[115]^inData[116]^inData[117]^inData[118]^inData[119]^inData[122]^inData[123]^inData[124]^inData[125]^inData[126]^inData[127]; |
/trunk/openHMC/rtl/hmc_controller/rx/rx_descrambler.v
82,6 → 82,7
input wire clk, |
input wire res_n, |
input wire bit_slip, |
input wire can_lock, |
output reg locked, |
input wire [DWIDTH-1:0] data_in, |
output reg [DWIDTH-1:0] data_out |
102,24 → 103,26
end |
endgenerate |
|
`ifdef SIMULATION |
initial begin |
lfsr <= 15'h0; |
end |
`endif |
|
// SEQUENTIAL PROCESS |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if (!res_n) begin |
locked <= 1'b0; |
lfsr <= 15'h0; |
data_out <= {DWIDTH {1'b0}}; |
end else begin |
|
`ifdef RESET_ALL |
if(!res_n) begin |
data_out <= {DWIDTH {1'b0}}; |
lfsr <= 15'h0; |
end else |
`endif |
begin |
data_out <= data_out_tmp; |
|
if (!locked && |data_in) begin |
if (!locked) begin |
lfsr <= calculated_seed; |
// Locked when the calculated seeds match |
if (calculated_seed == lfsr_steps[DWIDTH-1]) begin |
locked <= 1'b1; |
end |
end else begin |
if (bit_slip) begin |
lfsr <= lfsr_slipped; |
126,7 → 129,20
end else begin |
lfsr <= lfsr_steps[DWIDTH-1]; |
end |
end |
end |
|
if(!res_n) begin |
locked <= 1'b0; |
end else begin |
if (!locked) begin |
if (calculated_seed == lfsr_steps[DWIDTH-1]) begin |
locked <= 1'b1; |
end |
end |
if(!can_lock) begin |
locked <= 1'b0; |
end |
end |
end // serial shift right with left input |
|
/trunk/openHMC/rtl/hmc_controller/rx/rx_lane_logic.v
61,6 → 61,7
input wire [LANE_DWIDTH-1:0] scrambled_data_in, |
input wire bit_slip, //bit slip per lane |
input wire lane_polarity, |
input wire can_lock, |
output wire [LANE_DWIDTH-1:0] descrambled_data_out, |
output wire descrambler_locked, |
input wire descrambler_disable |
70,7 → 71,7
wire [LANE_DWIDTH-1:0] descrambled_data_out_tmp; |
wire [LANE_DWIDTH-1:0] data_2_descrambler; |
wire descrambler_locked_tmp; |
assign descrambler_locked = descrambler_disable ? 1'b1 : descrambler_locked_tmp; |
assign descrambler_locked = descrambler_disable ? can_lock : descrambler_locked_tmp; |
|
|
|
88,10 → 89,12
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
`ifdef RESET_ALL |
if(!res_n) begin |
scrambled_data_in_reg <= {LANE_DWIDTH{1'b0}}; |
end |
else begin |
end else |
`endif |
begin |
scrambled_data_in_reg <= scrambled_data_in^{LANE_DWIDTH{lane_polarity}}; |
end |
end |
120,6 → 123,7
) descrambler_I ( |
.clk(clk), |
.res_n(res_n), |
.can_lock(can_lock), |
.bit_slip(bit_slip), |
.locked(descrambler_locked_tmp), |
.data_in(data_2_descrambler), |
/trunk/openHMC/rtl/hmc_controller/rx/rx_crc_compare.v
272,24 → 272,34
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_lng_per_flit_dly[i_f] <= 4'h0; |
`ifdef RESET_ALL |
if(!res_n) d_in_data_dly <= {DWIDTH{1'b0}}; |
else |
`endif |
begin |
d_in_data_dly <= d_in_data; |
end |
d_in_data_dly <= {DWIDTH{1'b0}}; |
d_in_hdr_dly <= {FPW{1'b0}}; |
d_in_tail_dly <= {FPW{1'b0}}; |
d_in_valid_dly <= {FPW{1'b0}}; |
end else begin |
|
`ifdef RESET_ALL |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_lng_per_flit_dly[i_f] <= 4'h0; |
end |
|
d_in_hdr_dly <= {FPW{1'b0}}; |
d_in_tail_dly <= {FPW{1'b0}}; |
d_in_valid_dly <= {FPW{1'b0}}; |
end else |
`endif |
begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_lng_per_flit_dly[i_f] <= d_in_lng_per_flit[i_f]; |
end |
d_in_data_dly <= d_in_data; |
d_in_hdr_dly <= d_in_hdr; |
d_in_tail_dly <= d_in_tail; |
d_in_hdr_dly <= d_in_hdr & d_in_valid; |
d_in_tail_dly <= d_in_tail & d_in_valid; |
d_in_valid_dly <= d_in_valid; |
end |
end |
end |
|
//==================================================================== |
//---------------------------------Inter CRC stage, CRC assignment Logic |
297,9 → 307,20
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
`ifdef RESET_ALL |
if (!res_n) crc_accu_in[i_f] <= {32{1'b0}}; |
else |
`endif |
begin |
crc_accu_in[i_f] <= crc_init_out[i_f]; |
end |
end |
|
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
crc_accu_in[i_f] <= {32{1'b0}}; |
|
crc_accu_in_valid[i_f] <= {FPW{1'b0}}; |
crc_accu_in_tail[i_f] <= {FPW{1'b0}}; |
payload_remain[i_f] <= 4'h0; |
307,14 → 328,12
end else begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
crc_accu_in[i_f] <= crc_init_out[i_f]; |
crc_accu_in_valid[i_f] <= 4'h0; |
crc_accu_in_tail[i_f] <= 4'h0; |
crc_accu_in_tail[i_f] <= 4'h0; |
end |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
//First go through accu crcs |
|
if(|payload_remain[i_f]) begin |
|
if(payload_remain[i_f] > FPW) begin |
332,10 → 351,10
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc |
|
if( (i_f2+d_in_lng_per_flit_dly[i_f2]) >FPW ) begin |
payload_remain[i_f] <= (d_in_lng_per_flit_dly[i_f2]-FPW+i_f2); |
payload_remain[i_f] <= (d_in_lng_per_flit_dly[i_f2]-FPW+i_f2); |
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2 << i_f2; |
end else begin |
crc_accu_in_tail[i_f] <= 1'b1 << d_in_lng_per_flit_dly[i_f2]+i_f2-1; |
crc_accu_in_tail[i_f] <= 1'b1 << d_in_lng_per_flit_dly[i_f2]+i_f2-1; |
crc_accu_in_valid[i_f] <= ({FPW{1'b1}} >> (FPW-i_f2-d_in_lng_per_flit_dly[i_f2])) >> i_f2 << i_f2; |
end |
end |
351,39 → 370,50
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}}; |
crc_data_pipe_in_hdr[i_c] <= {FPW{1'b0}}; |
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}}; |
crc_data_pipe_in_valid[i_c] <= {FPW{1'b0}}; |
|
`ifdef ASYNC_RES |
if (!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}}; |
end |
end else |
`endif |
begin |
//Data forward |
crc_data_pipe_in_data[0] <= d_in_data_dly; |
crc_data_pipe_in_data[1] <= crc_data_pipe_in_data[0]; |
end |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
target_crc_per_tail1[i_f] <= 3'h0; |
end |
end else begin |
`ifdef RESET_ALL |
if(!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_hdr[i_c] <= {FPW{1'b0}}; |
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}}; |
crc_data_pipe_in_valid[i_c] <= {FPW{1'b0}}; |
end |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f]; |
end |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
target_crc_per_tail1[i_f] <= 3'h0; |
end |
end else |
`endif |
begin |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f]; |
end |
|
//Set the first stage of the data pipeline |
crc_data_pipe_in_data[0] <= d_in_data_dly; |
crc_data_pipe_in_hdr[0] <= d_in_hdr_dly; |
crc_data_pipe_in_tail[0] <= d_in_tail_dly; |
crc_data_pipe_in_valid[0] <= d_in_valid_dly; |
//Set the first stage of the data pipeline |
crc_data_pipe_in_hdr[0] <= d_in_hdr_dly; |
crc_data_pipe_in_tail[0] <= d_in_tail_dly; |
crc_data_pipe_in_valid[0] <= d_in_valid_dly; |
|
//Data Pipeline propagation |
for(i_c=0;i_c<(1);i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c+1] <= crc_data_pipe_in_data[i_c]; |
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c]; |
crc_data_pipe_in_hdr[i_c+1] <= crc_data_pipe_in_hdr[i_c]; |
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c]; |
crc_data_pipe_in_valid[i_c+1] <= crc_data_pipe_in_valid[i_c]; |
//Second Stage |
crc_data_pipe_in_tail[1] <= crc_data_pipe_in_tail[0]; |
crc_data_pipe_in_hdr[1] <= crc_data_pipe_in_hdr[0]; |
crc_data_pipe_in_tail[1] <= crc_data_pipe_in_tail[0]; |
crc_data_pipe_in_valid[1] <= crc_data_pipe_in_valid[0]; |
end |
end |
end |
|
//==================================================================== |
//---------------------------------At the end of the data pipeline get and compare the CRCs |
391,21 → 421,29
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
`ifdef ASYNC_RES |
if(!res_n)data_rdy_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
begin // Datapath |
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f]; |
end |
end |
//Propagate |
d_out_hdr <= crc_data_pipe_in_hdr[1]; |
d_out_tail <= crc_data_pipe_in_tail[1]; |
d_out_valid <= crc_data_pipe_in_valid[1]; |
|
if(!res_n) begin |
|
//Reset the outputs |
d_out_hdr <= {FPW{1'b0}}; |
d_out_tail <= {FPW{1'b0}}; |
d_out_valid <= {FPW{1'b0}}; |
d_out_error <= {FPW{1'b0}}; |
d_out_poisoned <= {FPW{1'b0}}; |
d_out_rtc <= {FPW{1'b0}}; |
d_out_flow <= {FPW{1'b0}}; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data_rdy_flit[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
|
d_out_rtc <= {FPW{1'b0}}; |
413,16 → 451,13
d_out_poisoned <= {FPW{1'b0}}; |
d_out_flow <= {FPW{1'b0}}; |
|
//Propagate |
d_out_hdr <= crc_data_pipe_in_hdr[1]; |
d_out_tail <= crc_data_pipe_in_tail[1]; |
d_out_valid <= crc_data_pipe_in_valid[1]; |
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_out_error[i_f] <= crc_data_pipe_in_hdr[1][i_f] && ( ~|lng(crc_data_pipe_out_data_flit[i_f]) |
|| lng(crc_data_pipe_out_data_flit[i_f])>9 |
|| !lng_dln_equal(crc_data_pipe_out_data_flit[i_f])); |
|
//Propagate data |
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f]; |
|
if(crc_data_pipe_in_tail[1][i_f])begin |
//Finally compare the CRC and add flow/rtc information if there is a tail |
|
440,25 → 475,12
d_out_rtc[i_f] <= 1'b1; |
end else begin |
|
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_TRET) || !is_flow(crc_data_pipe_out_data_flit[i_f])) begin |
//All non-flow packets have a valid RTC |
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_TRET) || !is_rsp_flow(crc_data_pipe_out_data_flit[i_f])) begin |
//All non-flow packets have a valid RTC, except TRET |
d_out_rtc[i_f] <= 1'b1; |
end |
if(is_flow(crc_data_pipe_out_data_flit[i_f])) begin |
//Set the flow packet indicator |
d_out_flow[i_f] <= 1'b1; |
|
//Check flow packets zero fields |
if(|adrs(crc_data_pipe_out_data_flit[i_f]) || |tag(crc_data_pipe_out_data_flit[i_f])) begin |
d_out_error[i_f] <= 1'b1; |
end |
if( (cmd(crc_data_pipe_out_data_flit[i_f]) != CMD_TRET) && |
(|rtc(crc_data_pipe_out_data_flit[i_f]) || |seq(crc_data_pipe_out_data_flit[i_f]))) begin |
d_out_error[i_f] <= 1'b1; |
end |
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_PRET) && |frp(crc_data_pipe_out_data_flit[i_f])) begin |
d_out_error[i_f] <= 1'b1; |
end |
if(is_rsp_flow(crc_data_pipe_out_data_flit[i_f])) begin |
d_out_flow[i_f] <= 1'b1; |
end |
end |
|
478,7 → 500,9
crc_128_init crc_init_I |
( |
.clk(clk), |
.res_n(res_n), |
`ifdef ASYNC_RES |
.res_n(res_n), |
`endif |
.inData(d_in_flit_removed_crc[f]), |
.crc(crc_init_out[f]) |
); |
497,7 → 521,6
.res_n(res_n), |
.tail(crc_accu_in_tail[f]), |
.d_in(crc_accu_in_combined[f]), |
.valid(crc_accu_in_valid[f]), |
.crc_out(crc_per_flit[f]) |
); |
end |
504,4 → 527,4
endgenerate |
|
endmodule |
`default_nettype wire |
`default_nettype wire |
/trunk/openHMC/rtl/hmc_controller/rx/rx_link.v
42,18 → 42,25
`default_nettype none |
|
module rx_link #( |
parameter LOG_FPW = 2, |
parameter FPW = 4, |
parameter DWIDTH = FPW*128, |
parameter LOG_NUM_LANES = 3, |
parameter NUM_LANES = 2**LOG_NUM_LANES, |
parameter HMC_PTR_SIZE = 8, |
parameter HMC_RF_RWIDTH = 64, |
//Configure functionality |
parameter LOG_MAX_RTC = 8, |
parameter CTRL_LANE_POLARITY = 1, |
parameter CTRL_LANE_REVERSAL = 1, |
parameter BITSLIP_SHIFT_RIGHT= 1 |
parameter LOG_FPW = 2, |
parameter FPW = 4, |
parameter DWIDTH = FPW*128, |
parameter LOG_NUM_LANES = 3, |
parameter NUM_LANES = 2**LOG_NUM_LANES, |
parameter HMC_PTR_SIZE = 8, |
parameter RF_COUNTER_SIZE = 64, |
//Set Token Related |
parameter LOG_MAX_RX_TOKENS = 8, |
parameter MAX_RTC_RET_LOG = 8, |
//Control |
parameter XIL_CNT_PIPELINED = 0, |
parameter CTRL_LANE_POLARITY = 1, |
parameter RX_RELAX_INIT_TIMING = 1, |
parameter RX_BIT_SLIP_CNT_LOG = 5, |
parameter DETECT_LANE_POLARITY = 1, |
parameter CTRL_LANE_REVERSAL = 1, |
parameter BITSLIP_SHIFT_RIGHT = 1, |
parameter OPEN_RSP_MODE = 0 |
) ( |
|
//---------------------------------- |
61,23 → 68,22
//---------------------------------- |
input wire clk, |
input wire res_n, |
input wire run_rx, |
|
//---------------------------------- |
//----TO HMC PHY |
//---------------------------------- |
input wire [DWIDTH-1:0] phy_scrambled_data_in, |
output reg [NUM_LANES-1:0] init_bit_slip, //bit slip per lane |
input wire [DWIDTH-1:0] phy_scrambled_data_in, |
output reg [NUM_LANES-1:0] phy_bit_slip, |
|
//---------------------------------- |
//----TO RX HTAX FIFO |
//---------------------------------- |
output reg [DWIDTH-1:0] d_out_fifo_data, |
input wire d_out_fifo_full, |
output wire [DWIDTH-1:0] d_out_fifo_data, |
input wire d_out_fifo_a_full, |
output reg d_out_fifo_shift_in, |
output reg [4*FPW-1:0] d_out_fifo_ctrl, |
output wire d_out_fifo_shift_in, |
output wire [4*FPW-1:0] d_out_fifo_ctrl, |
|
|
//---------------------------------- |
//----TO TX Block |
//---------------------------------- |
84,35 → 90,32
output reg tx_link_retry, |
output reg tx_error_abort_mode, |
output reg tx_error_abort_mode_cleared, |
output reg [7:0] tx_hmc_frp, |
output reg [7:0] tx_rrp, |
output reg [7:0] tx_returned_tokens, |
output reg [LOG_FPW:0] tx_hmc_tokens_to_return, |
output reg [LOG_FPW:0] tx_hmc_poisoned_tokens_to_return, |
output reg [7:0] tx_hmc_frp, |
output reg [7:0] tx_rrp, |
output reg [MAX_RTC_RET_LOG-1:0] tx_returned_tokens, |
output wire [LOG_FPW:0] tx_hmc_tokens_to_return, |
output wire [LOG_FPW:0] tx_hmc_poisoned_tokens_to_return, |
|
//---------------------------------- |
//----RF |
//---------------------------------- |
//Monitoring 1-cycle set to increment |
output reg [HMC_RF_RWIDTH-1:0] rf_cnt_poisoned, |
output reg [HMC_RF_RWIDTH-1:0] rf_cnt_rsp, |
output wire [RF_COUNTER_SIZE-1:0] rf_cnt_poisoned, |
output wire [RF_COUNTER_SIZE-1:0] rf_cnt_rsp, |
//Status |
output reg [1:0] rf_link_status, |
output reg [2:0] rf_hmc_init_status, |
input wire rf_tx_sends_ts1, |
output reg rf_link_up, |
output reg [2:0] rf_rx_init_status, |
input wire rf_hmc_sleep, |
//Init Status |
output wire [NUM_LANES-1:0] rf_descrambler_part_aligned, |
output wire [NUM_LANES-1:0] rf_descrambler_aligned, |
output wire [NUM_LANES-1:0] rf_descrambler_part_aligned, |
output wire [NUM_LANES-1:0] rf_descrambler_aligned, |
output wire rf_all_descramblers_aligned, |
//Control |
input wire [5:0] rf_bit_slip_time, |
input wire rf_hmc_init_cont_set, |
output reg [NUM_LANES-1:0] rf_lane_polarity, |
output wire [NUM_LANES-1:0] rf_lane_polarity, |
input wire rf_scrambler_disable, |
output reg rf_lane_reversal_detected, |
output reg [NUM_LANES-1:0] rf_descramblers_locked, |
input wire [4:0] rf_irtry_received_threshold |
output wire rf_lane_reversal_detected, |
output reg [NUM_LANES-1:0] rf_descramblers_locked, |
input wire [4:0] rf_irtry_received_threshold |
|
); |
`include "hmc_field_functions.h" |
124,17 → 127,19
//===================================================================================================== |
|
//------------------------------------------------------------------------------------Some general things |
//Link state |
localparam HMC_DOWN = 3'b000; |
localparam HMC_NULL = 3'b001; |
localparam HMC_TS1 = 3'b010; |
localparam HMC_UP = 3'b100; |
//Link state -- Most likely will be encoded as one-hot FSM |
localparam HMC_DOWN = 3'b000; |
localparam HMC_WAIT_FOR_NULL = 3'b001; |
localparam HMC_NULL = 3'b010; |
localparam HMC_TS1_PART_ALIGN = 3'b011; |
localparam HMC_TS1_FIND_REF = 3'b100; |
localparam HMC_TS1_ALIGN = 3'b101; |
localparam HMC_NULL_NEXT = 3'b110; |
localparam HMC_UP = 3'b111; |
|
//Commands |
localparam CMD_IRTRY = 3'b011; |
localparam CMD_FLOW = 3'b000; |
localparam CMD_RSP = 3'b111; |
localparam CMD_RSP_ERROR = 6'b111110; |
localparam CMD_IRTRY = 6'b000011; |
localparam CMD_RSP_ERROR = 6'b111110; |
|
//Other helpful defines |
localparam WIDTH_PER_LANE = (DWIDTH/NUM_LANES); |
158,16 → 163,16
assign rf_descrambler_aligned = init_descrambler_aligned; |
|
//DATA and REORDERING |
reg [WIDTH_PER_LANE-1:0] init_data_per_lane [NUM_LANES-1:0]; |
wire [DWIDTH-1:0] init_d_in; |
wire [128-1:0] init_d_in_flit [FPW-1:0]; |
wire [WIDTH_PER_LANE-1:0] descrambled_data_per_lane [NUM_LANES-1:0]; |
reg [WIDTH_PER_LANE-1:0] descrambled_data_per_lane_dly [NUM_LANES-1:0]; |
wire [DWIDTH-1:0] d_in; |
wire [DWIDTH-1:0] d_in_dly; |
wire [128-1:0] d_in_flit [FPW-1:0]; |
|
//Valid FLIT sources. A FLIT is valid when it is not NULL |
wire [FPW-1:0] valid_flit_src; //bit0 = flit0, ... |
wire [FPW-1:0] init_valid_flit_src; //bit0 = flit0, ... |
wire [FPW-1:0] valid_flit_src; //bit0 = flit0, ... |
wire [FPW-1:0] init_valid_flit_src; //bit0 = flit0, ... |
|
generate |
|
176,10 → 181,10
for(w = 0; w < WIDTH_PER_LANE; w = w + 1) begin |
if(CTRL_LANE_REVERSAL==1)begin |
assign d_in[w*NUM_LANES+n] = rf_lane_reversal_detected ? descrambled_data_per_lane[NUM_LANES-1-n][w] : descrambled_data_per_lane[n][w]; |
assign init_d_in[w*NUM_LANES+n] = rf_lane_reversal_detected ? init_data_per_lane[NUM_LANES-1-n][w] : init_data_per_lane[n][w]; |
assign d_in_dly[w*NUM_LANES+n] = rf_lane_reversal_detected ? descrambled_data_per_lane_dly[NUM_LANES-1-n][w] : descrambled_data_per_lane_dly[n][w]; |
end else begin |
assign d_in[w*NUM_LANES+n] = descrambled_data_per_lane[n][w]; |
assign init_d_in[w*NUM_LANES+n] = init_data_per_lane[n][w]; |
assign d_in_dly[w*NUM_LANES+n] = descrambled_data_per_lane_dly[n][w]; |
end |
end |
end |
188,10 → 193,10
for(f = 0; f < FPW; f = f + 1) begin : reorder_input_data |
//-- Reorder the descrambled data to FLITs |
assign d_in_flit[f] = d_in[128-1+(f*128):f*128]; |
assign init_d_in_flit[f] = init_d_in[128-1+(f*128):f*128]; |
//-- Generate valid flit positions for the init sequence |
assign valid_flit_src[f] = (|d_in_flit[f] == 1'b0) ? 1'b0 : 1'b1; |
assign init_valid_flit_src[f] = (|init_d_in_flit[f] == 1'b0) ? 1'b0 : 1'b1; |
assign init_d_in_flit[f] = d_in_dly[128-1+(f*128):f*128]; |
//-- Generate valid flit positions |
assign valid_flit_src[f] = |d_in_flit[f][5:0]; |
assign init_valid_flit_src[f] = |init_d_in_flit[f]; |
end |
|
endgenerate |
198,62 → 203,62
|
|
//------------------------------------------------------------------------------------INIT |
localparam LINK_DOWN = 2'b00; |
localparam LINK_INIT = 2'b01; |
localparam LINK_UP = 2'b10; |
localparam LINK_DOWN = 1'b0; |
localparam LINK_UP = 1'b1; |
|
reg [5:0] init_bit_slip_cnt; |
reg [4:0] init_wait_time; |
wire [NUM_LANES-1:0] init_descrambler_locked; //locked from the descrambler |
wire link_is_up; |
reg [3:0] init_tmp_seq; |
reg init_prbs_seen; |
reg [NUM_LANES-1:0] init_bit_slip; |
reg [NUM_LANES-1:0] init_bit_slip_part; |
reg [RX_BIT_SLIP_CNT_LOG-1:0]init_bit_slip_cnt; |
wire[NUM_LANES-1:0] init_descrambler_locked; //locked from the descrambler |
reg [3:0] init_tmp_seq; |
|
assign link_is_up = rf_link_status[1]; |
assign rf_all_descramblers_aligned = &init_descrambler_aligned; |
|
//--------------TS1 recognition |
localparam ts1_independent_portion = {4'hF,4'h0}; |
localparam ts1_lanex_portion = {4'h5}; |
localparam ts1_lane7or15_portion = 4'hc; |
localparam ts1_lane0_portion = 4'h3; |
localparam TS1_INDEPENDENT_PORTION = {4'hF,4'h0}; |
localparam TS1_LANE0_PORTION = 4'h3; //Not used if RX_RELAX_INIT_TIMING==1 |
localparam TS1_LANEX_PORTION = 4'h5; //Not used if RX_RELAX_INIT_TIMING==1 |
localparam TS1_LANE7OR15_PORTION = 4'hc; |
|
localparam ts1_per_cycle_and_lane = DWIDTH/NUM_LANES/16; |
localparam TS1_SEQS_PER_CYCLE_AND_LANE = DWIDTH/NUM_LANES/16; |
|
wire [NUM_LANES-1:0] init_lane_has_correct_ts1; |
wire [ts1_per_cycle_and_lane-1:0] init_lane_has_correct_ts1_vec [NUM_LANES-1:0]; |
wire [NUM_LANES-1:0] init_lane_has_correct_ts1; |
wire [TS1_SEQS_PER_CYCLE_AND_LANE-1:0]init_lane_has_correct_ts1_vec [NUM_LANES-1:0]; |
|
genvar t; |
generate |
//Make sure that the lanes have valid ts1 sequences throughout the entire data stream |
for(n=0;n<NUM_LANES;n=n+1) begin : lane_has_correct_ts1_gen |
|
assign init_lane_has_correct_ts1[n] = &init_lane_has_correct_ts1_vec[n]; |
end |
|
for(t=0;t<ts1_per_cycle_and_lane;t=t+1) begin |
if(n==0 || n==NUM_LANES-1) begin |
assign init_lane_has_correct_ts1_vec[n][t] = (init_data_per_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lane7or15_portion}) |
|| |
(init_data_per_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lane0_portion}); |
end else begin |
assign init_lane_has_correct_ts1_vec[n][t] = (init_data_per_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lanex_portion}); |
for(t=0;t<TS1_SEQS_PER_CYCLE_AND_LANE;t=t+1) begin : ts1_recognition_gen |
if(RX_RELAX_INIT_TIMING==1) begin |
for(n=0;n<NUM_LANES;n=n+1) begin |
assign init_lane_has_correct_ts1_vec[n][t] = (descrambled_data_per_lane[n][(t*16)+8+:8] == {TS1_INDEPENDENT_PORTION}); |
end |
end else begin |
for(n=1;n<NUM_LANES-1;n=n+1) begin |
assign init_lane_has_correct_ts1_vec[n][t] = (descrambled_data_per_lane[n][(t*16)+4+:12] == {TS1_INDEPENDENT_PORTION,TS1_LANEX_PORTION}); |
end |
assign init_lane_has_correct_ts1_vec[0][t] = (descrambled_data_per_lane[0][(t*16)+4+:12] == {TS1_INDEPENDENT_PORTION,TS1_LANE0_PORTION})|| |
(CTRL_LANE_REVERSAL==1 ? descrambled_data_per_lane[0][(t*16)+4+:12] == {TS1_INDEPENDENT_PORTION,TS1_LANE7OR15_PORTION} : 0); |
assign init_lane_has_correct_ts1_vec[NUM_LANES-1][t] = (descrambled_data_per_lane[NUM_LANES-1][(t*16)+4+:12] == {TS1_INDEPENDENT_PORTION,TS1_LANE7OR15_PORTION})|| |
(CTRL_LANE_REVERSAL==1 ? descrambled_data_per_lane[NUM_LANES-1][(t*16)+4+:12] == {TS1_INDEPENDENT_PORTION,TS1_LANE0_PORTION} : 0); |
end |
end |
endgenerate |
|
//--------------Align the lanes, scan for the ts1 seq |
reg [LOG_NUM_LANES-1:0] init_lane_cnt; |
wire [3:0] init_seq_diff; |
wire [LOG_NUM_LANES-1:0] init_lane_cnt; |
assign init_lane_cnt = init_bit_slip_cnt[LOG_NUM_LANES-1:0]; |
wire [3:0] init_seq_diff; |
|
//If one of the descramblers is already partially aligned search for other lanes with their ts1 sequence number close this lane. |
assign init_seq_diff = |init_descrambler_part_aligned ? |
(BITSLIP_SHIFT_RIGHT==1 ? (init_data_per_lane[init_lane_cnt][3:0] - init_tmp_seq) |
: init_tmp_seq - init_data_per_lane[init_lane_cnt][3:0]) |
: 0; |
assign init_seq_diff = (BITSLIP_SHIFT_RIGHT==1 ? (descrambled_data_per_lane[init_lane_cnt][3:0] - init_tmp_seq) |
: init_tmp_seq - descrambled_data_per_lane[init_lane_cnt][3:0]); |
|
//------------------------------------------------------------------------------------Input Stage: Scan for Packets, Headers, Tails ... |
reg [DWIDTH-1:0] data2crc; |
reg [FPW-1:0] data2crc_hdr; |
reg [FPW-1:0] data2crc_tail; |
reg [FPW-1:0] data2crc_valid; |
268,8 → 273,8
reg [3:0] data2crc_payload_remain_comb; |
|
generate |
for(f = 0; f < (FPW); f = f + 1) begin |
assign data2crc_lng[(f*4)+4-1:(f*4)] = data2crc_lng_per_flit[f]; |
for(f = 0; f < (FPW); f = f + 1) begin : reorder_crc_input |
assign data2crc_lng[(f*4)+:4] = data2crc_lng_per_flit[f]; |
end |
endgenerate |
|
290,29 → 295,18
end |
endgenerate |
|
//------------------------------------------------------------------------------------LNG and DLN stage |
reg [128-1:0] flit_after_lng_check [FPW-1:0]; |
reg [FPW-1:0] flit_after_lng_check_is_hdr; |
reg [FPW-1:0] flit_after_lng_check_is_tail; |
reg [FPW-1:0] flit_after_lng_check_is_valid; |
reg [FPW-1:0] flit_after_lng_check_is_error; |
reg [FPW-1:0] flit_after_lng_check_is_poisoned; |
reg [FPW-1:0] flit_after_lng_check_is_flow; |
reg [FPW-1:0] flit_after_lng_check_has_rtc; |
|
//------------------------------------------------------------------------------------Start TX retry Stage |
reg [128-1:0] flit_after_retry_stage [FPW-1:0]; |
reg [FPW-1:0] flit_after_retry_stage_is_hdr; |
reg [FPW-1:0] flit_after_retry_stage_is_tail; |
reg [FPW-1:0] flit_after_retry_stage_is_valid; |
reg [FPW-1:0] flit_after_retry_stage_is_valid_mask_msb; |
reg [FPW-1:0] flit_after_retry_stage_is_valid_mask_lsb; |
reg [FPW-1:0] flit_after_retry_stage_is_error; |
reg [FPW-1:0] flit_after_retry_stage_is_poisoned; |
reg [FPW-1:0] flit_after_retry_stage_is_flow; |
reg [FPW-1:0] flit_after_retry_stage_has_rtc; |
reg [FPW-1:0] flit_after_retry_stage_is_start_retry; |
reg [FPW-1:0] flit_after_retry_stage_is_start_retry_comb; |
reg [128-1:0] flit_after_irtry_stage [FPW-1:0]; |
reg [FPW-1:0] flit_after_irtry_stage_is_hdr; |
reg [FPW-1:0] flit_after_irtry_stage_is_tail; |
reg [FPW-1:0] flit_after_irtry_stage_is_valid; |
reg [FPW-1:0] flit_after_irtry_stage_is_error; |
reg [FPW-1:0] flit_after_irtry_stage_is_poisoned; |
reg [FPW-1:0] flit_after_irtry_stage_has_rtc; |
reg [FPW-1:0] flit_after_irtry_stage_is_start_retry; |
reg [FPW-1:0] flit_after_irtry_stage_is_clear_error; |
reg [FPW-1:0] flit_after_irtry_stage_is_start_retry_comb; |
reg [FPW-1:0] flit_after_irtry_stage_is_clear_error_comb; |
|
//------------------------------------------------------------------------------------SeqStage and Seqnum |
reg [128-1:0] flit_after_seq_check [FPW-1:0]; |
322,20 → 316,41
reg [FPW-1:0] flit_after_seq_check_is_error; |
reg [FPW-1:0] flit_after_seq_check_is_error_comb; |
reg [FPW-1:0] flit_after_seq_check_is_poisoned; |
reg [FPW-1:0] flit_after_seq_check_is_flow; |
reg [FPW-1:0] flit_after_seq_check_has_rtc; |
reg [FPW-1:0] flit_after_seq_check_is_start_retry; |
reg [FPW-1:0] flit_after_seq_check_is_clear_error; |
|
reg [2:0] next_seqnum; |
reg [2:0] next_seqnum_comb; //use param instead |
reg [2:0] next_seqnum_comb; //can be reduced to [1:0] for 2FLIT config |
reg [2:0] first_seq_after_error; |
|
//------------------------------------------------------------------------------------IRTRY packet count stage |
reg [128-1:0] flit_after_mask_stage [FPW-1:0]; |
reg [FPW-1:0] flit_after_mask_stage_is_hdr; |
reg [FPW-1:0] flit_after_mask_stage_is_tail; |
reg [FPW-1:0] flit_after_mask_stage_is_valid; |
reg [FPW-1:0] flit_after_mask_stage_is_valid_mask_lsb; |
reg [FPW-1:0] flit_after_mask_stage_is_valid_mask_msb; |
reg [FPW-1:0] flit_after_mask_stage_is_error; |
reg [FPW-1:0] flit_after_mask_stage_is_poisoned; |
reg [FPW-1:0] flit_after_mask_stage_is_start_retry; |
reg [FPW-1:0] flit_after_mask_stage_has_rtc; |
|
|
//Assign FLITs to word, necessary for the invalidation stage pipeline |
wire [DWIDTH-1:0] flit_after_mask_stage_word; |
generate |
for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_to_word |
assign flit_after_mask_stage_word[(f*128)+128-1:(f*128)] = flit_after_mask_stage[f]; |
end |
endgenerate |
|
//------------------------------------------------------------------------------------Invalidation Stage |
//Assuming Max Pkt size = 9 FLITs |
localparam CYCLES_TO_COMPLETE_FULL_PACKET = (FPW == 2) ? 5 : |
(FPW == 4) ? 3 : //Assuming Max Pkt size = 9 FLITs |
(FPW == 4) ? 3 : |
(FPW == 6) ? 3 : |
(FPW == 8) ? 2 : |
1; |
2; |
|
//Regs to retrieve the pkt length, assign the length to correspoding tail. The packet will be invalidated then |
reg [3:0] lng_per_tail [FPW-1:0] ; |
342,17 → 357,9
reg [3:0] lng_per_tail_comb [FPW-1:0] ; |
reg [3:0] lng_temp; |
reg [3:0] lng_comb; |
//Signal that an error was detected. Invalid all FLITs after |
reg error_detected; |
//Signal that an error was detected. Invalidate all FLITs after |
reg error; |
|
//Assign FLITs to word, necessary for the invalidation stage pipeline |
wire [DWIDTH-1:0] flit_after_seq_check_word; |
generate |
for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_after_seq_to_word |
assign flit_after_seq_check_word[(f*128)+128-1:(f*128)] = flit_after_seq_check[f]; |
end |
endgenerate |
|
reg [DWIDTH-1:0] flit_in_invalidation_data [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
reg [FPW-1:0] flit_in_invalidation_is_hdr [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
reg [FPW-1:0] flit_in_invalidation_is_tail [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
360,9 → 367,6
reg [FPW-1:0] flit_in_invalidation_mask_error; |
reg [FPW-1:0] flit_in_invalidation_is_poisoned [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
reg [FPW-1:0] flit_in_invalidation0_is_poisoned_comb; |
reg [FPW-1:0] flit_in_invalidation_is_flow [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
reg [FPW-1:0] flit_in_invalidation_has_rtc [CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
reg [FPW-1:0] flit_in_invalidation_is_start_retry[CYCLES_TO_COMPLETE_FULL_PACKET-1:0]; |
|
//------------------------------------------------------------------------------------Checked FLITs |
wire [128-1:0] checked_flit [FPW-1:0]; |
370,17 → 374,11
wire [FPW-1:0] checked_flit_is_valid; |
wire [FPW-1:0] checked_flit_is_hdr; |
wire [FPW-1:0] checked_flit_is_tail; |
wire [FPW-1:0] checked_flit_has_rtc; |
wire [FPW-1:0] checked_flit_is_flow; |
wire [FPW-1:0] checked_flit_is_start_retry; |
|
assign checked_flit_is_hdr = flit_in_invalidation_is_hdr [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
assign checked_flit_is_tail = flit_in_invalidation_is_tail [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
assign checked_flit_is_valid = flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1] ; |
assign checked_flit_is_poisoned = flit_in_invalidation_is_poisoned [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
assign checked_flit_is_flow = flit_in_invalidation_is_flow [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
assign checked_flit_has_rtc = flit_in_invalidation_has_rtc [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
assign checked_flit_is_start_retry = flit_in_invalidation_is_start_retry[CYCLES_TO_COMPLETE_FULL_PACKET-1]; |
|
generate |
for(f = 0; f < (FPW); f = f + 1) begin : reorder_invalidation_word_back_to_flits |
389,16 → 387,14
endgenerate |
|
//------------------------------------------------------------------------------------Counter |
reg [LOG_FPW:0] rf_cnt_poisoned_comb; |
reg [LOG_FPW:0] rf_cnt_rsp_comb; |
reg [LOG_FPW:0] rf_cnt_poisoned_comb; |
reg [LOG_FPW:0] rf_cnt_rsp_comb; |
|
//------------------------------------------------------------------------------------Input Buffer |
reg [LOG_FPW:0] tokens_out_of_fifo_sum_comb; |
reg [LOG_FPW:0] tokens_poisoned; |
reg [7:0] rtc_sum_comb; //for 8 FLIT config, maximum 8*31 tokens will be returned per cycle |
reg [MAX_RTC_RET_LOG-1:0]rtc_sum_comb; //for 8 FLIT config, maximum 8*31 tokens will be returned per cycle |
|
reg [128-1:0] input_buffer_d_in_flit [FPW-1:0]; |
reg [FPW-1:0] input_buffer_valid; |
reg [FPW-1:0] input_buffer_is_valid; |
reg [FPW-1:0] input_buffer_is_hdr; |
reg [FPW-1:0] input_buffer_is_tail; |
reg [FPW-1:0] input_buffer_is_error_rsp; |
405,7 → 401,7
wire [DWIDTH+(4*FPW)-1:0] input_buffer_d_in; |
wire [DWIDTH+(4*FPW)-1:0] input_buffer_d_out; |
wire input_buffer_empty; |
reg input_buffer_shift_in; |
wire input_buffer_shift_in; |
wire input_buffer_shift_out; |
assign input_buffer_shift_out = ~(input_buffer_empty || d_out_fifo_a_full); |
|
412,7 → 408,7
generate |
for(f = 0; f < (FPW); f = f + 1) begin : assign_flits_to_input_buffer_to_a_single_reg |
assign input_buffer_d_in[f*128+128-1:f*128] = input_buffer_d_in_flit[f]; |
assign input_buffer_d_in[DWIDTH+f] = input_buffer_valid[f]; |
assign input_buffer_d_in[DWIDTH+f] = input_buffer_is_valid[f]; |
assign input_buffer_d_in[DWIDTH+f+FPW] = input_buffer_is_hdr[f]; |
assign input_buffer_d_in[DWIDTH+f+(2*FPW)] = input_buffer_is_tail[f]; |
assign input_buffer_d_in[DWIDTH+f+(3*FPW)] = input_buffer_is_error_rsp[f]; |
420,12 → 416,11
endgenerate |
|
//------------------------------------------------------------------------------------LINK RETRY |
reg [5:0] irtry_start_retry_cnt; |
reg [5:0] irtry_clear_error_cnt; |
reg [5:0] irtry_start_retry_cnt_comb; |
reg [5:0] irtry_clear_error_cnt_comb; |
reg [4:0] irtry_start_retry_cnt; |
reg [4:0] irtry_clear_error_cnt; |
reg [4:0] irtry_start_retry_cnt_comb; |
reg [4:0] irtry_clear_error_cnt_comb; |
reg irtry_clear_trig; |
reg irtry_clear_trig_comb; |
|
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
436,133 → 431,159
//======================================================================================================================================== |
//------------------------------------------------------------------INIT |
//======================================================================================================================================== |
always @(posedge clk) begin |
for(i_l = 0;i_l<NUM_LANES;i_l=i_l+1)begin |
init_data_per_lane[i_l] <= descrambled_data_per_lane[i_l]; |
|
generate |
if(CTRL_LANE_REVERSAL==1) begin : control_lane_reversal |
reg init_lane_reversal_detected; |
assign rf_lane_reversal_detected = init_lane_reversal_detected; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
init_lane_reversal_detected <= 1'b0; |
end else begin |
if(rf_rx_init_status==HMC_DOWN) begin |
init_lane_reversal_detected <= 1'b0; |
end |
if(rf_rx_init_status==HMC_TS1_ALIGN && rf_all_descramblers_aligned && (descrambled_data_per_lane[0][7:4] == TS1_LANE7OR15_PORTION)) begin |
//lane reversal detected, reverse the input stream lane by lane |
init_lane_reversal_detected <= 1'b1; |
end |
end |
end |
end else begin |
assign rf_lane_reversal_detected = 1'b0; |
end |
end |
|
if(DETECT_LANE_POLARITY==1) begin : detect_lane_reversal |
reg [NUM_LANES-1:0] init_lane_polarity; |
assign rf_lane_polarity = init_lane_polarity; |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
init_lane_polarity <= {NUM_LANES{1'b0}}; |
end else begin |
if(rf_rx_init_status==HMC_DOWN) begin |
init_lane_polarity <= {NUM_LANES{1'b0}}; |
end |
//Detect Lane polarity when HMC is sending first NULLs |
if(rf_rx_init_status==HMC_WAIT_FOR_NULL) begin |
for(i_l = 0;i_l<NUM_LANES;i_l=i_l+1)begin |
if(descrambled_data_per_lane[i_l] == {WIDTH_PER_LANE{1'b1}})begin |
init_lane_polarity[i_l] <= 1'b1; |
end |
end |
end |
end |
end |
end else begin |
assign rf_lane_polarity = {NUM_LANES{1'b0}}; |
end |
endgenerate |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_l = 0;i_l<NUM_LANES;i_l=i_l+1)begin |
`ifdef RESET_ALL |
if(!res_n) descrambled_data_per_lane_dly[i_l] <= {WIDTH_PER_LANE{1'b0}}; |
else |
`endif |
descrambled_data_per_lane_dly[i_l] <= descrambled_data_per_lane[i_l]; |
end |
|
if(!res_n) begin |
//----Misc |
init_descrambler_aligned <= {NUM_LANES{1'b0}}; |
init_descrambler_part_aligned <= {NUM_LANES{1'b0}}; |
init_bit_slip <= {NUM_LANES{1'b0}}; |
init_bit_slip_cnt <= 6'h0; |
init_wait_time <= 5'h0; |
init_tmp_seq <= 4'h0; |
init_lane_cnt <= {LOG_NUM_LANES{1'b0}}; |
init_prbs_seen <= 1'b0; |
rf_hmc_init_status <= HMC_DOWN; |
rf_link_status <= LINK_DOWN; |
rf_lane_polarity <= {NUM_LANES{1'b0}}; |
rf_lane_reversal_detected <= 1'b0; |
rf_descramblers_locked <= {NUM_LANES{1'b0}}; |
init_descrambler_aligned <= {NUM_LANES{1'b0}}; |
init_descrambler_part_aligned <= {NUM_LANES{1'b0}}; |
phy_bit_slip <= {NUM_LANES{1'b0}}; |
init_bit_slip <= {NUM_LANES{1'b0}}; |
init_bit_slip_part <= {NUM_LANES{1'b0}}; |
init_bit_slip_cnt <= {RX_BIT_SLIP_CNT_LOG{1'b0}}; |
init_tmp_seq <= 4'h0; |
rf_rx_init_status <= HMC_DOWN; |
rf_link_up <= LINK_DOWN; |
rf_descramblers_locked <= {NUM_LANES{1'b0}}; |
|
end |
else begin |
|
rf_descramblers_locked <= init_descrambler_locked; |
rf_descramblers_locked <= run_rx ? init_descrambler_locked : {NUM_LANES{1'b0}}; |
init_bit_slip <= {NUM_LANES{1'b0}}; |
init_bit_slip_part <= {NUM_LANES{1'b0}}; |
phy_bit_slip <= init_bit_slip | init_bit_slip_part; |
init_tmp_seq <= init_tmp_seq + INIT_SEQ_INC_PER_CYCLE; |
|
init_bit_slip_cnt <= init_bit_slip_cnt +1; |
|
if(rf_hmc_sleep || !rf_hmc_init_cont_set) begin |
rf_link_status <= LINK_DOWN; |
end else if(rf_link_status == LINK_DOWN) begin |
//Begin (Re-)Init |
init_descrambler_aligned <= {NUM_LANES{1'b0}}; |
init_descrambler_part_aligned <= {NUM_LANES{1'b0}}; |
init_wait_time <= 5'h1f; |
init_tmp_seq <= 4'h0; |
init_lane_cnt <= {LOG_NUM_LANES{1'b0}}; |
init_prbs_seen <= 1'b0; |
rf_hmc_init_status <= HMC_DOWN; |
rf_link_status <= LINK_INIT; |
rf_lane_polarity <= {NUM_LANES{1'b0}}; |
rf_lane_reversal_detected <= 1'b0; |
rf_descramblers_locked <= {NUM_LANES{1'b0}}; |
end |
|
//Detect Lane polarity when HMC is sending first NULLs |
if(&rf_descramblers_locked && rf_link_status == LINK_INIT) begin |
for(i_l = 0;i_l<NUM_LANES;i_l=i_l+1)begin |
if(init_data_per_lane[i_l] == {WIDTH_PER_LANE{1'b1}})begin |
rf_lane_polarity[i_l] <= 1'b1; |
case (rf_rx_init_status) |
HMC_DOWN: begin |
init_descrambler_aligned <= {NUM_LANES{1'b0}}; |
init_descrambler_part_aligned <= {NUM_LANES{1'b0}}; |
if(&rf_descramblers_locked) begin |
rf_rx_init_status <= HMC_WAIT_FOR_NULL; |
end |
end |
end |
HMC_WAIT_FOR_NULL: begin |
if(|init_valid_flit_src == 1'b0) begin |
rf_rx_init_status <= HMC_NULL; |
end |
end |
HMC_NULL: begin |
if(&init_valid_flit_src) begin |
rf_rx_init_status <= HMC_TS1_PART_ALIGN; |
end |
end |
HMC_TS1_PART_ALIGN: begin |
if(|init_bit_slip_cnt[RX_BIT_SLIP_CNT_LOG-1:LOG_NUM_LANES] == 1'b0)begin |
init_bit_slip_part[init_lane_cnt] <= ~init_lane_has_correct_ts1[init_lane_cnt]; |
init_descrambler_part_aligned[init_lane_cnt] <= init_lane_has_correct_ts1[init_lane_cnt]; |
end |
if(&init_descrambler_part_aligned/*=={NUM_LANES{1'b1}}*/) begin |
rf_rx_init_status <= HMC_TS1_FIND_REF; |
init_tmp_seq <= descrambled_data_per_lane[0][3:0] + INIT_SEQ_INC_PER_CYCLE; |
init_bit_slip_cnt <= {RX_BIT_SLIP_CNT_LOG{1'b0}}; |
end |
end |
HMC_TS1_FIND_REF: begin |
if(init_seq_diff < 2) |
init_tmp_seq <= descrambled_data_per_lane[init_lane_cnt][3:0] + INIT_SEQ_INC_PER_CYCLE; |
|
if(&init_bit_slip_cnt==1'b1) |
rf_rx_init_status <= HMC_TS1_ALIGN; |
|
if(rf_hmc_init_status == HMC_DOWN) begin |
if(|init_valid_flit_src) begin |
init_prbs_seen <= 1'b1; |
end |
if(!init_valid_flit_src && init_prbs_seen && &rf_descramblers_locked) begin |
rf_hmc_init_status <= HMC_NULL; |
end |
end |
|
//When TX block sends ts1, start init process |
if(rf_tx_sends_ts1 && &init_valid_flit_src) begin |
rf_hmc_init_status <= HMC_TS1; |
end |
|
if(rf_hmc_init_status==HMC_TS1) begin |
// -------------------------------------------------------------------------TS1 AND DESCRAMBLER SYNCHRONIZATION |
if(!rf_all_descramblers_aligned) begin // repeat this until all descramblers are aligned !! |
|
if(|init_wait_time == 1'b0)begin |
|
init_tmp_seq <= init_tmp_seq + INIT_SEQ_INC_PER_CYCLE; |
|
if(|init_bit_slip_cnt == 1'b0)begin |
|
init_lane_cnt <= init_lane_cnt + 1; |
|
if(!init_descrambler_part_aligned[init_lane_cnt])begin |
init_bit_slip[init_lane_cnt] <= ~init_lane_has_correct_ts1[init_lane_cnt]; |
//if the current lane is more advanced than the current reference lane, set this lane as new reference |
if(init_seq_diff < 2 && init_lane_has_correct_ts1[init_lane_cnt]) begin |
init_tmp_seq <= init_data_per_lane[init_lane_cnt][3:0] + INIT_SEQ_INC_PER_CYCLE; |
end |
end |
|
if(&init_descrambler_part_aligned) begin |
if(|init_seq_diff==1'b0 && init_lane_has_correct_ts1[init_lane_cnt])begin |
init_descrambler_aligned[init_lane_cnt] <= 1'b1; |
end else begin |
init_bit_slip[init_lane_cnt] <= 1'b1; |
end |
end else begin |
init_descrambler_part_aligned[init_lane_cnt] <= init_lane_has_correct_ts1[init_lane_cnt]; |
end |
|
if(init_lane_cnt == NUM_LANES-1)begin |
init_bit_slip_cnt <= rf_bit_slip_time; |
end |
|
HMC_TS1_ALIGN: begin |
|
if(|init_bit_slip_cnt[RX_BIT_SLIP_CNT_LOG-1:LOG_NUM_LANES] == 1'b0)begin |
if(|init_seq_diff==1'b0 && init_lane_has_correct_ts1[init_lane_cnt])begin |
init_descrambler_aligned[init_lane_cnt] <= 1'b1; |
end else begin |
init_bit_slip_cnt <= init_bit_slip_cnt -1; |
init_bit_slip[init_lane_cnt] <= 1'b1; |
end |
|
end else begin |
init_wait_time <= init_wait_time -1; |
end |
// -------------------------------------------------------------------------SECOND NULL SEQUENCE |
end else begin // now that all is synchronized continue with NULL and TRET |
|
//lane reversal detected, reverse the input stream lane by lane |
if(init_data_per_lane[0][7:4] == ts1_lane7or15_portion)begin |
rf_lane_reversal_detected <= 1'b1; |
end |
if(rf_all_descramblers_aligned) begin |
rf_rx_init_status <= HMC_NULL_NEXT; |
end |
end |
HMC_NULL_NEXT: begin |
if(|init_valid_flit_src == 1'b0) begin |
rf_rx_init_status <= HMC_UP; |
rf_link_up <= LINK_UP; |
end |
end |
|
//when received NULLs again, init done (initial TRETs are treated as normal packets) |
if(|init_valid_flit_src == 1'b0)begin |
rf_link_status <= LINK_UP; |
rf_hmc_init_status <= HMC_UP; |
HMC_UP: begin |
if(rf_hmc_sleep || !run_rx) begin |
rf_rx_init_status <= HMC_DOWN; |
rf_link_up <= LINK_DOWN; |
end |
end |
end |
endcase |
end |
end |
|
582,30 → 603,34
|
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
|
data2crc_lng_per_flit_comb[i_f] = {128{1'b0}}; |
data2crc_lng_per_flit_comb[i_f] = 4'h0; |
|
if(data2crc_payload_remain_comb ==4'h1) begin |
data2crc_tail_comb[i_f] = 1'b1; |
|
case (data2crc_payload_remain_comb) |
4'h1: begin |
data2crc_tail_comb[i_f] = 1'b1; |
data2crc_valid_comb[i_f] = 1'b1; |
data2crc_payload_remain_comb = 4'h0; |
end |
|
if(data2crc_payload_remain_comb) begin |
4'h0: begin |
if(valid_flit_src[i_f])begin |
data2crc_hdr_comb[i_f] = 1'b1; |
data2crc_valid_comb[i_f] = 1'b1; |
if(lng(d_in_flit[i_f])<2 || lng(d_in_flit[i_f])>9 || !lng_dln_equal(d_in_flit[i_f]))begin |
data2crc_lng_per_flit_comb[i_f] = 4'h1; |
data2crc_tail_comb[i_f] = 1'b1; |
data2crc_payload_remain_comb = 4'h0; |
end else begin |
data2crc_payload_remain_comb = lng(d_in_flit[i_f]) -1; |
data2crc_lng_per_flit_comb[i_f] = lng(d_in_flit[i_f]); |
end |
end |
end |
default: begin |
data2crc_valid_comb[i_f] = 1'b1; |
data2crc_payload_remain_comb = data2crc_payload_remain_comb - 1; |
end else if(valid_flit_src[i_f])begin |
|
data2crc_hdr_comb[i_f] = 1'b1; |
data2crc_valid_comb[i_f] = 1'b1; |
|
if(lng(d_in_flit[i_f]) < 2 || lng(d_in_flit[i_f]) > 9) begin |
//Treat false lng values as single FLIT packets which will force error abort mode |
data2crc_tail_comb[i_f] = 1'b1; |
data2crc_lng_per_flit_comb[i_f] = 1; |
end else begin |
data2crc_payload_remain_comb = lng(d_in_flit[i_f]) -1; |
data2crc_lng_per_flit_comb[i_f] = lng(d_in_flit[i_f]); |
end |
end |
|
endcase |
end |
end |
|
615,147 → 640,74
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
data2crc_hdr <= {FPW{1'b0}}; |
data2crc_tail <= {FPW{1'b0}}; |
data2crc_valid <= {FPW{1'b0}}; |
data2crc_hdr <= {FPW{1'b0}}; |
data2crc_tail <= {FPW{1'b0}}; |
data2crc_valid <= {FPW{1'b0}}; |
data2crc_payload_remain <= 4'h0; |
|
data2crc_payload_remain <= {4{1'b0}}; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
data2crc_lng_per_flit[i_f] <= {128{1'b0}}; |
data2crc_lng_per_flit[i_f] <= 4'h0; |
end |
|
data2crc <= {DWIDTH{1'b0}}; |
|
end else begin |
if(link_is_up) begin |
data2crc_hdr <= data2crc_hdr_comb; |
data2crc_tail <= data2crc_tail_comb; |
if(rf_link_up) begin |
data2crc_valid <= data2crc_valid_comb; |
end |
|
data2crc_hdr <= data2crc_hdr_comb; |
data2crc_tail <= data2crc_tail_comb; |
data2crc_payload_remain <= data2crc_payload_remain_comb; |
|
data2crc_payload_remain <= data2crc_payload_remain_comb; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
data2crc_lng_per_flit[i_f] <= data2crc_lng_per_flit_comb[i_f]; |
end |
|
data2crc <= d_in; |
|
end |
end |
|
//================================================================================== |
//---------------------------------LNG/DLN check |
//================================================================================== |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
flit_after_lng_check_is_hdr <= {FPW{1'b0}}; |
flit_after_lng_check_is_tail <= {FPW{1'b0}}; |
flit_after_lng_check_is_valid <= {FPW{1'b0}}; |
flit_after_lng_check_is_poisoned <= {FPW{1'b0}}; |
flit_after_lng_check_is_flow <= {FPW{1'b0}}; |
flit_after_lng_check_has_rtc <= {FPW{1'b0}}; |
flit_after_lng_check_is_error <= {FPW{1'b0}}; |
|
for(i_f = 0; i_f < FPW; i_f = i_f + 1) begin |
flit_after_lng_check[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
flit_after_lng_check_is_hdr <= crc_d_out_flit_is_hdr; |
flit_after_lng_check_is_tail <= crc_d_out_flit_is_tail; |
flit_after_lng_check_is_valid <= crc_d_out_flit_is_valid; |
flit_after_lng_check_is_poisoned <= crc_d_out_flit_is_poisoned; |
flit_after_lng_check_is_flow <= crc_d_out_flit_is_flow; |
flit_after_lng_check_has_rtc <= crc_d_out_flit_has_rtc; |
flit_after_lng_check_is_error <= crc_d_out_flit_is_error; |
|
for(i_f = 0; i_f < FPW; i_f = i_f + 1) begin |
flit_after_lng_check[i_f] <= crc_d_out_flit[i_f]; |
end |
|
//perform lng/dln check |
for(i_f = 0; i_f < FPW; i_f = i_f + 1) begin |
if(crc_d_out_flit_is_hdr[i_f] && (lng(crc_d_out_flit[i_f]) != dln(crc_d_out_flit[i_f]))) begin |
flit_after_lng_check_is_error[i_f] <= 1'b1; |
end |
end |
end |
end |
|
//==================================================================== |
//---------------------------------Start Retry Stage |
//---------------------------------IRTRY Stage |
//==================================================================== |
//-- Count all types of IRTRY packets |
always @(*) begin |
|
//Set the lower bit mask for the next stage: Mask out all error FLITs |
flit_after_retry_stage_is_valid_mask_lsb = {FPW{1'b1}}; |
for(i_f = FPW-1; i_f >=0; i_f = i_f - 1) begin |
if(flit_after_lng_check_is_error[i_f])begin |
//Pass the tail in case it is an crc error so that the corresponding FLITs of the packet can be invalidated |
//but mask out single flit packets! |
flit_after_retry_stage_is_valid_mask_lsb = {FPW{1'b1}} >> (FPW-i_f-(flit_after_lng_check_is_tail[i_f] & !flit_after_lng_check_is_hdr[i_f])); |
end |
end |
flit_after_irtry_stage_is_start_retry_comb = {FPW{1'b0}}; |
flit_after_irtry_stage_is_clear_error_comb = {FPW{1'b0}}; |
|
//Next up, count both types of irtry packets and set the mask accordingly for irtry start packets in error abort mode and the |
//final clear abort FLIT that reaches the threshold |
|
flit_after_retry_stage_is_start_retry_comb = {FPW{1'b0}}; |
|
if( (tx_error_abort_mode && !irtry_clear_trig) || |
|(flit_after_retry_stage_is_error) || |
|(flit_after_seq_check_is_error) |
)begin |
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b0}}; |
end else begin |
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b1}}; |
end |
|
irtry_clear_trig_comb = 1'b0; |
|
irtry_clear_error_cnt_comb = irtry_clear_error_cnt; |
irtry_start_retry_cnt_comb = irtry_start_retry_cnt; |
|
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
|
if( flit_after_lng_check_is_flow[i_f] && |
cmd(flit_after_lng_check[i_f]) == {CMD_FLOW,CMD_IRTRY} && |
!flit_after_lng_check_is_error[i_f] |
if( crc_d_out_flit_is_flow[i_f] && |
cmd(crc_d_out_flit[i_f]) == {CMD_IRTRY} && |
!crc_d_out_flit_is_error[i_f] |
) begin |
|
if(irtry_start_retry_flag(flit_after_lng_check[i_f])) begin |
if(irtry_start_retry_flag(crc_d_out_flit[i_f])) begin |
//it's a start tx retry pkt |
irtry_start_retry_cnt_comb = irtry_start_retry_cnt_comb + 6'h1; |
irtry_clear_error_cnt_comb = 6'h0; |
irtry_start_retry_cnt_comb = irtry_start_retry_cnt_comb + 5'h1; |
irtry_clear_error_cnt_comb = 5'h0; |
end else begin |
//must be clear error pkt |
irtry_clear_error_cnt_comb = irtry_clear_error_cnt_comb + 6'h1; |
irtry_start_retry_cnt_comb = 6'h0; |
irtry_clear_error_cnt_comb = irtry_clear_error_cnt_comb + 5'h1; |
irtry_start_retry_cnt_comb = 5'h0; |
end |
|
if(irtry_start_retry_cnt_comb == rf_irtry_received_threshold) begin |
//The start retry packet that reaches the trehold is treated as valid and will trigger tx retry |
flit_after_retry_stage_is_valid_mask_msb[i_f] = 1'b1; |
flit_after_retry_stage_is_start_retry_comb[i_f] = 1'b1; |
flit_after_irtry_stage_is_start_retry_comb[i_f] = 1'b1; |
end |
|
//Clear error abort when threshold reached, allow following FLITs to be valid |
if(irtry_clear_error_cnt_comb == rf_irtry_received_threshold) begin |
irtry_clear_trig_comb = 1'b1; |
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b1}} << (i_f); |
flit_after_irtry_stage_is_clear_error_comb[i_f] = 1'b1; |
end |
|
end else begin |
//Reset both counters when received a non-irtry packet |
irtry_start_retry_cnt_comb = 6'h0; |
irtry_clear_error_cnt_comb = 6'h0; |
irtry_start_retry_cnt_comb = 5'h0; |
irtry_clear_error_cnt_comb = 5'h0; |
end |
end |
end |
767,11 → 719,11
if(!res_n) begin |
irtry_clear_trig <= 1'b0; |
|
irtry_clear_error_cnt <= {6{1'b0}}; |
irtry_start_retry_cnt <= {6{1'b0}}; |
irtry_clear_error_cnt <= {5{1'b0}}; |
irtry_start_retry_cnt <= {5{1'b0}}; |
|
end else begin |
irtry_clear_trig <= irtry_clear_trig_comb; |
irtry_clear_trig <= |flit_after_irtry_stage_is_clear_error_comb; |
|
irtry_clear_error_cnt <= irtry_clear_error_cnt_comb; |
irtry_start_retry_cnt <= irtry_start_retry_cnt_comb; |
782,36 → 734,37
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin |
flit_after_retry_stage[i_f] <= {128{1'b0}}; |
`ifdef RESET_ALL |
if(!res_n) flit_after_irtry_stage[i_f] <= {128{1'b0}}; |
else |
`endif |
flit_after_irtry_stage[i_f] <= crc_d_out_flit[i_f]; |
end |
flit_after_retry_stage_is_hdr <= {FPW{1'b0}}; |
flit_after_retry_stage_is_tail <= {FPW{1'b0}}; |
flit_after_retry_stage_is_poisoned <= {FPW{1'b0}}; |
flit_after_retry_stage_is_flow <= {FPW{1'b0}}; |
flit_after_retry_stage_has_rtc <= {FPW{1'b0}}; |
flit_after_retry_stage_is_error <= {FPW{1'b0}}; |
flit_after_retry_stage_is_valid <= {FPW{1'b0}}; |
flit_after_retry_stage_is_start_retry <= 1'b0; |
|
if(!res_n) begin |
`ifdef RESET_ALL |
flit_after_irtry_stage_is_hdr <= {FPW{1'b0}}; |
flit_after_irtry_stage_is_tail <= {FPW{1'b0}}; |
flit_after_irtry_stage_is_poisoned <= {FPW{1'b0}}; |
flit_after_irtry_stage_has_rtc <= {FPW{1'b0}}; |
flit_after_irtry_stage_is_error <= {FPW{1'b0}}; |
flit_after_irtry_stage_is_valid <= {FPW{1'b0}}; |
`endif |
flit_after_irtry_stage_is_start_retry <= {FPW{1'b0}}; |
flit_after_irtry_stage_is_clear_error <= {FPW{1'b0}}; |
end else begin |
|
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin |
flit_after_retry_stage[i_f] <= flit_after_lng_check[i_f]; |
end |
flit_after_retry_stage_is_hdr <= flit_after_lng_check_is_hdr; |
flit_after_retry_stage_is_tail <= flit_after_lng_check_is_tail; |
flit_after_retry_stage_is_poisoned <= flit_after_lng_check_is_poisoned & |
flit_after_retry_stage_is_valid_mask_msb & |
flit_after_retry_stage_is_valid_mask_lsb; |
flit_after_retry_stage_is_flow <= flit_after_lng_check_is_flow; |
flit_after_retry_stage_has_rtc <= flit_after_lng_check_has_rtc; |
flit_after_retry_stage_is_error <= flit_after_lng_check_is_error; |
flit_after_retry_stage_is_valid <= flit_after_lng_check_is_valid & |
flit_after_retry_stage_is_valid_mask_msb & |
flit_after_retry_stage_is_valid_mask_lsb; |
flit_after_retry_stage_is_start_retry <= flit_after_retry_stage_is_start_retry_comb; |
flit_after_irtry_stage_is_start_retry <= flit_after_irtry_stage_is_start_retry_comb; |
flit_after_irtry_stage_is_clear_error <= flit_after_irtry_stage_is_clear_error_comb; |
end |
flit_after_irtry_stage_is_hdr <= crc_d_out_flit_is_hdr; |
flit_after_irtry_stage_is_tail <= crc_d_out_flit_is_tail; |
flit_after_irtry_stage_is_poisoned <= crc_d_out_flit_is_poisoned; |
flit_after_irtry_stage_has_rtc <= crc_d_out_flit_has_rtc; |
flit_after_irtry_stage_is_error <= crc_d_out_flit_is_error; |
flit_after_irtry_stage_is_valid <= crc_d_out_flit_is_valid; |
end |
|
//-------------------------------------------Error abort mode |
834,7 → 787,7
end |
|
//Set error abort mode again if error detected |
if(|flit_after_lng_check_is_error || flit_after_seq_check_is_error)begin |
if(|crc_d_out_flit_is_error || flit_after_seq_check_is_error)begin |
tx_error_abort_mode <= 1'b1; |
end |
|
851,12 → 804,11
next_seqnum_comb = 3'h0; |
flit_after_seq_check_is_error_comb = {FPW{1'b0}}; |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
if(flit_after_retry_stage_has_rtc[i_f]) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
if(flit_after_irtry_stage_has_rtc[i_f]) begin |
//All packets that have an RTC also have a valid seqnum |
if(seq(flit_after_retry_stage[i_f]) == next_seqnum + next_seqnum_comb) begin |
next_seqnum_comb = next_seqnum_comb + 3'h1; |
end else begin |
next_seqnum_comb = next_seqnum_comb + 3'h1; |
if(seq(flit_after_irtry_stage[i_f]) != (next_seqnum + next_seqnum_comb)) begin |
flit_after_seq_check_is_error_comb[i_f] = 1'b1; |
end |
end |
866,28 → 818,34
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin |
`ifdef RESET_ALL |
if(!res_n) flit_after_seq_check[i_f] <= {128{1'b0}}; |
else |
`endif |
flit_after_seq_check[i_f] <= flit_after_irtry_stage[i_f]; |
end |
|
if(!res_n) begin |
|
//We expect the first packet to have the seqnum 1 |
next_seqnum <= 3'h1; |
next_seqnum <= 3'h0; |
|
flit_after_seq_check_is_hdr <= {FPW{1'b0}}; |
flit_after_seq_check_is_tail <= {FPW{1'b0}}; |
flit_after_seq_check_is_valid <= {FPW{1'b0}}; |
flit_after_seq_check_is_poisoned <= {FPW{1'b0}}; |
flit_after_seq_check_is_flow <= {FPW{1'b0}}; |
flit_after_seq_check_has_rtc <= {FPW{1'b0}}; |
`ifdef RESET_ALL |
flit_after_seq_check_is_hdr <= {FPW{1'b0}}; |
flit_after_seq_check_is_tail <= {FPW{1'b0}}; |
flit_after_seq_check_is_valid <= {FPW{1'b0}}; |
flit_after_seq_check_is_poisoned <= {FPW{1'b0}}; |
flit_after_seq_check_has_rtc <= {FPW{1'b0}}; |
flit_after_seq_check_is_start_retry <= {FPW{1'b0}}; |
flit_after_seq_check_is_clear_error <= {FPW{1'b0}}; |
`endif |
flit_after_seq_check_is_error <= {FPW{1'b0}}; |
flit_after_seq_check_is_start_retry <= {FPW{1'b0}}; |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
flit_after_seq_check[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
|
//Set the expected sequence number to the first one after error abort mode was cleared |
//otherwise apply the last seqnum + combinatioanl offset |
if(irtry_clear_trig_comb) begin |
if(|flit_after_irtry_stage_is_clear_error_comb) begin |
next_seqnum <= first_seq_after_error + next_seqnum_comb; |
end else begin |
next_seqnum <= next_seqnum + next_seqnum_comb; |
894,47 → 852,168
end |
|
//propage data to next stage and include any error bits that were detected during sequence number check |
flit_after_seq_check_is_hdr <= flit_after_retry_stage_is_hdr; |
flit_after_seq_check_is_tail <= flit_after_retry_stage_is_tail; |
flit_after_seq_check_is_valid <= flit_after_retry_stage_is_valid; |
flit_after_seq_check_is_poisoned <= flit_after_retry_stage_is_poisoned; |
flit_after_seq_check_is_flow <= flit_after_retry_stage_is_flow; |
flit_after_seq_check_has_rtc <= flit_after_retry_stage_has_rtc; |
flit_after_seq_check_is_error <= flit_after_retry_stage_is_error | |
flit_after_seq_check_is_error <= flit_after_irtry_stage_is_error | |
flit_after_seq_check_is_error_comb; |
flit_after_seq_check_is_start_retry <= flit_after_retry_stage_is_start_retry; |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
flit_after_seq_check[i_f] <= flit_after_retry_stage[i_f]; |
|
end |
flit_after_seq_check_is_hdr <= flit_after_irtry_stage_is_hdr; |
flit_after_seq_check_is_tail <= flit_after_irtry_stage_is_tail; |
flit_after_seq_check_is_valid <= flit_after_irtry_stage_is_valid; |
flit_after_seq_check_is_poisoned <= flit_after_irtry_stage_is_poisoned; |
flit_after_seq_check_has_rtc <= flit_after_irtry_stage_has_rtc; |
flit_after_seq_check_is_start_retry <= flit_after_irtry_stage_is_start_retry; |
flit_after_seq_check_is_clear_error <= flit_after_irtry_stage_is_clear_error; |
end |
|
//================================================================================== |
//---------------------------------Valid Mask - Remove valid bits for invalid FLITs |
//================================================================================== |
always@(*) begin |
flit_after_mask_stage_is_valid_mask_lsb = {FPW{1'b0}}; |
flit_after_mask_stage_is_valid_mask_msb = {FPW{1'b0}}; |
for(i_f = FPW-1; i_f >=0; i_f = i_f - 1) begin |
if(flit_after_seq_check_is_clear_error[i_f]) begin |
flit_after_mask_stage_is_valid_mask_msb = {{FPW-1{1'b1}},1'b0} << i_f; |
end |
if(flit_after_seq_check_is_error[i_f]) begin |
flit_after_mask_stage_is_valid_mask_lsb = {FPW{1'b1}} >> (FPW-i_f); |
end |
end |
|
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin |
flit_after_mask_stage[i_f] <= flit_after_seq_check[i_f]; |
end |
|
if(!res_n) begin |
|
`ifdef RESET_ALL |
flit_after_mask_stage_is_hdr <= {FPW{1'b0}}; |
flit_after_mask_stage_is_tail <= {FPW{1'b0}}; |
flit_after_mask_stage_is_poisoned <= {FPW{1'b0}}; |
flit_after_mask_stage_has_rtc <= {FPW{1'b0}}; |
flit_after_mask_stage_is_error <= {FPW{1'b0}}; |
flit_after_mask_stage_is_start_retry <= 1'b0; |
`endif |
flit_after_mask_stage_is_valid <= {FPW{1'b0}}; |
error <= 1'b0; |
end else begin |
|
if(|flit_after_seq_check_is_clear_error) |
error <= 1'b0; |
|
if(|flit_after_seq_check_is_error) |
error <= 1'b1; |
|
casex({error,|flit_after_seq_check_is_clear_error,|flit_after_seq_check_is_error}) |
3'b000: begin |
flit_after_mask_stage_is_valid <= flit_after_seq_check_is_valid; |
end |
3'b001: begin |
flit_after_mask_stage_is_valid <= flit_after_seq_check_is_valid & flit_after_mask_stage_is_valid_mask_lsb; |
end |
3'bx10: begin |
flit_after_mask_stage_is_valid <= flit_after_seq_check_is_valid & flit_after_mask_stage_is_valid_mask_msb; |
end |
3'bx11: begin |
flit_after_mask_stage_is_valid <= flit_after_seq_check_is_valid & flit_after_mask_stage_is_valid_mask_msb & flit_after_mask_stage_is_valid_mask_lsb; |
end |
default: begin |
flit_after_mask_stage_is_valid <= {FPW{1'b0}}; |
end |
endcase |
|
//propage data to next stage and include any error bits that were detected |
|
end |
flit_after_mask_stage_is_hdr <= flit_after_seq_check_is_hdr; |
flit_after_mask_stage_is_tail <= flit_after_seq_check_is_tail; |
flit_after_mask_stage_is_poisoned <= flit_after_seq_check_is_poisoned; |
flit_after_mask_stage_has_rtc <= flit_after_seq_check_has_rtc; |
flit_after_mask_stage_is_error <= flit_after_seq_check_is_error & flit_after_seq_check_is_tail; |
flit_after_mask_stage_is_start_retry <= flit_after_seq_check_is_start_retry; |
end |
|
//================================================================================== |
//---------------------------------Retrieve the lengths to invalide FLITs |
//---------------------------------Tokens/Pointers/Sequence numbers |
//================================================================================== |
//Count Tokens that were returned |
always @(*) begin |
rtc_sum_comb = {MAX_RTC_RET_LOG{1'b0}}; |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
if(flit_after_mask_stage_has_rtc[i_f] && flit_after_mask_stage_is_valid[i_f])begin |
rtc_sum_comb = rtc_sum_comb + rtc(flit_after_mask_stage[i_f]); |
end |
end |
end |
|
//Extract FRP/RRP + last seq (which is necessary to check packets after error_abort_mode is cleared) |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
tx_hmc_frp <= {8{1'b0}}; |
tx_rrp <= {8{1'b0}}; |
tx_returned_tokens <= {MAX_RTC_RET_LOG{1'b0}}; |
first_seq_after_error <= 3'h0; |
tx_link_retry <= 1'b0; |
|
end else begin |
//Return tokens |
tx_returned_tokens <= rtc_sum_comb; |
|
//Process FLITs and extract frp/seq/rrp if applicable |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
|
if((flit_after_mask_stage_is_tail[i_f] && flit_after_mask_stage_is_valid[i_f]) || flit_after_mask_stage_is_start_retry[i_f]) begin |
tx_rrp <= rrp(flit_after_mask_stage[i_f]); |
end |
|
if(flit_after_mask_stage_has_rtc[i_f] && flit_after_mask_stage_is_valid[i_f])begin |
tx_hmc_frp <= frp(flit_after_mask_stage[i_f]); |
first_seq_after_error <= seq(flit_after_mask_stage[i_f]); |
end |
end |
|
//-------------------------------------------TX retry |
tx_link_retry <= 1'b0; |
|
if(|flit_after_mask_stage_is_start_retry)begin |
tx_link_retry <= 1'b1; |
end |
|
end |
end |
|
//================================================================================== |
//---------------------------------Retrieve the lengths to invalidate FLITs |
//================================================================================== |
always @(*) begin |
//Retrieve the length from the header and assign it to the tail. This information will be used in the |
//invalidation stage to mask out FLITs that belong to the faulty packet |
|
lng_comb = lng_temp; |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
|
if(flit_after_retry_stage_is_hdr[i_f]) begin |
if( lng(flit_after_retry_stage[i_f]) < 2 || |
lng(flit_after_retry_stage[i_f]) > 9 |
) begin |
lng_comb = 1; |
if(flit_after_seq_check_is_hdr[i_f]) begin |
if(flit_after_seq_check_is_error[i_f]) begin |
lng_comb = 4'h1; |
end else begin |
lng_comb = lng(flit_after_retry_stage[i_f]); |
lng_comb = lng(flit_after_seq_check[i_f]); |
end |
end |
|
if(flit_after_retry_stage_is_tail[i_f]) begin |
if(flit_after_seq_check_is_tail[i_f]) begin |
lng_per_tail_comb[i_f] = lng_comb; |
end else begin |
lng_per_tail_comb[i_f] = {4{1'b0}}; |
lng_per_tail_comb[i_f] = 4'h0; |
end |
|
end |
945,12 → 1024,12
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
lng_per_tail[i_f] <= 0; |
end |
lng_temp <= {4{1'b0}}; |
lng_temp <= 4'h0; |
end else begin |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
lng_per_tail[i_f] <= lng_per_tail_comb[i_f]; |
end |
lng_temp <= lng_comb; |
964,40 → 1043,38
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET); i_c=i_c+1) begin |
flit_in_invalidation_data[i_c] <= {DWIDTH{1'b0}}; |
flit_in_invalidation_is_hdr[i_c] <= {FPW{1'b0}}; |
flit_in_invalidation_is_tail[i_c] <= {FPW{1'b0}}; |
flit_in_invalidation_is_flow[i_c] <= {FPW{1'b0}}; |
flit_in_invalidation_has_rtc[i_c] <= {FPW{1'b0}}; |
flit_in_invalidation_is_start_retry[i_c] <= {FPW{1'b0}}; |
`ifdef RESET_ALL |
if(!res_n) begin |
flit_in_invalidation_data[0] <= {DWIDTH{1'b0}}; |
|
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c=i_c+1) begin |
flit_in_invalidation_data[i_c+1] <= {DWIDTH{1'b0}}; |
end |
end else |
`endif |
begin |
flit_in_invalidation_data[0] <= flit_after_mask_stage_word; |
|
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c=i_c+1) begin |
flit_in_invalidation_data[i_c+1] <= flit_in_invalidation_data[i_c]; |
end |
end |
end else begin |
flit_in_invalidation_data[0] <= flit_after_seq_check_word; |
flit_in_invalidation_is_hdr[0] <= flit_after_seq_check_is_hdr; |
flit_in_invalidation_is_tail[0] <= flit_after_seq_check_is_tail; |
flit_in_invalidation_is_flow[0] <= flit_after_seq_check_is_flow; |
flit_in_invalidation_has_rtc[0] <= flit_after_seq_check_has_rtc; |
flit_in_invalidation_is_start_retry[0] <= flit_after_seq_check_is_start_retry; |
|
flit_in_invalidation_is_hdr[0] <= flit_after_mask_stage_is_hdr; |
flit_in_invalidation_is_tail[0] <= flit_after_mask_stage_is_tail; |
|
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c=i_c+1) begin |
flit_in_invalidation_data[i_c+1] <= flit_in_invalidation_data[i_c]; |
flit_in_invalidation_is_hdr[i_c+1] <= flit_in_invalidation_is_hdr[i_c]; |
flit_in_invalidation_is_tail[i_c+1] <= flit_in_invalidation_is_tail[i_c]; |
flit_in_invalidation_is_flow[i_c+1] <= flit_in_invalidation_is_flow[i_c]; |
flit_in_invalidation_has_rtc[i_c+1] <= flit_in_invalidation_has_rtc[i_c]; |
flit_in_invalidation_is_start_retry[i_c+1] <= flit_in_invalidation_is_start_retry[i_c]; |
end |
end |
end |
|
//Mark all poisoned FLITs |
always @(*) begin |
flit_in_invalidation0_is_poisoned_comb = {FPW{1'b0}}; |
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin |
if(flit_after_seq_check_is_poisoned[i_f])begin |
if(flit_after_mask_stage_is_poisoned[i_f])begin |
flit_in_invalidation0_is_poisoned_comb =flit_in_invalidation0_is_poisoned_comb | |
(({FPW{1'b1}} >> (FPW-i_f-1)) & ~({FPW{1'b1}} >> lng_per_tail[i_f]+(FPW-i_f-1))); |
end |
1009,7 → 1086,7
if(!res_n) begin |
|
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET); i_c = i_c + 1) begin |
flit_in_invalidation_is_poisoned[i_c] <= 0; |
flit_in_invalidation_is_poisoned[i_c] <= {FPW{1'b0}}; |
end |
|
end else begin |
1021,10 → 1098,8
|
//If there is a poisoned packet mark all FLITs as such |
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin |
if(flit_after_seq_check_is_poisoned[i_f]) begin |
if(flit_after_mask_stage_is_poisoned[i_f]) begin |
|
// flit_in_invalidation_is_poisoned[0] <= ({FPW{1'b1}} >> (FPW-i_f-1)) & ~({FPW{1'b1}} >> lng_per_tail[i_f]+(FPW-i_f-1)); |
|
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin |
if(lng_per_tail[i_f] > ((i_c)*FPW)+i_f+1) begin |
flit_in_invalidation_is_poisoned[i_c+1] <= flit_in_invalidation_is_poisoned[i_c] | ~({FPW{1'b1}} >> lng_per_tail[i_f]-(i_c*FPW)-i_f-1); |
1044,10 → 1119,9
if(!res_n) begin |
|
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET); i_c = i_c + 1) begin |
flit_in_invalidation_is_valid[i_c] <= 0; |
flit_in_invalidation_is_valid[i_c] <= {FPW{1'b0}}; |
end |
error_detected <= 0; |
flit_in_invalidation_mask_error <= {FPW{1'b1}}; |
flit_in_invalidation_mask_error <= {FPW{1'b0}}; |
|
end else begin |
|
1054,10 → 1128,6
//Reset the masks for invalidation stages |
flit_in_invalidation_mask_error <= {FPW{1'b1}}; |
|
if(irtry_clear_trig) begin |
error_detected <= 0; |
end |
|
//Propate invalidation stages but apply error and poisoned masks to the second stage |
for(i_c = 1; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin |
flit_in_invalidation_is_valid[i_c+1] <= flit_in_invalidation_is_valid[i_c]; |
1064,29 → 1134,21
end |
flit_in_invalidation_is_valid[1] <= flit_in_invalidation_is_valid[0] & flit_in_invalidation_mask_error; |
|
if(error_detected) begin |
//There is no valid FLIT when an error was detected |
flit_in_invalidation_is_valid[0] <= {FPW{1'b0}}; |
end else begin |
//First apply valids from previous stage |
flit_in_invalidation_is_valid[0] <= flit_after_seq_check_is_valid; |
//First apply valids from previous stage |
flit_in_invalidation_is_valid[0] <= flit_after_mask_stage_is_valid; |
|
//At least one FLIT contained an error in its tail. Leave all FLITs before the error untouched |
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin |
if(flit_after_seq_check_is_error[i_f] && flit_after_seq_check_is_tail[i_f]) begin |
error_detected <= 1'b1; |
flit_in_invalidation_mask_error <= {FPW{1'b1}} >> (FPW-i_f-1+lng_per_tail[i_f]); |
end |
//At least one FLIT contained an error in its tail. Leave all FLITs before the error untouched |
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin |
if(flit_after_mask_stage_is_error[i_f]) begin |
flit_in_invalidation_mask_error <= {FPW{1'b1}} >> (FPW-i_f-1+lng_per_tail[i_f]); |
end |
|
//Now use the length of the packet to invalidate FLITs that may reside in the next stages already |
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin |
if(flit_after_seq_check_is_error[i_f] && flit_after_seq_check_is_tail[i_f]) begin |
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin |
if(lng_per_tail[i_f] > ((i_c)*FPW)+i_f+1) begin |
flit_in_invalidation_is_valid[i_c+1] <= flit_in_invalidation_is_valid[i_c] & |
({FPW{1'b1}} >> lng_per_tail[i_f]-(i_c*FPW)-i_f-1); |
end |
//Now use the length of the packet to invalidate FLITs that may reside in the next stages already |
if(flit_after_mask_stage_is_error[i_f] && &flit_in_invalidation_mask_error) begin |
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin |
if(lng_per_tail[i_f] > ((i_c)*FPW)+i_f+1) begin |
flit_in_invalidation_is_valid[i_c+1] <= flit_in_invalidation_is_valid[i_c] & |
({FPW{1'b1}} >> lng_per_tail[i_f]-(i_c*FPW)-i_f-1); |
end |
end |
end |
1095,59 → 1157,6
end |
end |
|
//==================================================================== |
//---------------------------------FRP/RRP/RTC |
//==================================================================== |
//Count Tokens that were returned |
always @(*) begin |
rtc_sum_comb = {8{1'b0}}; |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
if(checked_flit_has_rtc[i_f])begin |
rtc_sum_comb = rtc_sum_comb + rtc(checked_flit[i_f]); |
end |
end |
end |
|
//Extract FRP/RRP + last seq (which is necessary to check packets after error_abort_mode is cleared) |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
tx_hmc_frp <= {8{1'b0}}; |
tx_rrp <= {8{1'b0}}; |
tx_returned_tokens <= {8{1'b0}}; |
first_seq_after_error <= 3'h1; |
|
tx_link_retry <= 1'b0; |
|
end else begin |
//Return tokens |
tx_returned_tokens <= rtc_sum_comb; |
|
//Process FLITs and extract frp/seq/rrp if applicable |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
|
if(checked_flit_is_tail[i_f] || checked_flit_is_start_retry[i_f]) begin |
tx_rrp <= rrp(checked_flit[i_f]); |
|
if(checked_flit_has_rtc[i_f])begin |
tx_hmc_frp <= frp(checked_flit[i_f]); |
first_seq_after_error <= seq(checked_flit[i_f]) + 3'h1; |
end |
end |
end |
|
//-------------------------------------------TX retry |
tx_link_retry <= 1'b0; |
|
if(|checked_flit_is_start_retry)begin |
tx_link_retry <= 1'b1; |
end |
|
end |
end |
|
//================================================================================== |
//---------------------------------Fill the input buffer with all response packets |
//================================================================================== |
1154,74 → 1163,25
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
input_buffer_shift_in <= 1'b0; |
input_buffer_valid <= {FPW{1'b0}}; |
input_buffer_is_hdr <= {FPW{1'b0}}; |
input_buffer_is_tail <= {FPW{1'b0}}; |
input_buffer_is_error_rsp <= {FPW{1'b0}}; |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
input_buffer_d_in_flit[i_f] <= {128{1'b0}}; |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
`ifdef RESET_ALL |
if(!res_n) input_buffer_d_in_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
input_buffer_d_in_flit[i_f] <= checked_flit[i_f]; |
end |
|
end else begin |
|
input_buffer_shift_in <= 1'b0; |
input_buffer_is_error_rsp <= {FPW{1'b0}}; |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
input_buffer_d_in_flit[i_f] <= {128{1'b0}}; |
|
//Flow and poisoned packets are not forwarded |
if(checked_flit_is_valid[i_f]) begin |
if(!checked_flit_is_flow[i_f] && !checked_flit_is_poisoned[i_f])begin |
input_buffer_d_in_flit[i_f] <= checked_flit[i_f]; |
end |
if(checked_flit_is_hdr[i_f] && (cmd(checked_flit[i_f])==CMD_RSP_ERROR)) begin |
input_buffer_is_error_rsp[i_f] <= 1'b1; |
end |
end |
for(i_f=0;i_f<FPW;i_f=i_f+1) begin |
input_buffer_is_error_rsp[i_f] <= checked_flit_is_hdr[i_f] && cmd(checked_flit[i_f])==CMD_RSP_ERROR; |
input_buffer_is_hdr[i_f] <= checked_flit_is_hdr[i_f] && !checked_flit_is_poisoned[i_f] && !is_rsp_flow(checked_flit[i_f]); |
input_buffer_is_valid[i_f] <= checked_flit_is_valid[i_f] && !checked_flit_is_poisoned[i_f] && !(is_rsp_flow(checked_flit[i_f]) && checked_flit_is_hdr[i_f]); |
input_buffer_is_tail[i_f] <= checked_flit_is_tail[i_f] && !checked_flit_is_poisoned[i_f] && !(is_rsp_flow(checked_flit[i_f]) && checked_flit_is_hdr[i_f]); |
end |
|
//Mask out any flow or poisoned packets |
input_buffer_valid <= checked_flit_is_valid & |
~checked_flit_is_flow & |
~checked_flit_is_poisoned; |
input_buffer_is_hdr <= checked_flit_is_hdr & |
~checked_flit_is_flow & |
~checked_flit_is_poisoned; |
input_buffer_is_tail <= checked_flit_is_tail & |
~checked_flit_is_flow & |
~checked_flit_is_poisoned; |
|
//If there is still a valid packet remaining after applying the mask |
if(|(checked_flit_is_valid & ~checked_flit_is_flow & ~checked_flit_is_poisoned))begin |
input_buffer_shift_in <= 1'b1; |
end |
|
end |
end |
assign input_buffer_shift_in = |input_buffer_is_valid; |
|
always @(*) begin |
tokens_poisoned = {LOG_FPW+1{1'b0}}; |
|
for(i_f=0; i_f<FPW; i_f=i_f+1) begin |
tokens_poisoned = tokens_poisoned + checked_flit_is_poisoned[i_f]; |
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
tx_hmc_poisoned_tokens_to_return <= {LOG_FPW+1{1'b0}}; |
end else begin |
tx_hmc_poisoned_tokens_to_return <= tokens_poisoned; |
end |
end |
|
//================================================================================== |
//---------------------------------Count responses and poisoned packets |
//================================================================================== |
1229,7 → 1189,7
rf_cnt_poisoned_comb = {LOG_FPW+1{1'b0}}; |
rf_cnt_rsp_comb = {LOG_FPW+1{1'b0}}; |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+1) begin |
if(checked_flit_is_poisoned[i_f] && checked_flit_is_hdr[i_f])begin |
rf_cnt_poisoned_comb = rf_cnt_poisoned_comb + {{LOG_FPW{1'b0}},1'b1}; |
end |
1240,64 → 1200,145
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_cnt_poisoned <= {HMC_RF_RWIDTH{1'b0}}; |
rf_cnt_rsp <= {HMC_RF_RWIDTH{1'b0}}; |
end else begin |
rf_cnt_poisoned <= rf_cnt_poisoned + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_cnt_poisoned_comb}; |
rf_cnt_rsp <= rf_cnt_rsp + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_cnt_rsp_comb}; |
end |
end |
`ifdef XILINX |
//Use the openhmc_counter48_wrapper_xilinx in building_blocks/counter to directly instantiate DSP48 |
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(LOG_FPW+1), |
.PIPELINED(XIL_CNT_PIPELINED) |
)cnt_poisoned ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(rf_cnt_poisoned_comb), |
.value(rf_cnt_poisoned) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(LOG_FPW+1), |
.PIPELINED(XIL_CNT_PIPELINED) |
)cnt_rsp ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(rf_cnt_rsp_comb), |
.value(rf_cnt_rsp) |
); |
|
`else |
reg [RF_COUNTER_SIZE-1:0] rf_cnt_poisoned_temp; |
reg [RF_COUNTER_SIZE-1:0] rf_cnt_rsp_temp; |
assign rf_cnt_poisoned = rf_cnt_poisoned_temp; |
assign rf_cnt_rsp = rf_cnt_rsp_temp; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_cnt_poisoned_temp <= {RF_COUNTER_SIZE{1'b0}}; |
rf_cnt_rsp_temp <= {RF_COUNTER_SIZE{1'b0}}; |
end else begin |
rf_cnt_poisoned_temp <= rf_cnt_poisoned_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_cnt_poisoned_comb}; |
rf_cnt_rsp_temp <= rf_cnt_rsp_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_cnt_rsp_comb}; |
end |
end |
`endif |
|
|
//================================================================================== |
//---------------------------------Shift response packets into the output fifo, return a token for each processed FLIT |
//---------------------------------Return the tokens |
//================================================================================== |
always @(*) begin |
tokens_out_of_fifo_sum_comb = {LOG_FPW+1{1'b0}}; |
generate |
if(OPEN_RSP_MODE==0) begin : return_tokens |
|
if(input_buffer_shift_out)begin |
for(i_f=0; i_f<FPW; i_f=i_f+1) begin |
tokens_out_of_fifo_sum_comb = tokens_out_of_fifo_sum_comb + |
(input_buffer_d_out[DWIDTH+i_f] && |
!input_buffer_d_out[DWIDTH+i_f+(3*FPW)]); //increment if there's a valid FLIT, but not an error response |
reg [MAX_RTC_RET_LOG-1:0] rtc_returned_tokens; |
reg [MAX_RTC_RET_LOG-1:0] rtc_poisoned_tokens_to_return; |
reg [LOG_FPW:0] tokens_out_of_fifo_sum_comb; |
reg [LOG_FPW:0] tokens_poisoned; |
|
assign tx_hmc_tokens_to_return = rtc_returned_tokens; |
assign tx_hmc_poisoned_tokens_to_return = rtc_poisoned_tokens_to_return; |
|
//Poisoned tokens will be returned before they enter the input buffer |
always @(*) begin |
tokens_poisoned = {LOG_FPW+1{1'b0}}; |
|
for(i_f=0; i_f<FPW; i_f=i_f+1) begin |
tokens_poisoned = tokens_poisoned + checked_flit_is_poisoned[i_f]; |
end |
end |
|
//All other tokens will be returned as they leave the input buffer |
always @(*) begin |
tokens_out_of_fifo_sum_comb = {LOG_FPW+1{1'b0}}; |
|
if(input_buffer_shift_out)begin |
for(i_f=0; i_f<FPW; i_f=i_f+1) begin |
tokens_out_of_fifo_sum_comb = tokens_out_of_fifo_sum_comb + |
(input_buffer_d_out[DWIDTH+i_f] && |
!input_buffer_d_out[DWIDTH+i_f+(3*FPW)]); //increment if there's a valid FLIT, but not an error response |
end |
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rtc_returned_tokens <= {LOG_FPW+1{1'b0}}; |
rtc_poisoned_tokens_to_return <= {LOG_FPW+1{1'b0}}; |
end else begin |
rtc_returned_tokens <= tokens_out_of_fifo_sum_comb; |
rtc_poisoned_tokens_to_return <= tokens_poisoned; |
end |
end |
|
end else begin |
//no input buffer, and no tokens will be returned |
assign tx_hmc_tokens_to_return = {LOG_FPW+1{1'b0}}; |
assign tx_hmc_poisoned_tokens_to_return = {LOG_FPW+1{1'b0}}; |
end |
end |
endgenerate |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
tx_hmc_tokens_to_return <= {LOG_FPW+1{1'b0}}; |
end else begin |
tx_hmc_tokens_to_return <= tokens_out_of_fifo_sum_comb; |
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
//----FIFO |
d_out_fifo_shift_in <= 1'b0; |
d_out_fifo_ctrl <= {4*FPW{1'b0}}; |
d_out_fifo_data <= {DWIDTH{1'b0}}; |
|
end else begin |
d_out_fifo_shift_in <= 1'b0; |
d_out_fifo_ctrl <= {4*FPW{1'b0}}; |
//================================================================================== |
//---------------------------------Shift response packets into the output fifo |
//================================================================================== |
generate |
if(OPEN_RSP_MODE==0) begin : assign_output_data |
|
reg [DWIDTH-1:0] out_data; |
reg out_shift_in; |
reg [4*FPW-1:0] out_ctrl; |
|
if(input_buffer_shift_out)begin |
d_out_fifo_data <= input_buffer_d_out[DWIDTH-1:0]; |
d_out_fifo_shift_in <= 1'b1; |
d_out_fifo_ctrl <= input_buffer_d_out[DWIDTH+(4*FPW)-1:DWIDTH]; |
assign d_out_fifo_data = out_data; |
assign d_out_fifo_shift_in = out_shift_in; |
assign d_out_fifo_ctrl = out_ctrl; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
//----FIFO |
out_shift_in <= 1'b0; |
out_ctrl <= {4*FPW{1'b0}}; |
out_data <= {DWIDTH{1'b0}}; |
end else begin |
if(input_buffer_shift_out)begin |
out_shift_in <= 1'b1; |
out_ctrl <= input_buffer_d_out[DWIDTH+(4*FPW)-1:DWIDTH]; |
out_data <= input_buffer_d_out[DWIDTH-1:0]; |
end else begin |
out_shift_in <= 1'b0; |
end |
end |
end |
end else begin //Open Response Mode |
|
assign d_out_fifo_data = input_buffer_d_in[DWIDTH-1:0]; |
assign d_out_fifo_shift_in = input_buffer_shift_in; |
assign d_out_fifo_ctrl = input_buffer_d_in[DWIDTH+(4*FPW)-1:DWIDTH]; |
|
end |
end |
end |
endgenerate |
|
|
|
1307,9 → 1348,9
//----------------------------------------------------------------------------------------------------- |
//===================================================================================================== |
|
wire res_n_lanes; |
assign res_n_lanes = ((rf_link_status == LINK_DOWN) || !rf_hmc_init_cont_set) ? 1'b0 : 1'b1; |
|
wire lanes_can_lock; |
assign lanes_can_lock = (rf_hmc_sleep || !run_rx) ? 1'b0 : 1'b1; |
// |
//Lane Init |
genvar i; |
generate |
1321,8 → 1362,9
.BITSLIP_SHIFT_RIGHT(BITSLIP_SHIFT_RIGHT) |
) rx_lane_I ( |
.clk(clk), |
.res_n(res_n_lanes), |
.bit_slip(init_bit_slip[i]), |
.res_n(res_n), |
.can_lock(lanes_can_lock), |
.bit_slip(phy_bit_slip[i]), |
.descrambler_locked(init_descrambler_locked[i]), |
.descrambler_disable(rf_scrambler_disable), |
.lane_polarity(rf_lane_polarity[i]), |
1343,10 → 1385,11
.clk(clk), |
.res_n(res_n), |
//input |
.d_in_data(data2crc), |
.d_in_data(d_in_dly), |
.d_in_hdr(data2crc_hdr), |
.d_in_tail(data2crc_tail), |
.d_in_valid(data2crc_valid), |
// .d_in_error(data2crc_error), |
.d_in_lng(data2crc_lng), |
//output |
.d_out_data(crc_d_out_data), |
1359,20 → 1402,23
.d_out_flow(crc_d_out_flit_is_flow) |
); |
|
//Buffer Fifo - Depth = Max Tokens |
openhmc_sync_fifo #( |
.DATASIZE(DWIDTH+(4*FPW)), //+4*FPW for header/tail/valid/error response information -> AXI-4 TUSER signal |
.ADDRSIZE(LOG_MAX_RTC) |
) input_buffer_I( |
.clk(clk), |
.res_n(res_n), |
.d_in(input_buffer_d_in), |
.shift_in(input_buffer_shift_in), |
.d_out(input_buffer_d_out), |
.shift_out(input_buffer_shift_out), |
.next_stage_full(1'b1), // Dont touch! |
.empty(input_buffer_empty) |
); |
generate |
if(OPEN_RSP_MODE==0) begin : use_input_buffer |
//Buffer Fifo - Depth = Max Tokens |
openhmc_sync_fifo #( |
.DATASIZE(DWIDTH+(4*FPW)), //+4*FPW for header/tail/valid/error response information -> AXI-4 TUSER signal |
.ADDRSIZE(LOG_MAX_RX_TOKENS) |
) input_buffer_I( |
.clk(clk), |
.res_n(res_n), |
.d_in(input_buffer_d_in), |
.shift_in(input_buffer_shift_in), |
.d_out(input_buffer_d_out), |
.shift_out(input_buffer_shift_out), |
.empty(input_buffer_empty) |
); |
end |
endgenerate |
|
endmodule |
`default_nettype wire |
/trunk/openHMC/rtl/hmc_controller/openhmc_top_xilinx.f
0,0 → 1,45
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
### Make sure to source the path variable first. |
#use: export OPENHMC_PATH=path_to_openhmc_main_folder |
|
####Building blocks |
${OPENHMC_PATH}/rtl/building_blocks/counter/openhmc_counter48_wrapper_xilinx.v |
-f ${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/xilinx/openhmc_fifos_xilinx.f |
|
/trunk/openHMC/rtl/hmc_controller/tx/tx_crc_combine.v
89,7 → 89,7
end |
endgenerate |
|
reg [3:0] d_in_flit_lng_dly [FPW-1:0]; |
reg [3:0] d_in_flit_lng_dly [FPW-1:0]; |
reg [DWIDTH-1:0] d_in_data_dly; |
reg [FPW-1:0] d_in_tail_dly; |
reg [FPW-1:0] d_in_hdr_dly; |
123,7 → 123,7
assign crc_accu_in_combined[f][(f2*32)+31:(f2*32)] = crc_accu_in_valid[f][f2] ? crc_accu_in[f2] : 32'h0; |
end |
end |
endgenerate |
endgenerate |
|
//------------------------------------------------------------------------------------Data Pipeline signals |
reg [DWIDTH-1:0] crc_data_pipe_in_data [1:0]; |
132,7 → 132,7
|
generate |
for(f = 0; f < (FPW); f = f + 1) begin : assign_data_pipe_output |
assign crc_data_pipe_out_data_flit[f] = crc_data_pipe_in_data[1][(f*128)+128-1:f*128]; |
assign crc_data_pipe_out_data_flit[f] = crc_data_pipe_in_data[1][(f*128)+127:f*128]; |
end |
endgenerate |
|
214,10 → 214,10
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(d_in_hdr[i_f])begin |
|
|
if(i_f+lng(d_in_flit[i_f])>FPW) begin |
//If the current packet spreads over multiple cycles |
|
|
if(swap_crc) begin |
//If the last packet was swapped and the current packet also spreads over the more than 1 cycle use crc 0 now |
d_in_flit_target_crc[i_f] <= 3'h0; |
235,7 → 235,7
if(swap_crc && !(d_in_hdr > d_in_tail)) begin |
d_in_flit_target_crc[i_f] <= i_f-1; |
end |
|
|
end |
end |
end |
247,22 → 247,32
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_flit_lng_dly[i_f] <= 4'h0; |
|
//------------Data Propagation |
`ifdef RESET_ALL |
if(!res_n) d_in_data_dly <= {DWIDTH{1'b0}}; |
else |
`endif |
d_in_data_dly <= d_in_data; |
//---------------------------- |
|
`ifdef RESET_ALL |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_flit_lng_dly[i_f] <= 4'h0; |
end |
d_in_tail_dly <= {FPW{1'b0}}; |
d_in_hdr_dly <= {FPW{1'b0}}; |
end else |
`endif |
begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_flit_lng_dly[i_f] <= lng(d_in_flit[i_f]); |
end |
d_in_tail_dly <= d_in_tail; |
d_in_hdr_dly <= d_in_hdr; |
end |
d_in_data_dly <= {DWIDTH{1'b0}}; |
d_in_tail_dly <= {FPW{1'b0}}; |
d_in_hdr_dly <= {FPW{1'b0}}; |
end else begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_flit_lng_dly[i_f] <= lng(d_in_flit[i_f]); |
end |
d_in_data_dly <= d_in_data; |
d_in_tail_dly <= d_in_tail; |
d_in_hdr_dly <= d_in_hdr; |
end |
end |
|
//==================================================================== |
//---------------------------------Inter CRC stage, CRC assignment Logic |
270,9 → 280,19
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
//------------Data Propagation |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
`ifdef RESET_ALL |
if(!res_n) crc_accu_in[i_f] <= {32{1'b0}}; |
else |
`endif |
crc_accu_in[i_f] <= crc_init_out[i_f]; |
end |
//---------------------------- |
|
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
crc_accu_in[i_f] <= {32{1'b0}}; |
crc_accu_in_valid[i_f] <= {FPW{1'b0}}; |
crc_accu_in_tail[i_f] <= {FPW{1'b0}}; |
payload_remain[i_f] <= 4'h0; |
280,7 → 300,7
end else begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
crc_accu_in[i_f] <= crc_init_out[i_f]; |
|
crc_accu_in_valid[i_f] <= 4'h0; |
crc_accu_in_tail[i_f] <= 4'h0; |
end |
288,7 → 308,7
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
//First go through accu crcs |
|
if(|payload_remain[i_f]) begin |
if(|payload_remain[i_f]) begin |
|
if(payload_remain[i_f] > FPW) begin |
crc_accu_in_valid[i_f] <= {FPW{1'b1}}; |
296,15 → 316,15
end else begin |
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]); |
crc_accu_in_tail[i_f] <= 1'b1 << (payload_remain[i_f]-1); |
payload_remain[i_f] <= 4'h0; |
payload_remain[i_f] <= 4'h0; |
end |
end |
|
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin |
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin |
if(i_f==d_in_flit_target_crc[i_f2] && d_in_hdr_dly[i_f2]) begin |
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc |
|
if( (i_f2+d_in_flit_lng_dly[i_f2]) >FPW ) begin |
if( (i_f2+d_in_flit_lng_dly[i_f2]) >FPW ) begin |
payload_remain[i_f] <= (d_in_flit_lng_dly[i_f2]-FPW+i_f2); |
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2 << i_f2; |
end else begin |
324,33 → 344,46
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}}; |
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}}; |
|
//------------Data Propagation |
`ifdef RESET_ALL |
if (!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}}; |
end |
end else |
`endif |
begin |
crc_data_pipe_in_data[0] <= d_in_data_dly; |
crc_data_pipe_in_data[1] <= crc_data_pipe_in_data[0]; |
end |
//---------------------------- |
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
target_crc_per_tail1[i_f] <= 3'h0; |
end |
end else begin |
`ifdef RESET_ALL |
if(!res_n) begin |
for(i_c=0;i_c<2;i_c=i_c+1)begin |
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}}; |
end |
|
for(i_f=0;i_f<(FPW);i_f=i_f+ 1) begin |
target_crc_per_tail1[i_f] <= {LOG_FPW{1'b0}}; |
end |
end else |
`endif |
begin |
|
//We keep the tails per FLIT so they are not part of the data pipe |
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin |
for(i_f=0;i_f<(FPW);i_f=i_f+ 1) begin |
target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f]; |
end |
|
//Set the first stage of the data pipeline |
crc_data_pipe_in_data[0] <= d_in_data_dly; |
crc_data_pipe_in_tail[0] <= d_in_tail_dly; |
|
//Data Pipeline propagation |
for(i_c=0;i_c<(1);i_c=i_c+1)begin |
crc_data_pipe_in_data[i_c+1] <= crc_data_pipe_in_data[i_c]; |
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c]; |
crc_data_pipe_in_tail[1] <= crc_data_pipe_in_tail[0]; |
end |
end |
end |
|
//==================================================================== |
//---------------------------------At the end of the data pipeline get and add CRCs |
359,16 → 392,14
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data_rdy_flit[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
|
`ifdef RESET_ALL |
if(!res_n) begin |
data_rdy_flit[i_f] <= {128{1'b0}}; |
end else |
`endif |
begin |
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f]; |
|
if(crc_data_pipe_in_tail[1][i_f])begin //Finally add the crc |
375,8 → 406,8
data_rdy_flit[i_f][128-1:128-32] <= crc_per_flit[target_crc_per_tail1[i_f]]; |
end |
end |
end |
end |
end |
|
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
389,7 → 420,9
crc_128_init crc_init_I |
( |
.clk(clk), |
.res_n(res_n), |
`ifdef RESET_ALL |
.res_n(res_n), |
`endif |
.inData(d_in_flit[f]), |
.crc(crc_init_out[f]) |
); |
408,7 → 441,6
.res_n(res_n), |
.tail(crc_accu_in_tail[f]), |
.d_in(crc_accu_in_combined[f]), |
.valid(crc_accu_in_valid[f]), |
.crc_out(crc_per_flit[f]) |
); |
end |
/trunk/openHMC/rtl/hmc_controller/tx/tx_run_length_limiter.v
132,22 → 132,30
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
`ifdef RESET_ALL |
if(!res_n) begin |
data_out <= {DWIDTH {1'b0}}; |
end else |
`endif |
begin |
if (enable && bit_flip) begin |
data_out <= {data_in[LANE_WIDTH-1:1], ~data_in[0]}; |
end else begin |
data_out <= data_in; |
end |
end |
if (!res_n) begin |
count_bottom_d1 <= { COUNT_BITS {1'b0}}; |
no_flip_bottom_d1 <= 1'b0; |
data_in_bottom_d1 <= 1'b0; |
rf_bit_flip <= 1'b0; |
data_out <= {LANE_WIDTH{1'b0}}; |
end else begin |
count_bottom_d1 <= count_bottom; |
no_flip_bottom_d1 <= no_flip[NUM_CHUNKS-1]; |
data_in_bottom_d1 <= data_in[LANE_WIDTH-1]; |
|
if (enable && bit_flip) begin |
data_out <= {data_in[LANE_WIDTH-1:1], ~data_in[0]}; |
rf_bit_flip <= bit_flip; |
end else begin |
data_out <= data_in; |
end |
end |
end |
/trunk/openHMC/rtl/hmc_controller/tx/tx_scrambler.v
61,7 → 61,7
`default_nettype none |
|
module tx_scrambler #( |
parameter LANE_WIDTH = 16, |
parameter LANE_WIDTH = 16, |
parameter HMC_RX_AC_COUPLED = 1 |
) |
( |
84,33 → 84,25
wire [LANE_WIDTH-1:0] run_length_d_out; |
reg [14:0] lfsr; // LINEAR FEEDBACK SHIFT REGISTER |
wire [14:0] lfsr_steps [LANE_WIDTH-1:0]; // LFSR values for serial time steps |
reg seed_set; |
|
// SEQUENTIAL PROCESS |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if (!res_n) begin |
seed_set <= 1'b0; |
lfsr[14:0] <= 15'h0; |
data_out <= {LANE_WIDTH {1'b0}}; |
end |
else |
`ifdef RESET_ALL |
if(!res_n) begin |
data_out <= {LANE_WIDTH{1'b0}}; |
end else |
`endif |
begin |
if(!seed_set) begin |
lfsr[14:0] <= seed; |
seed_set <= 1'b1; |
end else begin |
if (disable_scrambler) begin |
lfsr[14:0] <= 15'h0; |
end else begin |
lfsr[14:0] <= lfsr_steps[LANE_WIDTH-1]; |
end |
end |
data_out <= run_length_d_out; |
end |
end // serial shift right with left input |
|
if(!res_n) lfsr <= seed; |
else lfsr <= disable_scrambler ? {15{1'b0}} : lfsr_steps[LANE_WIDTH-1]; |
|
end |
|
// SCRAMBLE |
genvar j; |
generate |
/trunk/openHMC/rtl/hmc_controller/tx/tx_link.v
46,11 → 46,16
parameter FPW = 4, |
parameter DWIDTH = FPW*128, |
parameter NUM_LANES = 8, |
parameter HMC_PTR_SIZE = 8, |
parameter HMC_RF_RWIDTH = 64, |
parameter RF_COUNTER_SIZE = 64, |
parameter HMC_RX_AC_COUPLED = 1, |
parameter MAX_RTC_RET_LOG = 8, |
parameter LOG_MAX_RX_TOKENS = 8, |
parameter LOG_MAX_HMC_TOKENS= 10, |
parameter LOG_IRTRY_TIMOUT = 8, |
parameter XIL_CNT_PIPELINED = 0, |
//Debug |
parameter DBG_RX_TOKEN_MON = 1 |
parameter DBG_RX_TOKEN_MON = 1, |
parameter OPEN_RSP_MODE = 0 |
) ( |
|
//---------------------------------- |
67,8 → 72,8
//---------------------------------- |
//----HMC IF |
//---------------------------------- |
output reg hmc_LxRXPS, |
input wire hmc_LxTXPS, |
output reg LXRXPS, |
input wire LXTXPS, |
|
//---------------------------------- |
//----Input data |
87,9 → 92,9
input wire rx_force_tx_retry, |
input wire rx_error_abort_mode, |
input wire rx_error_abort_mode_cleared, |
input wire [HMC_PTR_SIZE-1:0] rx_hmc_frp, |
input wire [HMC_PTR_SIZE-1:0] rx_rrp, |
input wire [7:0] rx_returned_tokens, |
input wire [7:0] rx_hmc_frp, |
input wire [7:0] rx_rrp, |
input wire [MAX_RTC_RET_LOG-1:0] rx_returned_tokens, |
input wire [LOG_FPW:0] rx_hmc_tokens_to_return, |
input wire [LOG_FPW:0] rx_hmc_poisoned_tokens_to_return, |
|
98,9 → 103,9
//---------------------------------- |
//Monitoring 1-cycle set to increment |
output reg rf_cnt_retry, |
output reg [HMC_RF_RWIDTH-1:0] rf_sent_p, |
output reg [HMC_RF_RWIDTH-1:0] rf_sent_np, |
output reg [HMC_RF_RWIDTH-1:0] rf_sent_r, |
output wire [RF_COUNTER_SIZE-1:0] rf_sent_p, |
output wire [RF_COUNTER_SIZE-1:0] rf_sent_np, |
output wire [RF_COUNTER_SIZE-1:0] rf_sent_r, |
output reg rf_run_length_bit_flip, |
output reg rf_error_abort_not_cleared, |
|
109,24 → 114,17
input wire rf_hmc_received_init_null, |
input wire rf_descramblers_aligned, |
output wire [1:0] rf_tx_init_status, |
output reg [9:0] rf_hmc_tokens_av, |
output reg rf_hmc_is_in_sleep, |
output reg [9:0] rf_rx_tokens_av, |
output reg [LOG_MAX_HMC_TOKENS-1:0]rf_hmc_tokens_av, |
output wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_tokens_av, |
|
//Control |
input wire rf_hmc_sleep_requested, |
//input wire rf_warm_reset, |
input wire rf_hmc_init_cont_set, |
input wire rf_warm_reset, |
input wire rf_scrambler_disable, |
input wire [9:0] rf_rx_buffer_rtc, |
input wire [2:0] rf_first_cube_ID, |
input wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_buffer_rtc, |
input wire [4:0] rf_irtry_to_send, |
input wire rf_run_length_enable, |
input wire rf_run_length_enable |
|
//Debug Register |
input wire rf_dbg_dont_send_tret, |
input wire rf_dbg_halt_on_error_abort, |
input wire rf_dbg_halt_on_tx_retry |
); |
|
`include "hmc_field_functions.h" |
138,7 → 136,6
//===================================================================================================== |
//------------------------------------------------------------------------------------General Assignments |
localparam LANE_WIDTH = (DWIDTH/NUM_LANES); |
localparam NULL_FLIT = {128{1'b0}}; |
|
integer i_f; //counts to FPW |
integer i_t; //counts to number of TS1 packets in a word |
151,6 → 148,8
localparam PKT_P_WRITE = 3'b011; |
localparam PKT_MISC_P_WRITE = 3'b100; |
|
localparam CMD_IRTRY = 6'b000011; |
|
//------------------------------------------------------------------------------------Scrambler |
wire [14:0] seed_lane [NUM_LANES-1:0]; |
|
176,42 → 175,44
end |
endgenerate |
|
wire [NUM_LANES-1:0] bit_was_flipped; |
wire [NUM_LANES-1:0] bit_was_flipped; |
|
//------------------------------------------------------------------------------------FSM and States |
reg [3:0] state; |
localparam TX_NULL_1 = 4'b0001; |
localparam TX_TS1 = 4'b0010; |
localparam TX_NULL_2 = 4'b0011; |
localparam IDLE = 4'b1000; |
localparam TX = 4'b1001; |
localparam HMC_RTRY = 4'b1010; |
localparam SLEEP = 4'b1011; |
localparam WAIT_FOR_HMC = 4'b1100; |
localparam LNK_RTRY = 4'b1101; |
localparam FATAL_ERROR = 4'b1110; |
localparam DEBUG = 4'b1111; |
reg [2:0] state; |
reg [1:0] init_state; |
localparam INIT_TX_NULL_1 = 2'b00; |
localparam INIT_TX_TS1 = 2'b01; |
localparam INIT_TX_NULL_2 = 2'b11; |
localparam INIT_DONE = 2'b10; |
|
assign rf_tx_init_status = state[3] ? 0 : state[1:0]; |
localparam INIT = 3'b000; |
localparam IDLE = 3'b001; |
localparam TX = 3'b010; |
localparam HMC_RTRY = 3'b011; |
localparam SLEEP = 3'b100; |
localparam WAIT_FOR_HMC = 3'b101; |
localparam LNK_RTRY = 3'b110; |
localparam DEBUG = 3'b111; |
|
assign rf_tx_init_status = init_state; |
|
reg rtc_rx_initialize; |
|
//------------------------------------------------------------------------------------DATA and ORDERING |
//reorder incoming data to FLITs |
wire [128-1:0] d_in_flit [FPW-1:0]; |
wire [127:0] d_in_flit [FPW-1:0]; |
genvar f; |
generate |
for(f = 0; f < (FPW); f = f + 1) begin : reorder_input_data_to_flits |
assign d_in_flit[f] = d_in_data[128-1+(f*128):f*128]; |
assign d_in_flit[f] = d_in_data[127+(f*128):f*128]; |
end |
endgenerate |
|
//Create a mask and an input buffer that is necessary if packet transmission is interrupted and packets remain untransmitted |
reg d_in_use_buf; |
reg [128-1:0] d_in_buf_flit [FPW-1:0]; |
reg [FPW-1:0] d_in_buf_flit_is_hdr; |
reg [FPW-1:0] d_in_buf_flit_is_tail; |
reg [FPW-1:0] d_in_buf_flit_is_valid; |
reg [127:0] d_in_buf_flit [FPW-2:0]; |
reg [FPW-2:0] d_in_buf_flit_is_hdr; |
reg [FPW-2:0] d_in_buf_flit_is_valid; |
|
//Reorder the data per lane |
wire [DWIDTH-1:0] data_rdy; |
227,13 → 228,16
endgenerate |
|
//------------------------------------------------------------------------------------Init Regs |
localparam TS1_SEQ_INC_VAL_PER_CYCLE = (NUM_LANES==8) ? FPW : (FPW/2); |
localparam NUM_NULL_TO_SEND_BEFORE_IDLE = 50; //see HMC spec, 32 is minimum |
localparam TS1_SEQ_INC_VAL_PER_CYCLE = (NUM_LANES==8) ? FPW : (FPW/2); |
localparam LOG_CYCLES_NULL_TO_SEND = (FPW == 2) ? 4 : |
(FPW == 4) ? 3 : |
(FPW == 6) ? 3 : |
2; |
|
wire [(NUM_LANES*4)-1:0] ts1_seq_part_reordered [TS1_SEQ_INC_VAL_PER_CYCLE-1:0]; //ts1 seq is 4 bits |
reg [3:0] ts1_seq_nr_per_flit [TS1_SEQ_INC_VAL_PER_CYCLE-1:0]; |
wire [128-1:0] ts1_flit [FPW-1:0]; |
reg [5:0] num_init_nulls_sent; |
wire [127:0] ts1_flit [FPW-1:0]; |
reg [LOG_CYCLES_NULL_TO_SEND-1:0] num_null_cycles_sent; |
|
generate |
for(f = 0; f < TS1_SEQ_INC_VAL_PER_CYCLE; f = f + 1) begin : generate_lane_dependent_ts1_sequence |
243,42 → 247,27
end |
|
if(NUM_LANES==8) begin |
|
assign ts1_flit[f] = { |
32'hffffffff,32'h0,1'h1,7'h0,7'b1111111,1'h0,7'h0,1'h1,1'h0,7'b1111111,ts1_seq_part_reordered[f] |
}; |
|
end else begin |
|
assign ts1_flit[f*2] = { |
assign ts1_flit[f*2+1] = { |
64'hffffffffffffffff,64'h0 |
}; |
assign ts1_flit[f*2+1] = { |
15'h7fff,1'h0,1'h1,16'h0,15'h7fff,15'h0,1'h1,ts1_seq_part_reordered[f] |
assign ts1_flit[f*2] = { |
16'h8000,16'hfffe,16'h0001,16'h7fff,ts1_seq_part_reordered[f] |
}; |
|
end |
|
end |
endgenerate |
|
//------------------------------------------------------------------------------------SEQ and FRP Stage |
reg [128-1:0] data2seq_frp_stage_flit [FPW-1:0]; |
reg [128-1:0] data2seq_frp_stage_flit_comb [FPW-1:0]; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_hdr; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_tail; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_valid; |
reg [FPW-1:0] data2seq_frp_stage_is_flow; |
reg data2seq_frp_stage_force_tx_retry; |
|
//------------------------------------------------------------------------------------Counter variables |
reg [LOG_FPW:0] rf_sent_p_comb; |
reg [LOG_FPW:0] rf_sent_np_comb; |
reg [LOG_FPW:0] rf_sent_r_comb; |
|
|
//------------------------------------------------------------------------------------SEQ and FRP Stage |
reg [128-1:0] data2rtc_stage_flit [FPW-1:0]; |
//------------------------------------------------------------------------------------SEQ FRP RTC Stage |
reg [127:0] data2rtc_stage_flit [FPW-1:0]; |
reg [FPW-1:0] data2rtc_stage_flit_is_hdr; |
reg [FPW-1:0] data2rtc_stage_flit_is_tail; |
reg [FPW-1:0] data2rtc_stage_flit_is_valid; |
285,28 → 274,32
reg data2rtc_stage_is_flow; |
reg data2rtc_stage_force_tx_retry; |
|
reg [127:0] data2seq_frp_stage_flit [FPW-1:0]; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_hdr; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_tail; |
reg [FPW-1:0] data2seq_frp_stage_flit_is_valid; |
reg data2seq_frp_stage_is_flow; |
reg data2seq_frp_stage_force_tx_retry; |
|
//Information used to fill the retry buffer |
reg [LOG_FPW-1:0] target_temp [FPW:0]; |
reg [LOG_FPW-1:0] next_target; |
reg [LOG_FPW-1:0] target [FPW-1:0]; |
|
reg [LOG_FPW:0] tx_seqnum_inc; |
reg [2:0] tx_seqnum_temp [FPW-1:0]; |
|
//------------------------------------------------------------------------------------RETRY |
//HMC |
//Amount of cycles to wait until start HMC retry is issued again (when RX error abort is not cleared) |
localparam CYCLES_TO_CLEAR_ERR_ABORT_MODE = 254; //safe value |
reg [7:0] error_abort_mode_clr_cnt; |
reg force_hmc_retry; |
reg [5:0] irtry_start_retry_cnt; |
//Number of cycles to wait until start HMC retry is issued again (when RX error abort is not cleared) |
reg [LOG_IRTRY_TIMOUT-1:0] error_abort_mode_clr_cnt; |
reg force_hmc_retry; |
reg [4:0] irtry_start_retry_cnt; |
reg [4:0] irtry_clear_error_cnt; |
wire [63:0] irtry_hdr; |
assign irtry_hdr = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000011}; |
|
//Memory Controller |
reg [5:0] irtry_clear_error_cnt; |
wire [63:0] irtry_hdr; |
assign irtry_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000011}; |
|
//------------------------------------------------------------------------------------Retry Buffer |
reg [128-1:0] data2ram_flit [FPW-1:0]; |
reg [128-1:0] data2ram_flit_temp [FPW-1:0]; |
reg [FPW-1:0] data2ram_flit_is_hdr; |
reg [FPW-1:0] data2ram_flit_is_tail; |
reg [FPW-1:0] data2ram_flit_is_valid; |
reg data2ram_is_flow; |
reg data2ram_force_tx_retry; |
|
localparam RAM_ADDR_SIZE = (FPW == 2) ? 7 : |
(FPW == 4) ? 6 : |
(FPW == 6) ? 5 : |
313,10 → 306,22
(FPW == 8) ? 5 : |
1; |
|
reg ram_w_en, ram_r_en; |
reg [RAM_ADDR_SIZE-1:0] ram_w_addr; |
reg [127:0] data2ram_flit [FPW-1:0]; |
reg [127:0] data2ram_flit_temp [FPW-1:0]; |
reg [FPW-1:0] data2ram_flit_is_hdr; |
reg [FPW-1:0] data2ram_flit_is_tail; |
reg [FPW-1:0] data2ram_flit_is_valid; |
reg data2ram_force_tx_retry; |
|
//Header/Tail fields, and at the same time form the RAM read pointer |
reg [RAM_ADDR_SIZE-1:0] tx_frp_adr [FPW-1:0]; |
reg [2:0] tx_seqnum; |
|
|
reg [FPW-1:0] ram_w_en ; |
reg ram_r_en; |
wire [RAM_ADDR_SIZE-1:0] ram_w_addr_next; |
assign ram_w_addr_next = ram_w_addr + 1; |
assign ram_w_addr_next = tx_frp_adr[0] + 1; |
reg [RAM_ADDR_SIZE-1:0] ram_r_addr_temp; |
reg [FPW-1:0] ram_r_mask; |
wire [128+3-1:0] ram_r_data [FPW-1:0]; |
323,32 → 328,16
reg [128+3-1:0] ram_w_data [FPW-1:0]; |
|
wire [RAM_ADDR_SIZE-1:0] ram_r_addr; |
assign ram_r_addr = rx_rrp[HMC_PTR_SIZE-1:HMC_PTR_SIZE-RAM_ADDR_SIZE]; |
assign ram_r_addr = rx_rrp[7:8-RAM_ADDR_SIZE]; |
|
//Avoid overwriting not acknowleged FLITs in the retry buffer |
wire [RAM_ADDR_SIZE-1:0] ram_result; |
assign ram_result = ram_r_addr - ram_w_addr_next; |
|
//A safe value since ram_w_addr is calculated some cycles after packets were accepted |
//A safe value since ram_w_addr_next is calculated some cycles after packets were accepted |
wire ram_full; |
assign ram_full = (ram_result<9 && ram_result>0) ? 1'b1 : 1'b0 ; |
|
|
//Header/Tail fields, and at the same time form the RAM read pointer |
reg [RAM_ADDR_SIZE-1:0] tx_frp_adr; |
reg [2:0] tx_seqnum; |
reg tx_frp_adr_incr_temp; |
reg [LOG_FPW:0] tx_seqnum_temp; |
|
//variable to construct the frp |
wire [HMC_PTR_SIZE-RAM_ADDR_SIZE-1:0] tx_frp_ram [FPW-1:0]; |
|
generate |
for(f = 0; f < (FPW); f = f + 1) begin : assign_ram_addresses |
assign tx_frp_ram[f] = f; |
end |
endgenerate |
|
//Regs for TX Link retry handling |
reg tx_retry_finished; |
reg tx_retry_ongoing; |
355,16 → 344,21
reg tx_link_retry_request; //Sample the retry request |
|
//------------------------------------------------------------------------------------RRP Stage |
reg [128-1:0] data2rrp_stage_flit [FPW-1:0]; |
reg [127:0] data2rrp_stage_flit [FPW-1:0]; |
reg [FPW-1:0] data2rrp_stage_flit_is_hdr; |
reg [FPW-1:0] data2rrp_stage_flit_is_tail; |
reg [FPW-1:0] data2rrp_stage_flit_is_valid; |
reg data2rrp_stage_is_flow; |
|
reg [7:0] last_transmitted_rx_hmc_frp; |
`ifdef SIMULATION |
//We dont want to crash a simulation run because PRETs are still travelling upon test completion, so we include a trigger to only send PRETs when necessary in simulation |
//In hardware, PRETs will be sent whenever there is no valid FLIT on position 0 -> reduces the overall pointer return delay |
reg [7:0] last_transmitted_rx_hmc_frp; |
`else |
reg send_prets; |
`endif |
|
//------------------------------------------------------------------------------------CRC |
reg [128-1:0] data2crc_flit [FPW-1:0]; |
reg [127:0] data2crc_flit [FPW-1:0]; |
wire [DWIDTH-1:0] data2crc; |
reg [FPW-1:0] data2crc_flit_is_hdr; |
reg [FPW-1:0] data2crc_flit_is_tail; |
371,7 → 365,7
|
generate |
for(f = 0; f < (FPW); f = f + 1) begin : concatenate_flits_to_single_reg |
assign data2crc[(f*128)+128-1:(f*128)] = data2crc_flit[f]; |
assign data2crc[(f*128)+127:(f*128)] = data2crc_flit[f]; |
end |
endgenerate |
|
378,27 → 372,31
//------------------------------------------------------------------------------------FLOW PACKETS |
//TRET |
wire [63:0] tret_hdr; |
assign tret_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000010}; |
assign tret_hdr = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000010}; |
//PRET |
wire [63:0] pret_hdr ; |
assign pret_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000001}; |
wire [63:0] pret_hdr; |
assign pret_hdr = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000001}; |
|
//------------------------------------------------------------------------------------RTC HANDLING |
//Registers for the RTC field in request packets |
reg rtc_return; |
reg [4:0] rtc_return_val; |
reg rtc_return_sent; |
|
//A safe value to not send more FLITs than the HMC can buffer |
reg [LOG_FPW:0] flits_in_buf; |
reg [LOG_FPW:0] flits_transmitted; |
reg [9:0] remaining_tokens; |
reg [LOG_FPW-1:0] num_flits_in_buf; |
reg [LOG_FPW:0] num_flits_transmitted; |
reg [LOG_MAX_RX_TOKENS-1:0]remaining_tokens; |
localparam TOKENS_THRESHOLD= (FPW == 2) ? 11 : |
(FPW == 4) ? 15 : |
(FPW == 6) ? 23 : |
(FPW == 8) ? 23 : |
1; |
wire hmc_tokens_av; |
assign hmc_tokens_av = ((rf_hmc_tokens_av+flits_in_buf) > 8+(2*FPW)) ? 1'b1 : 1'b0; |
assign hmc_tokens_av = ((rf_hmc_tokens_av+num_flits_in_buf+rx_returned_tokens) > TOKENS_THRESHOLD) ? 1'b1 : 1'b0; |
|
//Return a maximum of 31 tokens |
wire [4:0] outstanding_tokens_to_return; |
assign outstanding_tokens_to_return = remaining_tokens > 31 ? 31 : remaining_tokens; |
assign outstanding_tokens_to_return = (OPEN_RSP_MODE==0) ? (remaining_tokens > 31 ? 31 : remaining_tokens[4:0]) : 5'h0; |
|
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
424,7 → 422,7
//==================================================================== |
//Track the remaining tokens in the rx input buffer. This is optional since the HMC must make sure not to send more tokens than RX can buffer, useful for debugging |
generate |
if(DBG_RX_TOKEN_MON==1) begin : Tokens_in_RX_buf |
if(DBG_RX_TOKEN_MON==1 && OPEN_RSP_MODE==0) begin : Tokens_in_RX_buf |
|
reg [6:0] sum_requested_tokens; //Count the amount of tokens requested from the HMC |
reg [6:0] sum_requested_tokens_temp; //Use this register for combinational logic |
461,26 → 459,27
end |
|
//Monitor remaining tokens in the openHMC RX input buffer |
reg [LOG_MAX_RX_TOKENS-1:0] rx_tokens_av; |
assign rf_rx_tokens_av = rx_tokens_av; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_rx_tokens_av <= {10{1'b0}}; |
rx_tokens_av <= {LOG_MAX_RX_TOKENS{1'b0}}; |
end else begin |
if(state==TX_NULL_1)begin |
if(state==INIT_TX_NULL_1)begin |
//initialize token counts when HMC init is not done |
rf_rx_tokens_av <= rf_rx_buffer_rtc; |
rx_tokens_av <= rf_rx_buffer_rtc; |
end else begin |
//calculate remaining tokens in RX buffers |
rf_rx_tokens_av <= rf_rx_tokens_av + rx_hmc_tokens_to_return - sum_requested_tokens; |
rx_tokens_av <= rx_tokens_av + rx_hmc_tokens_to_return - sum_requested_tokens; |
end |
end |
end |
|
|
end else begin |
always @(posedge clk) begin |
rf_rx_tokens_av <= 10'h0; |
end |
assign rf_rx_tokens_av = {LOG_MAX_RX_TOKENS{1'b0}}; |
end |
endgenerate |
|
490,11 → 489,130
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
//----Data |
if(!res_n) begin |
|
//----Init Regs |
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin //set |
ts1_seq_nr_per_flit[i_t]<= i_t; |
end |
num_null_cycles_sent <= {LOG_CYCLES_NULL_TO_SEND{1'b0}}; |
|
//General |
init_state <= INIT_TX_NULL_1; |
rtc_rx_initialize <= 1'b1; |
end |
else begin |
|
case(init_state) |
//---------------------------------INIT. Refer to Initialization section in the specification |
|
INIT_TX_NULL_1: begin |
//---init_state--- |
if(rf_hmc_received_init_null)begin |
init_state <= INIT_TX_TS1; |
end |
|
end |
|
INIT_TX_TS1: begin |
|
rtc_rx_initialize <= 1'b0; |
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin |
ts1_seq_nr_per_flit[i_t] <= ts1_seq_nr_per_flit[i_t] + TS1_SEQ_INC_VAL_PER_CYCLE; |
end |
|
//---init_state--- |
if(rf_descramblers_aligned)begin |
init_state <= INIT_TX_NULL_2; |
end |
|
end |
|
INIT_TX_NULL_2: begin |
//Issue at least 32 NULL FLITs before going active |
if(&num_null_cycles_sent && rf_link_is_up) begin |
init_state <= INIT_DONE; |
end |
num_null_cycles_sent <= num_null_cycles_sent + 1; |
end |
default: begin |
end |
endcase |
|
if(!LXTXPS || rf_warm_reset) begin |
init_state <= INIT_TX_NULL_1; |
if(rf_warm_reset) |
rtc_rx_initialize <= 1'b1; |
end |
|
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
`ifdef RESET_ALL |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1) data2rtc_stage_flit[i_f] <= {128{1'b0}}; |
for(i_f=0;i_f<FPW-1;i_f=i_f+1) d_in_buf_flit[i_f] <= {128{1'b0}}; |
end else |
`endif |
begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= {128{1'b0}}; |
end |
|
case(state) |
|
INIT: begin |
if(init_state == INIT_TX_TS1) begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= ts1_flit[i_f]; |
end |
end |
end |
|
IDLE: begin |
if(|remaining_tokens && !ram_full)begin |
data2rtc_stage_flit[0] <= {{64{1'b0}},tret_hdr}; |
end |
end |
|
TX: begin |
//Choose the data source |
if(d_in_use_buf) begin |
for(i_f=0;i_f<FPW-1;i_f=i_f+1) begin |
data2rtc_stage_flit[i_f+1] <= d_in_buf_flit[i_f]; |
end |
end else begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= d_in_flit[i_f]; |
end |
end |
|
for(i_f=0;i_f<FPW-1;i_f=i_f+1)begin |
//No matter what, fill the buffer |
d_in_buf_flit[i_f] <= d_in_flit[i_f+1]; |
end |
end |
|
HMC_RTRY: begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY start retry |
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000001,8'h00,irtry_hdr}; |
end |
end |
|
LNK_RTRY: begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY clear error abort |
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000010,8'h00,irtry_hdr}; |
end |
end |
endcase |
end |
|
if(!res_n) begin |
data2rtc_stage_flit_is_hdr <= {FPW{1'b0}}; |
data2rtc_stage_flit_is_tail <= {FPW{1'b0}}; |
data2rtc_stage_flit_is_valid <= {FPW{1'b0}}; |
504,36 → 622,24
d_in_shift_out <= 1'b0; |
|
//----Reset the input buffer reg |
d_in_buf_flit_is_hdr <= {FPW{1'b0}}; |
d_in_buf_flit_is_tail <= {FPW{1'b0}}; |
d_in_buf_flit_is_valid <= {FPW{1'b0}}; |
d_in_buf_flit_is_hdr <= {FPW-1{1'b0}}; |
d_in_buf_flit_is_valid <= {FPW-1{1'b0}}; |
d_in_use_buf <= 1'b0; |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
d_in_buf_flit[i_f] <= {128{1'b0}}; |
end |
|
//----Init Regs |
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin |
ts1_seq_nr_per_flit[i_t] <= i_t; |
end |
num_init_nulls_sent <= 6'h0; |
|
//General |
state <= TX_NULL_1; |
rtc_rx_initialize <= 1'b1; |
state <= INIT; |
|
//Token Flow Control |
remaining_tokens <= {10{1'b0}}; |
remaining_tokens <= {LOG_MAX_RX_TOKENS{1'b0}}; |
rtc_return_val <= {5{1'b0}}; |
rtc_return <= 1'b0; |
|
//Retry |
irtry_start_retry_cnt <= {6{1'b0}}; |
irtry_clear_error_cnt <= {6{1'b0}}; |
irtry_start_retry_cnt <= {5{1'b0}}; |
irtry_clear_error_cnt <= {5{1'b0}}; |
|
//HMC Control |
hmc_LxRXPS <= 1'b1; |
rf_hmc_is_in_sleep <= 1'b0; |
LXRXPS <= 1'b1; |
|
//Flow Control |
tx_link_retry_request <= 1'b0; |
544,25 → 650,17
//---------------------------------INIT |
//==================================================================== |
//Reset control signals |
d_in_shift_out <= 1'b0; |
rtc_rx_initialize <= 1'b0; |
d_in_shift_out <= 1'b0; |
irtry_start_retry_cnt <= {5{1'b0}}; |
irtry_clear_error_cnt <= {5{1'b0}}; |
|
//HMC Control |
hmc_LxRXPS <= 1'b1; |
rf_hmc_is_in_sleep <= 1'b0; |
LXRXPS <= 1'b1; |
|
if(rx_force_tx_retry)begin |
tx_link_retry_request <= 1'b1; |
end |
|
//Warm Reset |
// if(rf_warm_reset) begin |
// //in case of a warm reset request, continue at TX_NULL_2 sequence and intialize tokens to be returned |
// state <= TX_NULL_2; |
// num_init_nulls_sent <= {6{1'b0}}; |
// rtc_rx_initialize <= 1'b1; |
// end |
|
//RTC |
rtc_return <= 1'b0; |
//Initialize rtc to be transmitted after reset and warm reset |
579,61 → 677,10
data2rtc_stage_is_flow <= 1'b0; |
data2rtc_stage_force_tx_retry <= 1'b0; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= 128'h0; |
end |
rtc_return_val <= outstanding_tokens_to_return; |
|
case(state) |
|
//---------------------------------INIT. Refer to Initialization section in the specification |
|
TX_NULL_1: begin |
|
num_init_nulls_sent <= 6'h0; |
|
//---State--- |
if(rf_hmc_received_init_null)begin |
state <= TX_TS1; |
end |
|
end |
|
TX_TS1: begin |
|
data2rtc_stage_is_flow <= 1'b1; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= ts1_flit[i_f]; |
end |
|
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin |
ts1_seq_nr_per_flit[i_t] <= ts1_seq_nr_per_flit[i_t] + TS1_SEQ_INC_VAL_PER_CYCLE; |
end |
|
//---State--- |
if(rf_descramblers_aligned)begin |
state <= TX_NULL_2; |
end |
|
end |
|
TX_NULL_2: begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rtc_stage_flit[i_f] <= NULL_FLIT; |
end |
|
//Issue at least 32 NULL FLITs before going active |
if(num_init_nulls_sent+FPW > NUM_NULL_TO_SEND_BEFORE_IDLE) begin |
if(rf_link_is_up)begin |
state <= IDLE; |
end |
end else begin |
num_init_nulls_sent <= num_init_nulls_sent + FPW; |
end |
|
end |
|
//==================================================================== |
//---------------------------------Normal operation (including init TRETs) |
//==================================================================== |
640,23 → 687,24
// Some branches to other states may be removed in HMC_RTRY for instance. |
// Saves logic if an additional cycle in IDLE is acceptable |
|
INIT: begin |
if(init_state==INIT_DONE) state <= IDLE; |
end |
|
IDLE: begin |
//Issue NULL Flits if there's nothing else to do |
|
//SEND TRET PACKET even if there are no tokens available |
if(remaining_tokens && !ram_full && !tx_retry_ongoing && !rf_dbg_dont_send_tret)begin |
//RTC will be added in the RTC stage |
data2rtc_stage_flit[0] <= {{64{1'b0}},tret_hdr}; |
if(|remaining_tokens && !ram_full)begin |
data2rtc_stage_flit_is_hdr[0] <= 1'b1; |
data2rtc_stage_flit_is_tail[0] <= 1'b1; |
data2rtc_stage_flit_is_valid[0] <= 1'b1; |
|
remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_return + rx_hmc_poisoned_tokens_to_return - outstanding_tokens_to_return; |
rtc_return_val <= outstanding_tokens_to_return; |
rtc_return <= 1'b1; |
end |
|
//---State--- |
// //---State--- |
if(force_hmc_retry) begin |
state <= HMC_RTRY; |
end else if(tx_link_retry_request) begin |
678,65 → 726,52
d_in_shift_out <= 1'b1; |
|
//Fill the buffer |
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr; |
d_in_buf_flit_is_tail <= d_in_flit_is_tail; |
d_in_buf_flit_is_valid <= d_in_flit_is_valid; |
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr[FPW-1:1]; |
d_in_buf_flit_is_valid <= d_in_flit_is_valid[FPW-1:1]; |
|
//If there is data buffered - use it |
data2rtc_stage_flit_is_hdr <= d_in_use_buf ? d_in_buf_flit_is_hdr : d_in_flit_is_hdr; |
data2rtc_stage_flit_is_tail <= d_in_use_buf ? d_in_buf_flit_is_tail : d_in_flit_is_tail; |
data2rtc_stage_flit_is_valid <= d_in_use_buf ? d_in_buf_flit_is_valid : d_in_flit_is_valid; |
data2rtc_stage_flit_is_hdr <= d_in_use_buf ? {d_in_buf_flit_is_hdr,1'b0} : d_in_flit_is_hdr; |
data2rtc_stage_flit_is_tail <= d_in_use_buf ? {FPW{1'b0}} : d_in_flit_is_tail; |
data2rtc_stage_flit_is_valid <= d_in_use_buf ? {d_in_buf_flit_is_valid,1'b0} : d_in_flit_is_valid; |
|
//Set RTC to be added in the next step |
if( remaining_tokens && |
//if buffer should be used -> take buffered tail information |
((d_in_use_buf && |d_in_buf_flit_is_tail) || |
//otherwise use regular data input |
(!d_in_use_buf && |d_in_flit_is_tail)) |
if( |remaining_tokens && |
(!d_in_use_buf && |d_in_flit_is_tail) |
) begin |
remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_return + rx_hmc_poisoned_tokens_to_return - outstanding_tokens_to_return; |
rtc_return_val <= outstanding_tokens_to_return; |
rtc_return <= 1'b1; |
end |
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
//Choose the data source |
data2rtc_stage_flit[i_f] <= !d_in_use_buf ? d_in_flit[i_f] : d_in_buf_flit[i_f]; |
//No matter what, fill the buffer |
d_in_buf_flit[i_f] <= d_in_flit[i_f]; |
end |
|
|
//Exit state if seen a tail and exit condition occured |
if( ((!d_in_use_buf && |d_in_flit_is_tail) || (d_in_use_buf && |d_in_buf_flit_is_tail)) && |
if( ((!d_in_use_buf && |d_in_flit_is_tail)) && |
(force_hmc_retry || ram_full || tx_link_retry_request || !hmc_tokens_av || d_in_a_empty)) begin |
|
d_in_shift_out <= 1'b0; |
|
if(force_hmc_retry) begin |
state <= HMC_RTRY; |
end else if(tx_link_retry_request) begin |
state <= LNK_RTRY; |
end else begin |
state <= IDLE; |
end |
|
case ({force_hmc_retry,tx_link_retry_request}) |
2'b00: state <= IDLE; |
2'b01: state <= LNK_RTRY; |
default: state <= HMC_RTRY; |
endcase |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if((d_in_use_buf && d_in_buf_flit_is_tail[i_f]) || (!d_in_use_buf && d_in_flit_is_tail[i_f]))begin |
if(!d_in_use_buf && d_in_flit_is_tail[i_f])begin |
data2rtc_stage_flit_is_valid <= {FPW{1'b1}} >> {FPW-1-i_f}; |
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr & ({FPW{1'b1}} << (i_f + 1)); |
d_in_buf_flit_is_tail <= d_in_flit_is_tail & ({FPW{1'b1}} << (i_f + 1)); |
d_in_buf_flit_is_valid <= d_in_flit_is_valid & ({FPW{1'b1}} << (i_f + 1)); |
end |
end |
|
for(i_f=1;i_f<FPW;i_f=i_f+1)begin |
if(d_in_flit_is_tail[i_f])begin |
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr[FPW-1:1] & ({FPW-1{1'b1}} << i_f); |
d_in_buf_flit_is_valid <= d_in_flit_is_valid[FPW-1:1] & ({FPW-1{1'b1}} << i_f); |
end |
end |
|
//Use buf next time TX state is entered if there is a packet pending |
if((!d_in_use_buf && (d_in_flit_is_hdr[FPW-1:1] > d_in_flit_is_tail[FPW-1:1])) || |
(d_in_use_buf && (d_in_buf_flit_is_hdr[FPW-1:1] > d_in_buf_flit_is_tail[FPW-1:1])) )begin |
if(!d_in_use_buf && (d_in_flit_is_hdr[FPW-1:1] > d_in_flit_is_tail[FPW-1:1]))begin |
d_in_use_buf <= 1'b1; |
end |
|
end |
end |
|
743,31 → 778,13
//---------------------------------An error in RX path occured - send irtry start packets |
HMC_RTRY: begin |
|
data2rtc_stage_flit_is_hdr <= {FPW{1'b1}}; |
data2rtc_stage_flit_is_tail <= {FPW{1'b1}}; |
data2rtc_stage_flit_is_valid <= {FPW{1'b1}}; |
data2rtc_stage_is_flow <= 1'b1; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY start retry |
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000001,8'h00,irtry_hdr}; |
end |
|
irtry_start_retry_cnt <= irtry_start_retry_cnt + FPW; |
|
if(irtry_start_retry_cnt+FPW >= rf_irtry_to_send)begin |
irtry_start_retry_cnt <= {6{1'b0}}; |
|
//---State--- |
if(rf_dbg_halt_on_error_abort) begin |
state <= DEBUG; |
end else if(tx_link_retry_request) begin |
state <= LNK_RTRY; |
end else if(!d_in_empty && !ram_full && hmc_tokens_av)begin |
state <= TX; |
d_in_shift_out <= ~d_in_use_buf; |
end else begin |
state <= IDLE; |
end |
irtry_start_retry_cnt <= {5{1'b0}}; |
state <= IDLE; |
end |
|
end |
777,17 → 794,12
// re-send all valid packets in RAM after sending clear error packets |
LNK_RTRY: begin |
|
if(!tx_retry_ongoing && (tx_link_retry_request || irtry_clear_error_cnt>0)) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY clear error abort |
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000010,8'h00,irtry_hdr}; |
end |
data2rtc_stage_flit_is_hdr <= {FPW{1'b1}}; |
data2rtc_stage_flit_is_tail <= {FPW{1'b1}}; |
data2rtc_stage_flit_is_valid <= {FPW{1'b1}}; |
if(!tx_retry_ongoing && (tx_link_retry_request || |irtry_clear_error_cnt)) begin |
|
data2rtc_stage_is_flow <= 1'b1; |
|
if(irtry_clear_error_cnt+FPW >= rf_irtry_to_send)begin |
irtry_clear_error_cnt <= {6{1'b0}}; |
irtry_clear_error_cnt <= {5{1'b0}}; |
data2rtc_stage_force_tx_retry <= 1'b1; |
end else begin |
irtry_clear_error_cnt <= irtry_clear_error_cnt + FPW; |
795,20 → 807,10
end |
|
if(tx_retry_finished && !tx_link_retry_request) begin |
//---State--- |
if(rf_dbg_halt_on_tx_retry) begin |
state <= DEBUG; |
end else if(force_hmc_retry) begin |
state <= HMC_RTRY; |
end else if(!d_in_empty && !ram_full && hmc_tokens_av) begin |
state <= TX; |
d_in_shift_out <= ~d_in_use_buf; |
end else begin |
state <= IDLE; |
end |
state <= IDLE; |
end |
|
if(!tx_retry_ongoing) begin |
if(!tx_retry_ongoing && !rx_force_tx_retry) begin |
tx_link_retry_request <= 1'b0; |
end |
end |
816,45 → 818,30
//---------------------------------Power State Management |
SLEEP: begin |
|
hmc_LxRXPS <= 1'b0; |
|
if(!hmc_LxTXPS) begin |
rf_hmc_is_in_sleep <= 1'b1; |
if(rf_hmc_sleep_requested) begin |
LXRXPS <= 1'b0; |
end else begin |
state <= WAIT_FOR_HMC; |
end |
|
if(!rf_hmc_sleep_requested) begin |
state <= WAIT_FOR_HMC; |
hmc_LxRXPS <= 1'b1; |
end |
|
end |
|
WAIT_FOR_HMC: begin |
|
rf_hmc_is_in_sleep <= 1'b1; |
|
if(hmc_LxTXPS) begin |
state <= TX_NULL_1; |
if(LXTXPS) begin |
state <= INIT; |
end |
|
end |
|
DEBUG: begin |
//Freeze execution to debug in hardware |
if(!(rf_dbg_halt_on_tx_retry || rf_dbg_halt_on_error_abort)) begin |
state <= IDLE; |
end else begin |
state <= DEBUG; |
end |
end |
|
endcase |
|
if(!rf_hmc_init_cont_set) begin |
state <= TX_NULL_1; |
num_init_nulls_sent <= 6'h0; |
rtc_rx_initialize <= 1'b1; |
//Warm Reset |
if(rf_warm_reset) begin |
//in case of a warm reset request, continue at INIT_TX_NULL_2 sequence and intialize tokens to be returned |
state <= INIT; |
end |
|
end |
end |
|
865,15 → 852,17
//This always block remains combinational to save one cycle |
always @(*) begin |
|
flits_transmitted = {LOG_FPW+1{1'b0}}; |
flits_in_buf = {LOG_FPW+1{1'b0}}; |
num_flits_transmitted = {LOG_FPW+1{1'b0}}; |
num_flits_in_buf = {LOG_FPW{1'b0}}; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(d_in_flit_is_valid[i_f] && d_in_shift_out) begin |
flits_transmitted = flits_transmitted + {{LOG_FPW{1'b0}},1'b1}; |
num_flits_transmitted = num_flits_transmitted + 1; |
end |
end |
for(i_f=0;i_f<FPW-1;i_f=i_f+1)begin |
if(d_in_buf_flit_is_valid[i_f] && d_in_use_buf) begin |
flits_in_buf = flits_in_buf + {{LOG_FPW{1'b0}},1'b1}; |
num_flits_in_buf = num_flits_in_buf + 1; |
end |
end |
end |
882,14 → 871,14
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_hmc_tokens_av <= {10{1'b0}}; |
rf_hmc_tokens_av <= {LOG_MAX_HMC_TOKENS{1'b0}}; |
end else begin |
rf_hmc_tokens_av <= rf_hmc_tokens_av + rx_returned_tokens - flits_transmitted; |
rf_hmc_tokens_av <= rf_hmc_tokens_av + rx_returned_tokens - num_flits_transmitted; |
end |
end |
|
//==================================================================== |
//---------------------------------Counter in the RF , right now only data transactions are counted |
//---------------------------------Counter in the RF, currently only data transactions are counted |
//==================================================================== |
always @(*) begin |
|
921,20 → 910,61
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_sent_p <= {HMC_RF_RWIDTH{1'b0}}; |
rf_sent_np <= {HMC_RF_RWIDTH{1'b0}}; |
rf_sent_r <= {HMC_RF_RWIDTH{1'b0}}; |
end else begin |
rf_sent_p <= rf_sent_p + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_p_comb}; |
rf_sent_np <= rf_sent_np + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_np_comb}; |
rf_sent_r <= rf_sent_r + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_r_comb}; |
end |
end |
|
|
`ifdef XILINX |
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(LOG_FPW+1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) cnt_sent_p ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(rf_sent_p_comb), |
.value(rf_sent_p) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(LOG_FPW+1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) cnt_sent_np ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(rf_sent_np_comb), |
.value(rf_sent_np) |
); |
|
openhmc_counter48_wrapper_xilinx #( |
.INC_SIZE(LOG_FPW+1), |
.PIPELINED(XIL_CNT_PIPELINED) |
) cnt_sent_r ( |
.clk(clk), |
.res_n(res_n), |
.inc_value(rf_sent_r_comb), |
.value(rf_sent_r) |
); |
`else |
reg [RF_COUNTER_SIZE-1:0] rf_sent_p_temp; |
reg [RF_COUNTER_SIZE-1:0] rf_sent_np_temp; |
reg [RF_COUNTER_SIZE-1:0] rf_sent_r_temp; |
assign rf_sent_p = rf_sent_p_temp; |
assign rf_sent_np = rf_sent_np_temp; |
assign rf_sent_r = rf_sent_r_temp; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
rf_sent_p_temp <= {RF_COUNTER_SIZE{1'b0}}; |
rf_sent_np_temp <= {RF_COUNTER_SIZE{1'b0}}; |
rf_sent_r_temp <= {RF_COUNTER_SIZE{1'b0}}; |
end else begin |
rf_sent_p_temp <= rf_sent_p_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_p_comb}; |
rf_sent_np_temp <= rf_sent_np_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_np_comb}; |
rf_sent_r_temp <= rf_sent_r_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_r_comb}; |
end |
end |
`endif |
|
//==================================================================== |
//---------------------------------HMC Retry Logic |
//==================================================================== |
952,7 → 982,7
rf_error_abort_not_cleared <= 1'b0; |
|
if(rx_error_abort_mode)begin |
error_abort_mode_clr_cnt <= error_abort_mode_clr_cnt + 1; |
error_abort_mode_clr_cnt <= error_abort_mode_clr_cnt + 1; //decrement counter |
end |
|
if(rx_error_abort_mode_cleared) begin |
959,13 → 989,13
error_abort_mode_clr_cnt <= {8{1'b0}}; |
end |
|
if((rx_error_abort_mode && state!=HMC_RTRY && error_abort_mode_clr_cnt==0) || (error_abort_mode_clr_cnt > CYCLES_TO_CLEAR_ERR_ABORT_MODE))begin |
if(&error_abort_mode_clr_cnt) begin |
rf_error_abort_not_cleared <= 1'b1; |
end |
|
if((rx_error_abort_mode && state!=HMC_RTRY && |error_abort_mode_clr_cnt==1'b0) || (&error_abort_mode_clr_cnt))begin |
force_hmc_retry <= 1'b1; |
error_abort_mode_clr_cnt <= {8{1'b0}}; |
|
if(error_abort_mode_clr_cnt > CYCLES_TO_CLEAR_ERR_ABORT_MODE) begin |
rf_error_abort_not_cleared <= 1'b1; |
end |
|
end else begin |
if(state==HMC_RTRY)begin |
force_hmc_retry <= 1'b0; |
978,71 → 1008,105
//==================================================================== |
//---------------------------------RTC Stage |
//==================================================================== |
always @(*) begin |
rtc_return_sent = 0; |
generate |
if(OPEN_RSP_MODE==0) begin : RTC_stage |
reg [4:0] data2seq_frp_stage_flit_rtc [FPW-1:0]; |
reg rtc_return_sent; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2seq_frp_stage_flit_comb[i_f] = data2rtc_stage_flit[i_f]; |
always @(*) begin |
rtc_return_sent = 0; |
|
if(data2rtc_stage_flit_is_tail[i_f] && !data2rtc_stage_is_flow && !rtc_return_sent && rtc_return) begin |
//Return outstanding tokens, but only once per cycle |
data2seq_frp_stage_flit_comb[i_f][64+31:64+27] = rtc_return_val; |
rtc_return_sent = 1'b1; |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(data2rtc_stage_flit_is_tail[i_f] && !rtc_return_sent && rtc_return) begin |
//Return outstanding tokens, but only once per cycle |
data2seq_frp_stage_flit_rtc[i_f] = rtc_return_val; |
rtc_return_sent = 1'b1; |
end else begin |
data2seq_frp_stage_flit_rtc[i_f] = 5'h00; |
end |
end |
end |
end |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
data2seq_frp_stage_flit_is_hdr <= {FPW{1'b0}}; |
data2seq_frp_stage_flit_is_tail <= {FPW{1'b0}}; |
data2seq_frp_stage_flit_is_valid <= {FPW{1'b0}}; |
data2seq_frp_stage_is_flow <= 1'b0; |
data2seq_frp_stage_force_tx_retry <= 1'b0; |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2seq_frp_stage_flit[i_f] <= {128{1'b0}}; |
`ifdef ASYNC_RES |
if(!res_n) |
data2seq_frp_stage_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
begin |
data2seq_frp_stage_flit[i_f] <= data2rtc_stage_flit[i_f]; |
if(data2rtc_stage_flit_is_tail[i_f]) begin |
data2seq_frp_stage_flit[i_f][64+31:64+27] <= data2seq_frp_stage_flit_rtc[i_f]; |
end |
end |
end |
end |
end else begin |
data2seq_frp_stage_flit_is_hdr <= data2rtc_stage_flit_is_hdr & data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_flit_is_tail <= data2rtc_stage_flit_is_tail & data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_flit_is_valid <= data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_is_flow <= data2rtc_stage_is_flow; |
data2seq_frp_stage_force_tx_retry <= data2rtc_stage_force_tx_retry; |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2seq_frp_stage_flit[i_f] <= data2seq_frp_stage_flit_comb[i_f]; |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
`ifdef ASYNC_RES |
if(!res_n) |
data2seq_frp_stage_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
begin |
data2seq_frp_stage_flit[i_f] <= data2rtc_stage_flit[i_f]; |
end |
end |
end |
end |
end |
endgenerate |
|
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
`ifdef RESET_ALL |
if(!res_n) begin |
data2seq_frp_stage_flit_is_hdr <= {FPW{1'b0}}; |
data2seq_frp_stage_flit_is_tail <= {FPW{1'b0}}; |
data2seq_frp_stage_flit_is_valid <= {FPW{1'b0}}; |
data2seq_frp_stage_is_flow <= 1'b0; |
data2seq_frp_stage_force_tx_retry <= 1'b0; |
end else |
`endif |
begin |
data2seq_frp_stage_flit_is_hdr <= data2rtc_stage_flit_is_hdr & data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_flit_is_tail <= data2rtc_stage_flit_is_tail & data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_flit_is_valid <= data2rtc_stage_flit_is_valid; |
data2seq_frp_stage_is_flow <= data2rtc_stage_is_flow; |
data2seq_frp_stage_force_tx_retry <= data2rtc_stage_force_tx_retry; |
end |
end |
|
//==================================================================== |
//---------------------------------Seqnum and FRP Stage |
//==================================================================== |
|
always @(*) begin |
tx_seqnum_temp = {LOG_FPW+1{1'b0}}; |
|
//Set data flits |
tx_seqnum_inc = {LOG_FPW{1'b0}}; |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(data2seq_frp_stage_flit_is_valid[i_f] | data2seq_frp_stage_is_flow) begin |
data2ram_flit_temp[i_f] = data2seq_frp_stage_flit[i_f]; |
end else begin |
data2ram_flit_temp[i_f] = {128{1'b0}}; |
tx_seqnum_temp[i_f] = 0; |
if(data2seq_frp_stage_flit_is_tail[i_f])begin |
tx_seqnum_inc = tx_seqnum_inc + 1; |
tx_seqnum_temp[i_f] = tx_seqnum + tx_seqnum_inc; |
end |
end |
|
//Increment ram addr(also frp) if there is a valid FLIT that is not flow |
if(|data2seq_frp_stage_flit_is_valid && !data2seq_frp_stage_is_flow)begin |
tx_frp_adr_incr_temp = 1'b1; |
end else begin |
tx_frp_adr_incr_temp = 1'b0; |
end |
target_temp[0] = next_target; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(data2seq_frp_stage_flit_is_tail[i_f] && !data2seq_frp_stage_is_flow && data2seq_frp_stage_flit_is_valid[i_f])begin |
tx_seqnum_temp = tx_seqnum_temp + 1; |
//Assign the FRP, combined of the ram selected and the RAM address |
data2ram_flit_temp[i_f][64+15+3:64+8] = {tx_seqnum+tx_seqnum_temp,tx_frp_adr+tx_frp_adr_incr_temp,tx_frp_ram[i_f]}; |
if(data2rtc_stage_flit_is_valid[i_f]) begin |
target_temp[i_f+1] = target_temp[i_f] + 1; |
if(target_temp[i_f+1]==FPW) |
target_temp[i_f+1]=0; |
end else begin |
target_temp[i_f+1] = target_temp[i_f]; |
end |
end |
end |
1051,12 → 1115,20
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
//Reset frp and seqnum |
tx_frp_adr <= {LOG_FPW{1'b0}}; |
//Reset the target RAM location and seqnum |
tx_seqnum <= {LOG_FPW{1'b0}}; |
next_target <= {LOG_FPW{1'b0}}; |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
target[i_f] <= {FPW{1'b0}}; |
end |
end else begin |
tx_frp_adr <= tx_frp_adr + tx_frp_adr_incr_temp; |
tx_seqnum <= tx_seqnum + tx_seqnum_temp; |
tx_seqnum <= tx_seqnum + tx_seqnum_inc; |
if(!data2rtc_stage_is_flow) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
target[i_f] <= target_temp[i_f]; |
end |
next_target <= target_temp[FPW]; |
end |
end |
end |
|
1064,24 → 1136,44
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
data2ram_flit_is_hdr <= {FPW{1'b0}}; |
data2ram_flit_is_tail <= {FPW{1'b0}}; |
data2ram_flit_is_valid <= {FPW{1'b0}}; |
data2ram_is_flow <= 1'b0; |
data2ram_force_tx_retry <= 1'b0; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2ram_flit[i_f] <= {128{1'b0}}; |
`ifdef RESET_ALL |
if(!res_n) data2ram_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
begin |
data2ram_flit[i_f] <= data2seq_frp_stage_flit[i_f]; |
|
if(data2seq_frp_stage_flit_is_tail[i_f]) begin |
data2ram_flit[i_f][64+15+3:64+8] <= {tx_seqnum_temp[i_f],tx_frp_adr[target[i_f]],target[i_f]}; |
end |
end |
end |
end else begin |
data2ram_flit_is_hdr <= data2seq_frp_stage_flit_is_hdr; |
|
data2ram_flit_is_hdr <= data2seq_frp_stage_flit_is_hdr | {FPW{data2seq_frp_stage_is_flow}}; |
data2ram_flit_is_tail <= data2seq_frp_stage_flit_is_tail; |
data2ram_flit_is_valid <= data2seq_frp_stage_flit_is_valid; |
data2ram_is_flow <= data2seq_frp_stage_is_flow ; |
data2ram_flit_is_valid <= data2seq_frp_stage_flit_is_valid | {FPW{data2seq_frp_stage_is_flow}}; |
data2ram_force_tx_retry <= data2seq_frp_stage_force_tx_retry; |
if(!res_n) begin |
`ifdef RESET_ALL |
data2ram_flit_is_hdr <= {FPW{1'b0}}; |
data2ram_flit_is_tail <= {FPW{1'b0}}; |
data2ram_flit_is_valid <= {FPW{1'b0}}; |
data2ram_force_tx_retry <= 1'b0; |
`endif |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2ram_flit[i_f] <= data2ram_flit_temp[i_f]; |
tx_frp_adr[i_f] <= {RAM_ADDR_SIZE{1'b0}}; |
end |
end else begin |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(data2seq_frp_stage_flit_is_valid[i_f]) begin |
tx_frp_adr[target[i_f]] <= tx_frp_adr[target[i_f]] + 1; |
end |
end |
|
end |
end |
|
1092,44 → 1184,30
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
ram_w_data[i_f] <= {128+3{1'b0}}; |
end |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
ram_w_data[target[i_f]] <= { data2seq_frp_stage_flit_is_valid[i_f], |
data2seq_frp_stage_flit_is_tail[i_f], |
data2seq_frp_stage_flit_is_hdr[i_f], |
data2seq_frp_stage_flit[i_f] |
}; |
|
end else begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(!data2ram_is_flow)begin |
ram_w_data[i_f] <= { data2ram_flit_is_valid[i_f], |
data2ram_flit_is_tail[i_f], |
data2ram_flit_is_hdr[i_f], |
data2ram_flit[i_f] |
}; |
if(data2seq_frp_stage_flit_is_tail[i_f])begin |
ram_w_data[target[i_f]][64+15+3:64+8] <= {tx_seqnum_temp[i_f],tx_frp_adr[target[i_f]],target[i_f]}; |
end |
end |
end |
end |
end |
|
//-- Write to RAM and increment the address if there are valid FLITs to be written |
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
if(!res_n) begin |
//Reset control signals |
ram_w_addr <= {RAM_ADDR_SIZE{1'b0}}; |
ram_w_en <= 1'b1; |
end else begin |
|
//Reset control signals |
ram_w_en <= 1'b0; |
|
if(|data2ram_flit_is_valid && !data2ram_is_flow) begin |
ram_w_addr <= ram_w_addr + 1; |
ram_w_en <= 1'b1; |
if(!res_n) begin |
ram_w_en <= {FPW{1'b0}}; |
end else begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(data2seq_frp_stage_flit_is_valid[i_f]) begin |
ram_w_en[target[i_f]] <= 1'b1; |
end else begin |
ram_w_en[target[i_f]] <= 1'b0; |
end |
end |
end |
|
end |
end |
|
//==================================================================== |
//---------------------------------Select Data Source: Valid sources are the Retry Buffers or regular data stream. |
1137,6 → 1215,24
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
`ifdef RESET_ALL |
if(!res_n) data2rrp_stage_flit[i_f] <= {128{1'b0}}; |
else |
`endif |
begin |
|
if(tx_retry_ongoing) begin |
//-- If there's a TX retry ongoing increment read address until it equals the write address |
data2rrp_stage_flit[i_f] <= ram_r_data[i_f][127:0]; |
end else begin |
//Propagate data from normal packet stream |
data2rrp_stage_flit[i_f] <= data2ram_flit[i_f]; |
end |
end |
end |
|
if(!res_n) begin |
//Reset control signals |
tx_retry_finished <= 1'b0; |
1146,52 → 1242,43
//Ram |
ram_r_en <= 1'b0; |
ram_r_addr_temp <= {RAM_ADDR_SIZE{1'b0}}; |
ram_r_mask <= {FPW{1'b1}}; |
ram_r_mask <= {FPW{1'b0}}; |
|
//Data propagation |
data2rrp_stage_flit_is_hdr <= {FPW{1'b0}}; |
data2rrp_stage_flit_is_tail <= {FPW{1'b0}}; |
data2rrp_stage_flit_is_valid <= {FPW{1'b0}}; |
data2rrp_stage_is_flow <= 1'b0; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rrp_stage_flit[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
tx_retry_finished <= 1'b0; |
tx_retry_ongoing <= 1'b0; |
rf_cnt_retry <= 1'b0; |
|
data2rrp_stage_is_flow <= 1'b0; |
ram_r_en <= 1'b0; |
ram_r_addr_temp <= {RAM_ADDR_SIZE{1'b0}}; |
ram_r_mask <= {FPW{1'b0}}; |
|
//if there is a retry request coming set the ram address to last received rrp |
if(data2rtc_stage_force_tx_retry) begin |
if(data2seq_frp_stage_force_tx_retry) begin |
ram_r_en <= 1'b1; |
ram_r_addr_temp <= ram_r_addr; |
ram_r_mask <= ({FPW{1'b1}}) << (rx_rrp[HMC_PTR_SIZE-RAM_ADDR_SIZE-1:0]); |
ram_r_addr_temp <= ram_r_addr+1; |
end |
|
if(!tx_retry_ongoing) begin |
|
//Propagate data from normal packet stream |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2rrp_stage_flit[i_f] <= data2ram_flit[i_f]; |
end |
data2rrp_stage_flit_is_hdr <= data2ram_flit_is_hdr; |
data2rrp_stage_flit_is_tail <= data2ram_flit_is_tail; |
data2rrp_stage_flit_is_valid <= data2ram_flit_is_valid; |
data2rrp_stage_is_flow <= data2ram_is_flow; |
|
|
//Switch to retry if requested |
if(data2ram_force_tx_retry) begin |
|
if(ram_r_addr_temp == ram_w_addr_next) begin //if the next address is the write address -> no retry. That should never happen |
if(ram_r_addr_temp == ram_w_addr_next) begin //if the next address is the write address -> no retry. |
tx_retry_finished <= 1'b1; |
tx_retry_ongoing <= 1'b0; |
ram_r_en <= 1'b0; |
end else begin |
ram_r_addr_temp <= ram_r_addr_temp + 1; |
ram_r_mask <= ({FPW{1'b1}}) << (rx_rrp[8-RAM_ADDR_SIZE-1:0]); |
ram_r_addr_temp <= ram_r_addr_temp+1; |
ram_r_en <= 1'b1; |
rf_cnt_retry <= 1'b1; |
tx_retry_ongoing <= 1'b1; |
end |
1202,28 → 1289,25
ram_r_mask <= {FPW{1'b1}}; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(ram_r_mask[i_f])begin |
//Within the first cycle of retry, choose only the proper flit sources |
data2rrp_stage_flit[i_f] <= ram_r_data[i_f][128-1:0]; |
data2rrp_stage_flit_is_hdr[i_f] <= ram_r_data[i_f][128]; |
data2rrp_stage_flit_is_tail[i_f] <= ram_r_data[i_f][128+1]; |
data2rrp_stage_flit_is_valid[i_f] <= ram_r_data[i_f][128+2]; |
end else begin |
//And reset all other FLITs because they're not meant to be retransmitted |
data2rrp_stage_flit[i_f] <= {128{1'b0}}; |
data2rrp_stage_flit_is_hdr[i_f] <= 1'b0; |
data2rrp_stage_flit_is_tail[i_f] <= 1'b0; |
data2rrp_stage_flit_is_valid[i_f] <= 1'b0; |
end |
end |
data2rrp_stage_flit_is_hdr[i_f] <= ram_r_mask[i_f] ? ram_r_data[i_f][128] :1'b0 ; |
data2rrp_stage_flit_is_tail[i_f] <= ram_r_mask[i_f] ? ram_r_data[i_f][128+1] :1'b0 ; |
data2rrp_stage_flit_is_valid[i_f] <= ram_r_mask[i_f] ? ram_r_data[i_f][128+2] :1'b0 ; |
end |
|
//if the next address is the write address -> retry finished |
if((ram_r_addr_temp) == ram_w_addr_next) begin |
if(ram_r_addr_temp == ram_w_addr_next) begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
if(i_f >= target[0] && !(tx_frp_adr[0]==tx_frp_adr[FPW-1]))begin |
data2rrp_stage_flit_is_hdr[i_f] <= 1'b0; |
data2rrp_stage_flit_is_tail[i_f] <= 1'b0; |
data2rrp_stage_flit_is_valid[i_f] <= 1'b0; |
end |
end |
tx_retry_finished <= 1'b1; |
tx_retry_ongoing <= 1'b0; |
ram_r_en <= 1'b0; |
end else begin |
ram_r_addr_temp <= ram_r_addr_temp + 1; |
ram_r_addr_temp <= ram_r_addr_temp + 1; |
tx_retry_ongoing <= 1'b1; |
ram_r_en <= 1'b1; |
end |
|
end |
1237,51 → 1321,74
`ifdef ASYNC_RES |
always @(posedge clk or negedge res_n) begin `else |
always @(posedge clk) begin `endif |
|
`ifdef RESET_ALL |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2crc_flit[i_f] <= {128{1'b0}}; |
end |
`endif |
begin |
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2crc_flit[i_f] <= (data2rrp_stage_flit_is_valid[i_f] || !init_state[1]) ? data2rrp_stage_flit[i_f] : {128{1'b0}}; |
|
//Add the RRP |
if(data2rrp_stage_flit_is_tail[i_f] || (data2rrp_stage_flit_is_hdr[i_f] && is_req_flow(data2rrp_stage_flit[i_f])))begin |
data2crc_flit[i_f][64+7:64] <= rx_hmc_frp; |
end |
|
//Increment the FRP by 1, It points to the next possible FLIT position -> retry will start there |
if(data2rrp_stage_flit_is_tail[i_f])begin |
data2crc_flit[i_f][64+15:64+8] <= data2rrp_stage_flit[i_f][64+15:64+8] + 1; |
end |
|
end |
`ifdef SIMULATION |
if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !data2rrp_stage_flit_is_valid[0])begin `else |
if(!data2rrp_stage_flit_is_valid[0] && send_prets)begin `endif |
data2crc_flit[0][63:0] <= pret_hdr; |
data2crc_flit[0][64+7:64] <= rx_hmc_frp; |
end |
end |
|
if(!res_n) begin |
//----Reset control signals |
last_transmitted_rx_hmc_frp <= {HMC_PTR_SIZE{1'b0}}; |
`ifdef SIMULATION |
//----Reset control signals |
last_transmitted_rx_hmc_frp <= {8{1'b0}}; |
`else |
send_prets <= 1'b0; |
`endif |
|
//----Data |
data2crc_flit_is_hdr <= {FPW{1'b0}}; |
data2crc_flit_is_tail <= {FPW{1'b0}}; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
data2crc_flit[i_f] <= {128{1'b0}}; |
end |
|
end else begin |
|
//Propagate signals |
data2crc_flit_is_hdr <= data2rrp_stage_flit_is_hdr; |
data2crc_flit_is_tail <= data2rrp_stage_flit_is_tail; |
data2crc_flit_is_tail <= data2rrp_stage_flit_is_tail | ((data2rrp_stage_flit_is_hdr[FPW-1] && cmd(data2rrp_stage_flit[FPW-1])==CMD_IRTRY) ? {FPW{1'b1}} : {FPW{1'b0}}) ; |
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin |
|
data2crc_flit[i_f] <= data2rrp_stage_flit[i_f]; |
|
//Add the RRP |
if(data2rrp_stage_flit_is_tail[i_f])begin |
data2crc_flit[i_f][64+7:64] <= rx_hmc_frp; |
`ifdef SIMULATION |
//If there is a tail, remember the last transmitted RRP. Otherwise generate PRET if there is a new RRP |
if(|data2rrp_stage_flit_is_tail)begin |
last_transmitted_rx_hmc_frp <= rx_hmc_frp; |
end |
if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !data2rrp_stage_flit_is_valid[0])begin |
data2crc_flit_is_hdr[0] <= 1'b1; |
data2crc_flit_is_tail[0] <= 1'b1; |
last_transmitted_rx_hmc_frp <= rx_hmc_frp; |
end |
`else |
|
//Increment the FRP by 1, It points to the next possible FLIT position -> retry will start there |
if(data2rrp_stage_flit_is_tail[i_f] && !data2rrp_stage_is_flow)begin |
data2crc_flit[i_f][64+15:64+8] <= data2rrp_stage_flit[i_f][64+15:64+8] + 1; |
end |
if(|data2crc_flit_is_hdr) send_prets <= 1'b1; |
if(rf_hmc_sleep_requested || rf_warm_reset) send_prets <= 1'b0; |
|
if(!data2rrp_stage_flit_is_valid[0] && send_prets)begin |
data2crc_flit_is_hdr[0] <= 1'b1; |
data2crc_flit_is_tail[0] <= 1'b1; |
end |
`endif |
|
end |
|
//If there is a tail, remember the last transmitted RRP. Otherwise generate PRET if there is a new RRP |
if(|data2rrp_stage_flit_is_tail)begin |
last_transmitted_rx_hmc_frp <= rx_hmc_frp; |
end else if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !(|data2rrp_stage_flit_is_valid))begin //else send a PRET |
data2crc_flit_is_hdr[0] <= 1'b1; |
data2crc_flit_is_tail[0] <= 1'b1; |
data2crc_flit[0][63:0] <= pret_hdr; |
data2crc_flit[0][64+7:64] <= rx_hmc_frp; |
last_transmitted_rx_hmc_frp <= rx_hmc_frp; |
end |
|
end |
end |
|
1295,15 → 1402,15
generate |
for(f=0;f<FPW;f=f+1)begin : retry_buffer_gen |
openhmc_ram #( |
.DATASIZE(128+3), //FLIT + flow/valid/hdr/tail indicator |
.DATASIZE(128+3), //FLIT + tail/hdr/valid indicator |
.ADDRSIZE(RAM_ADDR_SIZE) |
) |
retry_buffer_per_lane_I |
( |
.clk(clk), |
.wen(ram_w_en), |
.wen(ram_w_en[f]), |
.wdata(ram_w_data[f]), |
.waddr(ram_w_addr), |
.waddr(tx_frp_adr[f]), |
.ren(ram_r_en), |
.raddr(ram_r_addr_temp), |
.rdata(ram_r_data[f]) |
/trunk/openHMC/LICENSE
1,166 → 1,166
GNU LESSER GENERAL PUBLIC LICENSE |
Version 3, 29 June 2007 |
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
|
|
This version of the GNU Lesser General Public License incorporates |
the terms and conditions of version 3 of the GNU General Public |
License, supplemented by the additional permissions listed below. |
|
0. Additional Definitions. |
|
As used herein, "this License" refers to version 3 of the GNU Lesser |
General Public License, and the "GNU GPL" refers to version 3 of the GNU |
General Public License. |
|
"The Library" refers to a covered work governed by this License, |
other than an Application or a Combined Work as defined below. |
|
An "Application" is any work that makes use of an interface provided |
by the Library, but which is not otherwise based on the Library. |
Defining a subclass of a class defined by the Library is deemed a mode |
of using an interface provided by the Library. |
|
A "Combined Work" is a work produced by combining or linking an |
Application with the Library. The particular version of the Library |
with which the Combined Work was made is also called the "Linked |
Version". |
|
The "Minimal Corresponding Source" for a Combined Work means the |
Corresponding Source for the Combined Work, excluding any source code |
for portions of the Combined Work that, considered in isolation, are |
based on the Application, and not on the Linked Version. |
|
The "Corresponding Application Code" for a Combined Work means the |
object code and/or source code for the Application, including any data |
and utility programs needed for reproducing the Combined Work from the |
Application, but excluding the System Libraries of the Combined Work. |
|
1. Exception to Section 3 of the GNU GPL. |
|
You may convey a covered work under sections 3 and 4 of this License |
without being bound by section 3 of the GNU GPL. |
|
2. Conveying Modified Versions. |
|
If you modify a copy of the Library, and, in your modifications, a |
facility refers to a function or data to be supplied by an Application |
that uses the facility (other than as an argument passed when the |
facility is invoked), then you may convey a copy of the modified |
version: |
|
a) under this License, provided that you make a good faith effort to |
ensure that, in the event an Application does not supply the |
function or data, the facility still operates, and performs |
whatever part of its purpose remains meaningful, or |
|
b) under the GNU GPL, with none of the additional permissions of |
this License applicable to that copy. |
|
3. Object Code Incorporating Material from Library Header Files. |
|
The object code form of an Application may incorporate material from |
a header file that is part of the Library. You may convey such object |
code under terms of your choice, provided that, if the incorporated |
material is not limited to numerical parameters, data structure |
layouts and accessors, or small macros, inline functions and templates |
(ten or fewer lines in length), you do both of the following: |
|
a) Give prominent notice with each copy of the object code that the |
Library is used in it and that the Library and its use are |
covered by this License. |
|
b) Accompany the object code with a copy of the GNU GPL and this license |
document. |
|
4. Combined Works. |
|
You may convey a Combined Work under terms of your choice that, |
taken together, effectively do not restrict modification of the |
portions of the Library contained in the Combined Work and reverse |
engineering for debugging such modifications, if you also do each of |
the following: |
|
a) Give prominent notice with each copy of the Combined Work that |
the Library is used in it and that the Library and its use are |
covered by this License. |
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license |
document. |
|
c) For a Combined Work that displays copyright notices during |
execution, include the copyright notice for the Library among |
these notices, as well as a reference directing the user to the |
copies of the GNU GPL and this license document. |
|
d) Do one of the following: |
|
0) Convey the Minimal Corresponding Source under the terms of this |
License, and the Corresponding Application Code in a form |
suitable for, and under terms that permit, the user to |
recombine or relink the Application with a modified version of |
the Linked Version to produce a modified Combined Work, in the |
manner specified by section 6 of the GNU GPL for conveying |
Corresponding Source. |
|
1) Use a suitable shared library mechanism for linking with the |
Library. A suitable mechanism is one that (a) uses at run time |
a copy of the Library already present on the user's computer |
system, and (b) will operate properly with a modified version |
of the Library that is interface-compatible with the Linked |
Version. |
|
e) Provide Installation Information, but only if you would otherwise |
be required to provide such information under section 6 of the |
GNU GPL, and only to the extent that such information is |
necessary to install and execute a modified version of the |
Combined Work produced by recombining or relinking the |
Application with a modified version of the Linked Version. (If |
you use option 4d0, the Installation Information must accompany |
the Minimal Corresponding Source and Corresponding Application |
Code. If you use option 4d1, you must provide the Installation |
Information in the manner specified by section 6 of the GNU GPL |
for conveying Corresponding Source.) |
|
5. Combined Libraries. |
|
You may place library facilities that are a work based on the |
Library side by side in a single library together with other library |
facilities that are not Applications and are not covered by this |
License, and convey such a combined library under terms of your |
choice, if you do both of the following: |
|
a) Accompany the combined library with a copy of the same work based |
on the Library, uncombined with any other library facilities, |
conveyed under the terms of this License. |
|
b) Give prominent notice with the combined library that part of it |
is a work based on the Library, and explaining where to find the |
accompanying uncombined form of the same work. |
|
6. Revised Versions of the GNU Lesser General Public License. |
|
The Free Software Foundation may publish revised and/or new versions |
of the GNU Lesser General Public License from time to time. Such new |
versions will be similar in spirit to the present version, but may |
differ in detail to address new problems or concerns. |
|
Each version is given a distinguishing version number. If the |
Library as you received it specifies that a certain numbered version |
of the GNU Lesser General Public License "or any later version" |
applies to it, you have the option of following the terms and |
conditions either of that published version or of any later version |
published by the Free Software Foundation. If the Library as you |
received it does not specify a version number of the GNU Lesser |
General Public License, you may choose any version of the GNU Lesser |
General Public License ever published by the Free Software Foundation. |
|
If the Library as you received it specifies that a proxy can decide |
whether future versions of the GNU Lesser General Public License shall |
apply, that proxy's public statement of acceptance of any version is |
permanent authorization for you to choose that version for the |
Library. |
|
GNU LESSER GENERAL PUBLIC LICENSE |
Version 3, 29 June 2007 |
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
|
|
This version of the GNU Lesser General Public License incorporates |
the terms and conditions of version 3 of the GNU General Public |
License, supplemented by the additional permissions listed below. |
|
0. Additional Definitions. |
|
As used herein, "this License" refers to version 3 of the GNU Lesser |
General Public License, and the "GNU GPL" refers to version 3 of the GNU |
General Public License. |
|
"The Library" refers to a covered work governed by this License, |
other than an Application or a Combined Work as defined below. |
|
An "Application" is any work that makes use of an interface provided |
by the Library, but which is not otherwise based on the Library. |
Defining a subclass of a class defined by the Library is deemed a mode |
of using an interface provided by the Library. |
|
A "Combined Work" is a work produced by combining or linking an |
Application with the Library. The particular version of the Library |
with which the Combined Work was made is also called the "Linked |
Version". |
|
The "Minimal Corresponding Source" for a Combined Work means the |
Corresponding Source for the Combined Work, excluding any source code |
for portions of the Combined Work that, considered in isolation, are |
based on the Application, and not on the Linked Version. |
|
The "Corresponding Application Code" for a Combined Work means the |
object code and/or source code for the Application, including any data |
and utility programs needed for reproducing the Combined Work from the |
Application, but excluding the System Libraries of the Combined Work. |
|
1. Exception to Section 3 of the GNU GPL. |
|
You may convey a covered work under sections 3 and 4 of this License |
without being bound by section 3 of the GNU GPL. |
|
2. Conveying Modified Versions. |
|
If you modify a copy of the Library, and, in your modifications, a |
facility refers to a function or data to be supplied by an Application |
that uses the facility (other than as an argument passed when the |
facility is invoked), then you may convey a copy of the modified |
version: |
|
a) under this License, provided that you make a good faith effort to |
ensure that, in the event an Application does not supply the |
function or data, the facility still operates, and performs |
whatever part of its purpose remains meaningful, or |
|
b) under the GNU GPL, with none of the additional permissions of |
this License applicable to that copy. |
|
3. Object Code Incorporating Material from Library Header Files. |
|
The object code form of an Application may incorporate material from |
a header file that is part of the Library. You may convey such object |
code under terms of your choice, provided that, if the incorporated |
material is not limited to numerical parameters, data structure |
layouts and accessors, or small macros, inline functions and templates |
(ten or fewer lines in length), you do both of the following: |
|
a) Give prominent notice with each copy of the object code that the |
Library is used in it and that the Library and its use are |
covered by this License. |
|
b) Accompany the object code with a copy of the GNU GPL and this license |
document. |
|
4. Combined Works. |
|
You may convey a Combined Work under terms of your choice that, |
taken together, effectively do not restrict modification of the |
portions of the Library contained in the Combined Work and reverse |
engineering for debugging such modifications, if you also do each of |
the following: |
|
a) Give prominent notice with each copy of the Combined Work that |
the Library is used in it and that the Library and its use are |
covered by this License. |
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license |
document. |
|
c) For a Combined Work that displays copyright notices during |
execution, include the copyright notice for the Library among |
these notices, as well as a reference directing the user to the |
copies of the GNU GPL and this license document. |
|
d) Do one of the following: |
|
0) Convey the Minimal Corresponding Source under the terms of this |
License, and the Corresponding Application Code in a form |
suitable for, and under terms that permit, the user to |
recombine or relink the Application with a modified version of |
the Linked Version to produce a modified Combined Work, in the |
manner specified by section 6 of the GNU GPL for conveying |
Corresponding Source. |
|
1) Use a suitable shared library mechanism for linking with the |
Library. A suitable mechanism is one that (a) uses at run time |
a copy of the Library already present on the user's computer |
system, and (b) will operate properly with a modified version |
of the Library that is interface-compatible with the Linked |
Version. |
|
e) Provide Installation Information, but only if you would otherwise |
be required to provide such information under section 6 of the |
GNU GPL, and only to the extent that such information is |
necessary to install and execute a modified version of the |
Combined Work produced by recombining or relinking the |
Application with a modified version of the Linked Version. (If |
you use option 4d0, the Installation Information must accompany |
the Minimal Corresponding Source and Corresponding Application |
Code. If you use option 4d1, you must provide the Installation |
Information in the manner specified by section 6 of the GNU GPL |
for conveying Corresponding Source.) |
|
5. Combined Libraries. |
|
You may place library facilities that are a work based on the |
Library side by side in a single library together with other library |
facilities that are not Applications and are not covered by this |
License, and convey such a combined library under terms of your |
choice, if you do both of the following: |
|
a) Accompany the combined library with a copy of the same work based |
on the Library, uncombined with any other library facilities, |
conveyed under the terms of this License. |
|
b) Give prominent notice with the combined library that part of it |
is a work based on the Library, and explaining where to find the |
accompanying uncombined form of the same work. |
|
6. Revised Versions of the GNU Lesser General Public License. |
|
The Free Software Foundation may publish revised and/or new versions |
of the GNU Lesser General Public License from time to time. Such new |
versions will be similar in spirit to the present version, but may |
differ in detail to address new problems or concerns. |
|
Each version is given a distinguishing version number. If the |
Library as you received it specifies that a certain numbered version |
of the GNU Lesser General Public License "or any later version" |
applies to it, you have the option of following the terms and |
conditions either of that published version or of any later version |
published by the Free Software Foundation. If the Library as you |
received it does not specify a version number of the GNU Lesser |
General Public License, you may choose any version of the GNU Lesser |
General Public License ever published by the Free Software Foundation. |
|
If the Library as you received it specifies that a proxy can decide |
whether future versions of the GNU Lesser General Public License shall |
apply, that proxy's public statement of acceptance of any version is |
permanent authorization for you to choose that version for the |
Library. |
|
/trunk/openHMC/doc/openHMC_documentation_rev1_4.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
trunk/openHMC/doc/openHMC_documentation_rev1_4.pdf
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/openHMC/doc/openHMC_documentation_1_5.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/openHMC/doc/openHMC_documentation_1_5.pdf
===================================================================
--- trunk/openHMC/doc/openHMC_documentation_1_5.pdf (nonexistent)
+++ trunk/openHMC/doc/openHMC_documentation_1_5.pdf (revision 15)
trunk/openHMC/doc/openHMC_documentation_1_5.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: trunk/openHMC/sim/tb/bfm/build/compile_tb_openhmc.f
===================================================================
--- trunk/openHMC/sim/tb/bfm/build/compile_tb_openhmc.f (revision 14)
+++ trunk/openHMC/sim/tb/bfm/build/compile_tb_openhmc.f (nonexistent)
@@ -1,82 +0,0 @@
-#
-# .--------------. .----------------. .------------.
-# | .------------. | .--------------. | .----------. |
-# | | ____ ____ | | | ____ ____ | | | ______ | |
-# | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
-# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
-# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
-# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
-# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
-# | | | | | | | | | | | |
-# |_| | '------------' | '--------------' | '----------' |
-# '--------------' '----------------' '------------'
-#
-# openHMC - An Open Source Hybrid Memory Cube Controller
-# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
-# www.ziti.uni-heidelberg.de
-# B6, 26
-# 68159 Mannheim
-# Germany
-#
-# Contact: openhmc@ziti.uni-heidelberg.de
-# http://ra.ziti.uni-heidelberg.de/openhmc
-#
-# This source file is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This source file is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this source file. If not, see .
-#
-#
-
-#Leave untouched
-+define+HMC_REQUESTER_IS_ACTIVE=0
-+define+HMC_RESPONDER_IS_ACTIVE=0
-+define+CAG_ASSERTIONS
-
-+define+RFS_DATA_WIDTH=64
-+define+RFS_HMC_CONTROLLER_RF_AWIDTH=4
-+define+RFS_HMC_CONTROLLER_RF_RWIDTH=64
-+define+RFS_HMC_CONTROLLER_RF_WWIDTH=64
-
-+incdir+${OPENHMC_SIM}/tb/bfm/src
-+incdir+${OPENHMC_SIM}/tb/bfm/testlib
-+incdir+${OPENHMC_SIM}/UVC/axi4_stream/sv
-+incdir+${OPENHMC_SIM}/UVC/cag_rgm/sv
-+incdir+${OPENHMC_SIM}/UVC/hmc_module/sv
-+incdir+${OPENHMC_SIM}/UVC/hmc_base_types/sv
-
-#Micron BFM model
--f ${OPENHMC_SIM}/bfm/hmc_bfm.f
-
--64bit
--access +rwc
-
--uvm
-
--sv
--q
-
--ncerror CUVWSI
--ncerror CUVWSP
--ncerror CUVMPW
--ncerror CUVUKP
--ncerror RTSDAD
--ncerror OBINRG
--ncerror BNDMEM
--ncerror FUNTSK
--ncerror CSINFI
--ncerror RECOME
--nowarn CUVIHR
-+UVM_NO_RELNOTES
-
-### DUT-specific files
-
--top tb_top
Index: trunk/openHMC/sim/tb/bfm/build/compile_hw_openhmc.f
===================================================================
--- trunk/openHMC/sim/tb/bfm/build/compile_hw_openhmc.f (revision 14)
+++ trunk/openHMC/sim/tb/bfm/build/compile_hw_openhmc.f (nonexistent)
@@ -1,44 +0,0 @@
-#
-# .--------------. .----------------. .------------.
-# | .------------. | .--------------. | .----------. |
-# | | ____ ____ | | | ____ ____ | | | ______ | |
-# | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
-# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
-# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
-# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
-# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
-# | | | | | | | | | | | |
-# |_| | '------------' | '--------------' | '----------' |
-# '--------------' '----------------' '------------'
-#
-# openHMC - An Open Source Hybrid Memory Cube Controller
-# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
-# www.ziti.uni-heidelberg.de
-# B6, 26
-# 68159 Mannheim
-# Germany
-#
-# Contact: openhmc@ziti.uni-heidelberg.de
-# http://ra.ziti.uni-heidelberg.de/openhmc
-#
-# This source file is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This source file is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this source file. If not, see .
-#
-#
-
-#openHMC controller
--f ${OPENHMC_PATH}/rtl/hmc_controller/openhmc_top.f
-+incdir+${OPENHMC_PATH}/rtl/include/
-
-#Include Register File model
-+incdir+${OPENHMC_SIM}/tb/bfm/src/rgm/openhmc/
\ No newline at end of file
Index: trunk/openHMC/sim/tb/bfm/build/compile_ius_openhmc_behavioral_bfm.f
===================================================================
--- trunk/openHMC/sim/tb/bfm/build/compile_ius_openhmc_behavioral_bfm.f (revision 14)
+++ trunk/openHMC/sim/tb/bfm/build/compile_ius_openhmc_behavioral_bfm.f (revision 15)
@@ -38,10 +38,16 @@
###Include Sources
#Behavioral serializer and routing models
--f ${OPENHMC_SIM}/tb/bfm/src/serdes/behavioral/serdes_behavioral.f
+-f ${OPENHMC_SIM}/tb/common/src/serdes/behavioral/serdes_behavioral.f
#Source top TB, HW, and DUT
--f ${OPENHMC_SIM}/tb/bfm/build/compile_tb_openhmc.f
--f ${OPENHMC_SIM}/tb/bfm/build/compile_hw_openhmc.f
+#Micron BFM model
+-f ${OPENHMC_SIM}/bfm/hmc_bfm.f
++incdir+${OPENHMC_SIM}/bfm
+-f ${OPENHMC_SIM}/tb/common/build/compile_tb_openhmc.f
+-f ${OPENHMC_SIM}/tb/common/build/compile_hw_openhmc.f
++incdir+${OPENHMC_SIM}/tb/bfm/testlib
++incdir+${OPENHMC_SIM}/tb/bfm/src
${OPENHMC_SIM}/tb/bfm/src/tb_top_bfm.sv
${OPENHMC_SIM}/tb/bfm/src/targets/dut_openhmc_behavioral_bfm.sv
+
/trunk/openHMC/sim/tb/bfm/build/ncsim.tcl
4,8 → 4,18
probe -create tb_top.dut_I.openhmc_instance.rx_link_I -all -database waves -memories |
probe -create tb_top.dut_I.openhmc_instance.tx_link_I -all -database waves -memories |
|
probe -create tb_top.axi4_hmc_rsp_if -all -database waves |
probe -create tb_top.axi4_hmc_req_if -all -database waves |
probe -create tb_top.hmc_if -all -database waves |
|
set assert_output_stop_level failed |
set assert_report_incompletes 0 |
|
#-- enable IDA probes |
#ida_database -open -name=ida.db -compress |
#ida_probe -log=on |
#ida_probe -wave=on |
#ida_probe -sv_flow=on |
|
run |
|
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_complex_pkt_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_hdelay_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_seq_lib.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_base_pkt_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_big_pkts_hdelay_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_zdelay_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_small_pkts_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_single_pkt_cycle_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_small_pkts_hdelay_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/seq_lib/hmc_small_pkts_zdelay_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/init_test/init_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/high_delay_pkt_test/high_delay_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/high_delay_pkt_test/high_delay_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/posted_pkt_test/posted_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/posted_pkt_test/posted_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_zdelay_test/big_pkt_zdelay_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_zdelay_test/big_pkt_zdelay_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/non_posted_pkt_test/non_posted_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/non_posted_pkt_test/non_posted_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_hdelay_test/small_pkt_hdelay_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_hdelay_test/small_pkt_hdelay_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_test/big_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_test/big_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/simple_test/simple_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_zdelay_test/small_pkt_zdelay_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_zdelay_test/small_pkt_zdelay_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/sleep_mode/sleep_mode.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_hdelay_test/big_pkt_hdelay_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/big_pkt_hdelay_test/big_pkt_hdelay_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/atomic_pkt_test/atomic_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/atomic_pkt_test/atomic_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/test_lib.sv
File deleted
/trunk/openHMC/sim/tb/bfm/testlib/zero_delay_pkt_test/zero_delay_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/zero_delay_pkt_test/zero_delay_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/hmc_check_seq.sv
File deleted
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_test/small_pkt_test.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/small_pkt_test/small_pkt_test_seq.sv
File deleted
\ No newline at end of file
/trunk/openHMC/sim/tb/bfm/testlib/bfm_init_seq.sv
File deleted
/trunk/openHMC/sim/tb/bfm/testlib/hmc_init_seq.sv
File deleted
/trunk/openHMC/sim/tb/bfm/testlib/hmc_base_test.sv
62,7 → 62,8
//-- AXI4 request config |
axi4_req_config = axi4_stream_config::type_id::create("axi4_req_config", this); |
axi4_req_config.master_active = UVM_ACTIVE; |
axi4_req_config.slave_active = UVM_PASSIVE; |
axi4_req_config.slave_active = UVM_PASSIVE; |
axi4_req_config.open_rsp_mode = UVM_PASSIVE; |
|
uvm_report_info(get_type_name(), $psprintf("Setting the axi4_req config:\n"), UVM_LOW); |
uvm_config_db#(axi4_stream_config)::set(this, "hmc_tb0", "axi4_req_config", axi4_req_config); |
71,6 → 72,7
axi4_rsp_config = axi4_stream_config::type_id::create("axi4_rsp_config", this); |
axi4_rsp_config.master_active = UVM_PASSIVE; |
axi4_rsp_config.slave_active = UVM_ACTIVE; |
axi4_rsp_config.open_rsp_mode = `OPEN_RSP_MODE==1 ? UVM_ACTIVE : UVM_PASSIVE; |
|
uvm_report_info(get_type_name(), $psprintf("Setting the axi4_rsp config:\n"), UVM_LOW); |
uvm_config_db#(axi4_stream_config)::set(this, "hmc_tb0", "axi4_rsp_config", axi4_rsp_config); |
77,6 → 79,7
|
//-- HMC link config |
link_cfg = hmc_link_config::type_id::create("link_cfg",this); |
link_cfg.cfg_rsp_open_loop = `OPEN_RSP_MODE==1 ? UVM_ACTIVE : UVM_PASSIVE; |
void'(link_cfg.randomize()); |
|
uvm_config_db#(hmc_link_config)::set(this, "hmc_tb0", "link_cfg", link_cfg); |
104,10 → 107,6
phase.phase_done.set_drain_time(this, 10us); |
endtask : run_phase |
|
//function void report_phase(uvm_phase phase); |
// report_summarize(); |
//endfunction : report_phase |
|
endclass : hmc_base_test |
|
|
118,7 → 117,7
endfunction : new |
|
`uvm_object_utils(hmc_base_seq) |
`uvm_declare_p_sequencer(hmc_vseqr) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task pre_body(); |
if(starting_phase != null) |
/trunk/openHMC/sim/tb/bfm/testlib/hmc_model_init_seq.sv
0,0 → 1,135
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef BFM_INIT_SEQ |
`define BFM_INIT_SEQ |
|
class hmc_model_init_seq extends hmc_base_seq; |
|
reg_openhmc_rf_status_general_c status; |
reg_openhmc_rf_control_c control; |
reg_openhmc_rf_sent_np_c sent_np; |
reg_openhmc_rf_rcvd_rsp_c rcvd_rsp; |
|
function new(string name="hmc_model_init_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(hmc_model_init_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
task body(); |
|
// init register |
//initiate all the registers (used for sleep mode) |
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
|
$cast(control,p_sequencer.rf_seqr_hmc.get_by_name("control")); |
control.set_check_on_read(1'b0); |
|
$cast(sent_np,p_sequencer.rf_seqr_hmc.get_by_name("sent_np")); |
sent_np.set_check_on_read(1'b0); |
|
$cast(rcvd_rsp,p_sequencer.rf_seqr_hmc.get_by_name("rcvd_rsp")); |
rcvd_rsp.set_check_on_read(1'b0); |
|
|
`uvm_info(get_type_name(), $psprintf("Configure BFM"), UVM_NONE) |
`uvm_info(get_type_name(), $psprintf("HMC_Token Count is: %d", p_sequencer.link_cfg.hmc_tokens), UVM_NONE) |
p_sequencer.hmc_link_cfg.cfg_cid = p_sequencer.link_cfg.cube_id; |
p_sequencer.hmc_link_cfg.cfg_lane_auto_correct = p_sequencer.link_cfg.cfg_lane_auto_correct; |
p_sequencer.hmc_link_cfg.cfg_rsp_open_loop = p_sequencer.link_cfg.cfg_rsp_open_loop; |
|
// These are set to match the design |
p_sequencer.hmc_link_cfg.cfg_rx_clk_ratio = p_sequencer.link_cfg.cfg_rx_clk_ratio; |
p_sequencer.hmc_link_cfg.cfg_half_link_mode_rx = p_sequencer.link_cfg.cfg_half_link_mode_rx; |
p_sequencer.hmc_link_cfg.cfg_tx_lane_reverse = p_sequencer.link_cfg.cfg_tx_lane_reverse; |
p_sequencer.hmc_link_cfg.cfg_tx_lane_delay = p_sequencer.link_cfg.cfg_tx_lane_delay; |
|
p_sequencer.hmc_link_cfg.cfg_hsstx_inv = p_sequencer.link_cfg.cfg_hsstx_inv; |
|
|
p_sequencer.hmc_link_cfg.cfg_tx_clk_ratio = p_sequencer.link_cfg.cfg_tx_clk_ratio; |
p_sequencer.hmc_link_cfg.cfg_half_link_mode_tx = p_sequencer.link_cfg.cfg_half_link_mode_tx; |
|
p_sequencer.hmc_link_cfg.cfg_descram_enb = p_sequencer.link_cfg.cfg_scram_enb; |
p_sequencer.hmc_link_cfg.cfg_scram_enb = p_sequencer.link_cfg.cfg_scram_enb; |
p_sequencer.hmc_link_cfg.cfg_tokens = p_sequencer.link_cfg.hmc_tokens; |
p_sequencer.hmc_link_cfg.cfg_tokens_expected = p_sequencer.link_cfg.rx_tokens; |
|
p_sequencer.hmc_link_cfg.cfg_init_retry_rxcnt = p_sequencer.link_cfg.cfg_init_retry_rxcnt; |
p_sequencer.hmc_link_cfg.cfg_init_retry_txcnt = p_sequencer.link_cfg.cfg_init_retry_txcnt; |
|
//***Enable Errors - Dont touch |
p_sequencer.hmc_link_cfg.cfg_rsp_dln = p_sequencer.link_cfg.cfg_rsp_dln; |
p_sequencer.hmc_link_cfg.cfg_rsp_lng = p_sequencer.link_cfg.cfg_rsp_lng; |
p_sequencer.hmc_link_cfg.cfg_rsp_crc = p_sequencer.link_cfg.cfg_rsp_crc; |
p_sequencer.hmc_link_cfg.cfg_rsp_seq = p_sequencer.link_cfg.cfg_rsp_seq; |
p_sequencer.hmc_link_cfg.cfg_rsp_poison = p_sequencer.link_cfg.cfg_rsp_poison; |
|
p_sequencer.hmc_link_cfg.cfg_req_dln = p_sequencer.link_cfg.cfg_req_dln; |
p_sequencer.hmc_link_cfg.cfg_req_lng = p_sequencer.link_cfg.cfg_req_lng; |
p_sequencer.hmc_link_cfg.cfg_req_crc = p_sequencer.link_cfg.cfg_req_crc; |
p_sequencer.hmc_link_cfg.cfg_req_seq = p_sequencer.link_cfg.cfg_req_seq; |
|
//Reduce timings for simulation |
p_sequencer.hmc_link_cfg.cfg_tsref = p_sequencer.link_cfg.cfg_tsref; |
p_sequencer.hmc_link_cfg.cfg_top = p_sequencer.link_cfg.cfg_top; |
|
p_sequencer.hmc_link_cfg.cfg_retry_timeout = p_sequencer.link_cfg.cfg_retry_timeout; |
p_sequencer.hmc_link_cfg.cfg_retry_limit = p_sequencer.link_cfg.cfg_retry_limit; //8 |
|
//Enable retry |
p_sequencer.hmc_link_cfg.cfg_retry_enb = p_sequencer.link_cfg.cfg_retry_enb; |
|
if(p_sequencer.hmc_link_cfg.cfg_scram_enb) |
p_sequencer.hmc_link_cfg.cfg_tx_rl_lim = p_sequencer.link_cfg.cfg_tx_rl_lim; |
|
p_sequencer.hmc_link_cfg.display(); //uncomment for full link configuration output |
|
tb_top.dut_I.hmc_bfm0.set_config(p_sequencer.hmc_link_cfg,0); |
`uvm_info(get_type_name(), $psprintf("HMC BFM CONFIGURATION IS COMPLETE"), UVM_NONE) |
|
|
endtask : body |
|
endclass : hmc_model_init_seq |
|
`endif // HMC_INIT_SEQ |
/trunk/openHMC/sim/tb/bfm/testlib/openhmc_init_seq.sv
0,0 → 1,140
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef HMC_INIT_SEQ |
`define HMC_INIT_SEQ |
|
class openhmc_init_seq extends hmc_base_seq; |
|
function new(string name="openhmc_init_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(openhmc_init_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
bit phy_tx_ready = 1'b0; |
bit phy_rx_ready = 1'b0; |
bit link_up = 1'b0; |
int timeout = 0; |
|
task body(); |
|
//------------------------------------------------------- configure the openHMC controller |
reg_openhmc_rf_control_c control; |
reg_openhmc_rf_status_general_c status; |
reg_openhmc_rf_status_init_c status_init; |
reg_openhmc_rf_counter_reset_c cnt_reset; |
|
`uvm_info(get_type_name(), "Running init sequence", UVM_NONE) |
|
$cast(control,p_sequencer.rf_seqr_hmc.get_by_name("control")); |
control.set_check_on_read(1'b0); |
p_sequencer.rf_seqr_hmc.read_reg(control); |
|
control.fields.rx_token_count_ = p_sequencer.link_cfg.rx_tokens; |
control.fields.scrambler_disable_ = ~p_sequencer.link_cfg.cfg_scram_enb; |
control.fields.bit_slip_time_ = p_sequencer.link_cfg.bit_slip_time; |
control.fields.set_hmc_sleep_ = 0; |
control.fields.run_length_enable_ = ~p_sequencer.link_cfg.cfg_scram_enb; |
control.fields.irtry_to_send_ = p_sequencer.link_cfg.cfg_init_retry_txcnt*4; |
control.fields.irtry_received_threshold_ = p_sequencer.link_cfg.cfg_init_retry_rxcnt; |
|
p_sequencer.rf_seqr_hmc.write_reg(control); |
|
//Dummy Read to status init |
$cast(status_init,p_sequencer.rf_seqr_hmc.get_by_name("status_init")); |
status_init.set_check_on_read(1'b0); |
p_sequencer.rf_seqr_hmc.read_reg(status_init); |
|
//Dummy counter reset |
$cast(cnt_reset,p_sequencer.rf_seqr_hmc.get_by_name("counter_reset")); |
cnt_reset.fields.rreinit_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(cnt_reset); |
|
//-- Wait until the PHY is out of reset |
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
while (phy_tx_ready == 1'b0) |
begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
phy_tx_ready = status.fields.phy_tx_ready_; |
`uvm_info(get_type_name(), "Waiting for the PHY TX to get ready", UVM_NONE) |
end |
`uvm_info(get_type_name(), "Phy TX ready", UVM_NONE) |
|
//------------------------------------------------------- Set Reset and Init Continue |
control.fields.p_rst_n_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
#1us; |
|
control.fields.hmc_init_cont_set_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
`uvm_info(get_type_name(), "Init cont in RF set", UVM_NONE) |
|
//------------------------------------------------------- Wait for the PHY to get ready |
while (phy_rx_ready == 1'b0) |
begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
phy_rx_ready = status.fields.phy_rx_ready_; |
`uvm_info(get_type_name(), "Waiting for PHY RX to get ready", UVM_NONE) |
end |
`uvm_info(get_type_name(), "Phy RX is ready", UVM_NONE) |
|
//-- Poll on link_up to make sure that it comes up. |
while (link_up == 1'b0) |
begin |
if (timeout == 8000) //-- Try Resetting it. |
begin |
`uvm_fatal(get_type_name(), "The link didn't come up...") |
end |
#4ns; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
link_up = status.fields.link_up_; |
timeout = timeout + 1; |
end |
`uvm_info(get_type_name(), "Link is UP !", UVM_NONE) |
|
endtask : body |
|
endclass : openhmc_init_seq |
|
`endif // HMC_INIT_SEQ |
/trunk/openHMC/sim/tb/bfm/src/tag_handler.sv
File deleted
/trunk/openHMC/sim/tb/bfm/src/hmc_req_packet.sv
File deleted
/trunk/openHMC/sim/tb/bfm/src/bfm_2_hmc_monitor.sv
File deleted
/trunk/openHMC/sim/tb/bfm/src/hmc_2_axi4_sequence.sv
File deleted
/trunk/openHMC/sim/tb/bfm/src/hmc_vseqr.sv
File deleted
/trunk/openHMC/sim/tb/bfm/src/hmc_link_config.sv
48,12 → 48,13
|
rand int hmc_tokens; |
rand int rx_tokens; |
rand bit [5:0] bit_slip_time; |
rand bit [2:0] cube_id; |
|
rand bit cfg_tx_lane_reverse; |
rand bit [15:0] cfg_hsstx_inv; |
rand bit cfg_scram_enb; |
rand bit [15:0] cfg_tx_lane_delay[16] = '{16{4'h0}}; |
bit cfg_scram_enb = 1; |
rand bit [15:0] cfg_tx_lane_delay[16]; |
rand bit [ 3:0] cfg_retry_limit = 3; //-- LINKRETRY - infinite retry when cfg_retry_limit[3] == 1 |
rand bit [ 2:0] cfg_retry_timeout = 5; |
|
60,14 → 61,19
rand bit cfg_check_pkt = 1; //-- check for valid packet |
|
bit cfg_lane_auto_correct = 1; |
bit cfg_rsp_open_loop = 0; |
int cfg_rx_clk_ratio = 40; |
bit cfg_half_link_mode_rx = (2**`LOG_NUM_LANES==8); |
uvm_active_passive_enum cfg_rsp_open_loop = UVM_PASSIVE; |
bit cfg_half_link_mode_rx = (`LOG_NUM_LANES==3); |
bit [7:0] cfg_tx_rl_lim = 85; |
int cfg_tx_clk_ratio = 40; |
bit cfg_half_link_mode_tx = (2**`LOG_NUM_LANES==8); |
bit [7:0] cfg_init_retry_rxcnt = 16; |
bit [7:0] cfg_init_retry_txcnt = 6; //-- Actual value in BFM is 4times this value |
`ifdef HMC_12G |
int cfg_rx_clk_ratio = 50; //Set to 50 for 12.5Gbit , 60 for 15Gbit |
int cfg_tx_clk_ratio = 50; //Set to 50 for 12.5Gbit , 60 for 15Gbit |
`else |
int cfg_rx_clk_ratio = 40; //Set to 50 for 12.5Gbit , 60 for 15Gbit |
int cfg_tx_clk_ratio = 40; //Set to 50 for 12.5Gbit , 60 for 15Gbit |
`endif |
bit cfg_half_link_mode_tx = (`LOG_NUM_LANES==3); |
rand bit [7:0] cfg_init_retry_rxcnt; |
rand bit [7:0] cfg_init_retry_txcnt; //-- Actual value in BFM is 4times this value |
realtime cfg_tsref = 1us; |
realtime cfg_top = 1us; |
|
82,9 → 88,26
//-- constrains |
//-- |
|
constraint cfg_init_retry_rxcnt_c { |
cfg_init_retry_rxcnt == 16; |
// cfg_init_retry_rxcnt <= 20; |
} |
|
constraint cfg_init_retry_txcnt_c { |
//Actual Value is constraint*4 |
// cfg_init_retry_txcnt >= 5; |
cfg_init_retry_txcnt == 7; |
} |
|
constraint bit_slip_time_c { |
bit_slip_time >= 32; |
bit_slip_time <= 63; |
} |
|
constraint hmc_tokens_c { |
hmc_tokens >= 25; |
soft hmc_tokens dist{[25:30]:/5, [31:100]:/15, [101:1023]:/80}; |
// soft hmc_tokens dist{[25:30]:/5, [31:100]:/15, [101:1023]:/80}; |
soft hmc_tokens dist{[25:30]:/5, [31:219]:/95}; //Current hardware |
} |
|
constraint cfg_hsstx_inv_c { |
93,7 → 116,8
|
constraint rx_tokens_c { |
rx_tokens >= 9; |
soft rx_tokens dist{[9:30]:/5, [31:100]:/15, [101:1023]:/80}; |
// soft rx_tokens dist{[9:30]:/5, [31:100]:/15, [101:1023]:/80}; //Make sure to increase the input buffer accordingly |
soft rx_tokens dist{[9:30]:/5, [31:255]:/95}; //Safe value for input buffer address size = 8. Leave some FLITs for poisoned packets |
} |
|
constraint cube_id_c { |
113,18 → 137,16
|
|
constraint error_rates_c { |
soft cfg_rsp_dln == 5; |
soft cfg_rsp_lng == 5; |
soft cfg_rsp_crc == 5; |
soft cfg_rsp_seq == 5; |
soft cfg_rsp_poison == 5; |
soft cfg_rsp_dln ==0;//dist{[0:10]}; |
soft cfg_rsp_lng ==0;//dist{[0:10]}; |
soft cfg_rsp_crc ==0;//dist{[0:10]}; |
soft cfg_rsp_seq ==0;//dist{[0:10]}; |
soft cfg_rsp_poison ==0;//dist{[0:10]}; |
soft cfg_req_dln ==0;//dist{[0:10]}; |
soft cfg_req_lng ==0;//dist{[0:10]}; |
soft cfg_req_crc ==0;//dist{[0:10]}; |
soft cfg_req_seq ==0; // Must be zero for BFM 28965 ! |
|
soft cfg_req_dln == 5; |
soft cfg_req_lng == 5; |
soft cfg_req_crc == 5; |
soft cfg_req_seq == 0; // Must be zero for BFM 28965 ! |
|
|
( |
cfg_rsp_dln || |
cfg_rsp_lng || |
161,4 → 183,4
|
endclass : hmc_link_config |
|
`endif // AXI4_STREAM_CONFIG_SV |
`endif // HMC_LINK_CONFIG_SV |
/trunk/openHMC/sim/tb/bfm/src/tb_top_bfm.sv
62,13 → 62,12
|
`include "hmc_packet.sv" |
`include "hmc_req_packet.sv" |
//`include "hmc_req_posted_packet.sv" |
`include "hmc_2_axi4_sequencer.sv" |
`include "hmc_2_axi4_sequence.sv" |
`include "tag_handler.sv" |
|
`include "hmc_link_config.sv" |
`include "hmc_vseqr.sv" |
`include "vseqr.sv" |
|
`include "axi4_stream_hmc_monitor.sv" |
`include "bfm_2_hmc_monitor.sv" |
83,23 → 82,17
axi4_stream_if #( |
.DATA_BYTES(`AXI4BYTES), |
.TUSER_WIDTH(`AXI4BYTES) |
) axi4_hmc_req_if( |
.ACLK(clk_user), |
.ARESET_N(res_n) |
); |
) axi4_hmc_req_if(); |
|
axi4_stream_if #( |
.DATA_BYTES(`AXI4BYTES), |
.TUSER_WIDTH(`AXI4BYTES) |
) axi4_hmc_rsp_if( |
.ACLK(clk_user), |
.ARESET_N(res_n) |
); |
) axi4_hmc_rsp_if(); |
|
cag_rgm_rfs_if #( |
.ADDR_WIDTH(`RFS_HMC_CONTROLLER_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_WWIDTH) |
.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH) |
) rfs_hmc_if(); |
|
dut dut_I ( |
122,9 → 115,6
uvm_config_db#(pkt_analysis_port#())::set(null,"uvm_test_top.hmc_tb0.hmc_module.hmc_req_mon","mb_pkt",dut_I.hmc_bfm0.hmc_flit_top.mb_rsp_pkt[0]); |
uvm_config_db#(pkt_analysis_port#())::set(null,"uvm_test_top.hmc_tb0.hmc_module.hmc_rsp_mon","mb_pkt",dut_I.hmc_bfm0.hmc_flit_top.mb_req_pkt[0]); |
|
//uvm_config_db#(pkt_analysis_port#())::set(null,"uvm_test_top.hmc_tb0.hmc_module.hmc_req_mon","mb_pkt",dut_I.hmc_bfm0.hmc_flit_top.mb_req_pkt_err_cov[0]); |
//uvm_config_db#(pkt_analysis_port#())::set(null,"uvm_test_top.hmc_tb0.hmc_module.hmc_rsp_mon","mb_pkt",dut_I.hmc_bfm0.hmc_flit_top.mb_rsp_pkt_err_cov[0]); |
|
run_test(); |
end |
|
132,7 → 122,7
clk_user <= 1'b1; |
clk_hmc_refclk <= 1'b1; |
res_n <= 1'b0; |
#1000ns |
#500ns; |
@(posedge clk_user) res_n <= 1'b1; |
end |
|
167,7 → 157,7
endcase |
end |
|
//-- 125 MHz |
//-- 125 MHz HMC/Transceiver refclock |
always #4ns clk_hmc_refclk <= ~clk_hmc_refclk; |
|
|
endmodule : tb_top |
/trunk/openHMC/sim/tb/bfm/src/hmc_tb.sv
64,14 → 64,14
hmc_link_config link_cfg; |
|
cag_rgm_rfs_env #( |
.ADDR_WIDTH(`RFS_HMC_CONTROLLER_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_WWIDTH) |
.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH) |
) rfs_hmc_I; |
|
rf_hmc_controller_rf_c rf_model_hmc; |
rf_openhmc_rf_c rf_model_hmc; |
|
hmc_vseqr v_seqr; |
vseqr v_seqr; |
|
int i = 2; |
|
143,10 → 143,10
|
hmc_module = hmc_module_env::type_id::create("hmc_module",this); |
|
rfs_hmc_I = cag_rgm_rfs_env #(.ADDR_WIDTH(`RFS_HMC_CONTROLLER_RF_AWIDTH), .READ_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_RWIDTH),.WRITE_DATA_WIDTH(`RFS_HMC_CONTROLLER_RF_WWIDTH))::type_id::create("rfs_hmc_I", this); |
rf_model_hmc = rf_hmc_controller_rf_c::type_id::create("rf_model_hmc",this); |
rfs_hmc_I = cag_rgm_rfs_env #(.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), .READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH),.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH))::type_id::create("rfs_hmc_I", this); |
rf_model_hmc = rf_openhmc_rf_c::type_id::create("rf_model_hmc",this); |
|
v_seqr = hmc_vseqr::type_id::create("v_seqr", this); |
v_seqr = vseqr::type_id::create("v_seqr", this); |
|
endfunction : build_phase |
|
200,6 → 200,8
v_seqr.rf_seqr_hmc = rfs_hmc_I.sequencer; |
|
|
v_seqr.scb = hmc_module.scb; |
|
endfunction : connect_phase |
|
endclass : hmc_tb |
/trunk/openHMC/sim/tb/bfm/src/vseqr.sv
0,0 → 1,85
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef hmc_VIRTUAL_SEQUENCER_SV |
`define hmc_VIRTUAL_SEQUENCER_SV |
|
class vseqr extends uvm_sequencer; |
|
hmc_link_config link_cfg; |
|
cls_link_cfg hmc_link_cfg; |
|
//-- references to testbench sequencers |
cag_rgm_sequencer rf_seqr_hmc; |
|
hmc_module_scb scb; |
|
hmc_2_axi4_sequencer #(.DATA_BYTES(`AXI4BYTES),.TUSER_WIDTH(`AXI4BYTES)) axi4_req_seqr; |
|
`uvm_component_utils_begin(vseqr) |
`uvm_field_object(link_cfg, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new (string name = "hmc_virtual_sequencer", uvm_component parent); |
super.new(name, parent); |
|
hmc_link_cfg = new(); |
endfunction : new |
|
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if (!uvm_config_db#(hmc_link_config)::get(this, "", "link_cfg", link_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("hmc_link_config not set via config_db")); |
end |
|
|
endfunction : build_phase |
|
|
//function void connect_phase(uvm_phase phase); |
// |
//endfunction : connect_phase |
|
|
endclass : vseqr |
|
`endif // hmc_VIRTUAL_SEQUENCER_SV |
/trunk/openHMC/sim/tb/bfm/src/targets/dut_openhmc_behavioral_bfm.sv
73,7 → 73,9
wire [NUM_LANES-1:0] bit_slip; |
wire [NUM_LANES-1:0] phy_lane_polarity; |
bit P_RST_N; |
wire clk_hmc = clk_user; |
//If transceiver models are used, clk_hmc should be sourced from the transceiver outclock and res_n hmc can be set independently |
wire clk_hmc = clk_user; |
wire res_n_hmc = res_n; |
|
// Wire the HMC BFM model |
wire LxRXPS; // HMC input |
96,8 → 98,14
|
//----------------------------- Attach the Register File System interface |
assign rfs_hmc_if.clk = clk_hmc; |
assign rfs_hmc_if.res_n = res_n; |
assign rfs_hmc_if.res_n = res_n_hmc; |
|
//Assign the AXI4 IF |
assign axi4_req.ACLK = (`OPENHMC_ASYNC_FIFOS==0) ? clk_hmc : clk_user; |
assign axi4_rsp.ACLK = (`OPENHMC_ASYNC_FIFOS==0) ? clk_hmc : clk_user; |
assign axi4_req.ARESET_N = (`OPENHMC_ASYNC_FIFOS==0) ? res_n_hmc : res_n; |
assign axi4_rsp.ARESET_N = (`OPENHMC_ASYNC_FIFOS==0) ? res_n_hmc : res_n; |
|
//----------------------------- Generate Clocks |
bit clk_10G; |
generate |
108,6 → 116,7
endgenerate |
|
//----------------------------- Behavioral SerDes |
bit LxTXPS_synced; |
genvar lane; |
generate |
begin : serializers_gen |
117,6 → 126,7
.DWIDTH(LANE_WIDTH) |
) serializer_I ( |
.clk(clk_hmc), |
.res_n(res_n), |
.fast_clk(clk_10G), |
.data_in(to_serializers[lane*LANE_WIDTH+LANE_WIDTH-1:lane*LANE_WIDTH]), |
.data_out(serial_Txp[lane]) |
125,6 → 135,7
.DWIDTH(LANE_WIDTH) |
) deserializer_I ( |
.clk(clk_hmc), |
.res_n(LxTXPS_synced && res_n), |
.fast_clk(clk_10G), |
.bit_slip(bit_slip[lane]), |
.lane_polarity(phy_lane_polarity[lane]), |
134,7 → 145,7
end |
end |
endgenerate |
|
always @(posedge clk_hmc) LxTXPS_synced <= LxTXPS; |
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
//---------INSTANTIATIONS HERE------------------------------------------------------------------------- |
145,11 → 156,14
.FPW(FPW), |
.LOG_NUM_LANES(LOG_NUM_LANES), |
//Configure the Functionality |
.LOG_MAX_RTC(10), //That is max 1023 Tokens |
.LOG_MAX_RX_TOKENS(10), |
.LOG_MAX_HMC_TOKENS(10), //That is max 1023 Tokens |
.HMC_RX_AC_COUPLED(1), |
.CTRL_LANE_POLARITY(0), |
.CTRL_LANE_POLARITY(1), |
.CTRL_LANE_REVERSAL(1), |
.BITSLIP_SHIFT_RIGHT(1), |
.OPEN_RSP_MODE(`OPEN_RSP_MODE), |
.SYNC_AXI4_IF(`OPENHMC_ASYNC_FIFOS==0), |
//Debug Logic |
.DBG_RX_TOKEN_MON(1) //Required by the test check sequence |
) |
184,15 → 198,17
.phy_data_tx_link2phy(to_serializers), |
.phy_data_rx_phy2link(from_deserializers), |
.phy_bit_slip(bit_slip), |
.phy_ready(res_n), |
.phy_tx_ready(res_n), |
.phy_rx_ready(res_n), |
.phy_lane_polarity(phy_lane_polarity), |
.phy_init_cont_set(), |
|
//---------------------------------- |
//----Connect HMC |
//---------------------------------- |
.P_RST_N(P_RST_N), |
.hmc_LxRXPS(LxRXPS), |
.hmc_LxTXPS(LxTXPS), |
.LXRXPS(LxRXPS), |
.LXTXPS(LxTXPS), |
.FERR_N(FERR_N), |
|
//---------------------------------- |
/trunk/openHMC/sim/tb/run/clean_up.sh
42,4 → 42,7
rm -rf cov_work |
rm -f *.log |
rm -f irun.key |
rm -rf .simvision |
rm -rf .simvision |
rm -rf .rmi_process |
rm -f *.diag |
rm -f *.err |
/trunk/openHMC/sim/tb/run/run_bfm.sh
0,0 → 1,83
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
#!/bin/bash |
|
if [ ! $OPENHMC_SIM ] |
then |
echo "Please export OPENHMC_SIM first" |
exit 1 |
fi |
|
if [ ! $OPENHMC_PATH ] |
then |
echo "Please export OPENHMC_PATH first" |
exit 1 |
fi |
|
export CAG_TB_DIR=${OPENHMC_SIM}/tb/bfm |
export CAG_DUT="openhmc_behavioral_bfm" |
|
#----------------------------------------------------------------- |
|
echo "" |
echo "*" |
echo "* .--------------. .----------------. .------------. " |
echo "* | .------------. | .--------------. | .----------. |" |
echo "* | | ____ ____ | | | ____ ____ | | | ______ | |" |
echo "* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |" |
echo "* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |" |
echo "* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |" |
echo "* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ '.___.'\| |" |
echo "* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | '._____.'| |" |
echo "* | | | | | | | | | | | |" |
echo "* |_| | ------------ | '--------------' | '----------' |" |
echo "* '--------------' '----------------' '------------' " |
echo "*" |
echo "*" |
echo "* *******************************************************" |
echo "* * *" |
echo "* * openHMC Verification Environment *" |
echo "* * *" |
echo "* * using Micron Bus Functional Model *" |
echo "* * *" |
echo "* *******************************************************" |
echo "" |
|
${OPENHMC_SIM}/tb/run/run_files/run.sh $* |
|
/trunk/openHMC/sim/tb/run/run_files/run.sh
39,7 → 39,7
#!/bin/bash |
|
function print_help { |
printf "Usage: %s: [-c] [-d DUT] [-f FPW] [-g] [-l NUM_LANES] [o] [-q] [-p] [-s SEED] [-t TEST_NAME] [-v UVM_VERBOSITY] -?\n" $(basename $0) >&2 |
printf "Usage: %s: [-c] [-d DUT] [-f FPW] [-g] [-l NUM_LANES] [-o] [-q] [-a] [-r] [-s SEED] [-t TEST_NAME] [-v UVM_VERBOSITY] -?\n" $(basename $0) >&2 |
} |
|
#----------------------------------------------------------------- |
54,6 → 54,9
log_num_lanes="3" |
fpw="default" |
log_fpw="2" |
num_axi_bytes="64" |
open_rsp="0" |
async_fifos="0" |
|
do_clean_up= |
tflag="0" |
63,14 → 66,15
use_gui= |
input_file="-input ${CAG_TB_DIR}/build/ncsim.tcl" |
seed="" |
num_axi_bytes="64" |
enable_coverage="" |
|
|
#-- parse options |
while getopts 'cgot:v:d:s:l:f:q?' OPTION |
while getopts 'acgort:v:d:s:l:f:q?' OPTION |
do |
case $OPTION in |
a) async_fifos="1" |
;; |
c) do_clean_up=1 |
;; |
d) export CAG_DUT=${OPTARG} |
82,6 → 86,13
;; |
l) num_lanes="${OPTARG}" |
;; |
o) enable_coverage="-coverage all -covoverwrite" |
;; |
q) input_file="" |
verbosity="UVM_NONE" |
;; |
r) open_rsp="1" |
;; |
s) seed="+svseed+${OPTARG}" |
;; |
t) tflag="1" |
89,11 → 100,6
;; |
v) verbosity="$OPTARG" |
;; |
o) enable_coverage="-coverage all -covoverwrite" |
;; |
q) input_file="" |
verbosity="UVM_NONE" |
;; |
?) print_help |
exit 2 |
;; |
160,6 → 166,18
test_name="simple_test" |
fi |
|
#-- Open Response |
if [ "$open_rsp" == "1" ] |
then |
printf "*** OPEN RESPONSE LOOP MODE ***\n" |
fi |
|
#-- Async FIFOs |
if [ "$open_rsp" == "1" ] |
then |
printf "*** Using Asynchronous FIFOs ***\n" |
fi |
|
#-- select DUT |
if [ "$dflag" == "0" ] |
then |
185,5 → 203,8
-f ${CAG_TB_COMPILE_IUS} \ |
${enable_coverage} \ |
-access +rwc \ |
"-define OPEN_RSP_MODE=$open_rsp" \ |
"-define OPENHMC_ASYNC_FIFOS=$async_fifos" \ |
-timescale 1ns/1ps \ |
${use_gui} "+UVM_TESTNAME=${test_name}" "+UVM_VERBOSITY=${verbosity}" ${seed} \ |
"-define LOG_NUM_LANES=$log_num_lanes -define FPW=$fpw -define LOG_FPW=$log_fpw -define AXI4BYTES=$num_axi_bytes" $* |
/trunk/openHMC/sim/tb/run/run.sh
50,8 → 50,8
exit 1 |
fi |
|
export CAG_TB_DIR=${OPENHMC_SIM}/tb/bfm |
export CAG_DUT="openhmc_behavioral_bfm" |
export CAG_TB_DIR=${OPENHMC_SIM}/tb/uvc |
export CAG_DUT="openhmc_behavioral_uvc" |
|
#----------------------------------------------------------------- |
|
74,8 → 74,8
echo "* * *" |
echo "* * openHMC Verification Environment *" |
echo "* * *" |
echo "* * using CAG HMC Verification Model *" |
echo "* * *" |
echo "* * *" |
echo "* *******************************************************" |
echo "" |
|
/trunk/openHMC/sim/tb/common/build/compile_hw_openhmc.f
0,0 → 1,44
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
#openHMC controller |
-f ${OPENHMC_PATH}/rtl/hmc_controller/openhmc_top.f |
+incdir+${OPENHMC_PATH}/rtl/include/ |
|
#Include Register File model |
+incdir+${OPENHMC_SIM}/tb/common/src/rgm/openhmc/ |
/trunk/openHMC/sim/tb/common/build/compile_tb_openhmc.f
0,0 → 1,87
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
#Leave untouched |
+define+HMC_REQUESTER_IS_ACTIVE=0 |
+define+HMC_RESPONDER_IS_ACTIVE=0 |
+define+CAG_ASSERTIONS |
+define+SIMULATION |
|
+define+RFS_DATA_WIDTH=64 |
+define+RFS_OPENHMC_RF_AWIDTH=4 |
+define+RFS_OPENHMC_RF_RWIDTH=64 |
+define+RFS_OPENHMC_RF_WWIDTH=64 |
|
+incdir+${OPENHMC_SIM}/tb/common/src |
+incdir+${OPENHMC_SIM}/tb/common/testlib |
+incdir+${OPENHMC_SIM}/UVC/axi4_stream/sv |
+incdir+${OPENHMC_SIM}/UVC/cag_rgm/sv |
+incdir+${OPENHMC_SIM}/UVC/hmc_module/sv |
+incdir+${OPENHMC_SIM}/UVC/hmc_base_types/sv |
|
-64bit |
-access +rwc |
|
-linedebug |
-ida |
|
-uvm |
|
|
#-coverage All |
#-covoverwrite |
|
-sv |
-q |
|
-ncerror CUVWSI |
-ncerror CUVWSP |
-ncerror CUVMPW |
-ncerror CUVUKP |
-ncerror RTSDAD |
-ncerror OBINRG |
-ncerror BNDMEM |
-ncerror FUNTSK |
-ncerror CSINFI |
-ncerror RECOME |
-nowarn CUVIHR |
+UVM_NO_RELNOTES |
|
### DUT-specific files |
|
-top tb_top |
/trunk/openHMC/sim/tb/common/testlib/openhmc_check_seq.sv
0,0 → 1,131
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef openhmc_check_seq |
`define openhmc_check_seq |
|
|
class openhmc_check_seq extends hmc_base_seq; |
|
function new(string name="openhmc_check_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(openhmc_check_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
int timer; |
int q_size, q_size_prev; |
int draintime = 200; |
|
task body(); |
reg_openhmc_rf_status_general_c status; |
reg_openhmc_rf_sent_np_c sent_np; |
reg_openhmc_rf_rcvd_rsp_c rcvd_rsp; |
|
`uvm_info(get_type_name(), "Running Check Sequence", UVM_NONE) |
|
timer = 0; |
q_size_prev = 0; |
|
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
|
$cast(sent_np,p_sequencer.rf_seqr_hmc.get_by_name("sent_np")); |
sent_np.set_check_on_read(1'b0); |
|
$cast(rcvd_rsp,p_sequencer.rf_seqr_hmc.get_by_name("rcvd_rsp")); |
rcvd_rsp.set_check_on_read(1'b0); |
|
p_sequencer.rf_seqr_hmc.read_reg(status); |
p_sequencer.rf_seqr_hmc.read_reg(sent_np); |
p_sequencer.rf_seqr_hmc.read_reg(rcvd_rsp); |
|
|
while( |
((p_sequencer.scb.axi4_np_requests.size() ) || |
(status.fields.rx_tokens_remaining_ != ((p_sequencer.link_cfg.cfg_rsp_open_loop==UVM_ACTIVE) ? status.fields.rx_tokens_remaining_ :p_sequencer.link_cfg.rx_tokens)) || |
(status.fields.hmc_tokens_remaining_ != p_sequencer.link_cfg.hmc_tokens) ) |
&& |
(timer < draintime) |
) begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
p_sequencer.rf_seqr_hmc.read_reg(sent_np); |
p_sequencer.rf_seqr_hmc.read_reg(rcvd_rsp); |
|
if(p_sequencer.link_cfg.cfg_rsp_open_loop==UVM_ACTIVE) |
`uvm_info(get_type_name(), "OPEN RESPONSE LOOP MODE. openHMC tokens not checked.", UVM_NONE) |
else |
`uvm_info(get_type_name(),$psprintf("RX token count in TX_LINK = %0d, should be %0d", status.fields.rx_tokens_remaining_, p_sequencer.link_cfg.rx_tokens),UVM_LOW) |
|
q_size = p_sequencer.scb.axi4_np_requests.size(); |
`uvm_info(get_type_name(), $psprintf("Scoreboard open response queue size = %d",q_size) , UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("HMC token count in TX_LINK = %0d, should be %0d", status.fields.hmc_tokens_remaining_, p_sequencer.link_cfg.hmc_tokens),UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("sent = %0d non-posted packets, received %0d responses", sent_np.fields.cnt_, rcvd_rsp.fields.cnt_),UVM_LOW) |
|
if(q_size==q_size_prev) begin |
timer++; |
end else begin |
timer=0; |
end |
q_size_prev = q_size; |
|
end |
#1us; |
|
p_sequencer.rf_seqr_hmc.read_reg(status); |
p_sequencer.rf_seqr_hmc.read_reg(sent_np); |
p_sequencer.rf_seqr_hmc.read_reg(rcvd_rsp); |
|
#5us; |
|
//-- ***REPORTS*** |
//-- Report Packet Counts |
if( timer==draintime ) begin |
`uvm_info(get_type_name(),$psprintf("Counted: %0d NP Requests, %0d Responses", sent_np.fields.cnt_, rcvd_rsp.fields.cnt_), UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("Responder token count in TX_LINK = %0d, should be %0d", status.fields.hmc_tokens_remaining_, p_sequencer.link_cfg.hmc_tokens), UVM_LOW) |
`uvm_fatal(get_type_name(),$psprintf("Requester token count in TX_LINK = %0d, should be %0d", status.fields.rx_tokens_remaining_, p_sequencer.link_cfg.rx_tokens)) |
end |
|
endtask : body |
|
endclass : openhmc_check_seq |
|
`endif // openhmc_check_seq |
/trunk/openHMC/sim/tb/common/testlib/non_posted_pkt_test/non_posted_pkt_test_seq.sv
0,0 → 1,108
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// non_posted_pkt_test sequence |
// |
// |
|
|
`ifndef non_posted_pkt_test_SEQ_SV |
`define non_posted_pkt_test_SEQ_SV |
|
class non_posted_pkt_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 10; |
} |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
hmc_big_pkts_seq b_pkt; |
hmc_small_pkts_seq s_pkt; |
|
hmc_big_pkts_hdelay_seq b_h_pkt; |
hmc_big_pkts_zdelay_seq b_z_pkt; |
hmc_small_pkts_hdelay_seq s_h_pkt; |
hmc_small_pkts_zdelay_seq s_z_pkt; |
|
function new(string name="non_posted_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(non_posted_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting non_posted_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
|
repeat (iterations) |
randcase |
1 : `uvm_do_with( work,{req_class == NON_POSTED;}) |
1 : `uvm_do_with( b_pkt,{req_class == NON_POSTED;}) |
1 : `uvm_do_with( s_pkt,{req_class == NON_POSTED;}) |
1 : `uvm_do_with(b_h_pkt,{req_class == NON_POSTED;}) |
1 : `uvm_do_with(s_h_pkt,{req_class == NON_POSTED;}) |
1 : `uvm_do_with(b_z_pkt,{req_class == NON_POSTED;}) |
1 : `uvm_do_with(s_z_pkt,{req_class == NON_POSTED;}) |
endcase |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "non_posted_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : non_posted_pkt_test_seq |
|
`endif // non_posted_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/non_posted_pkt_test/non_posted_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// non_posted_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef non_posted_pkt_test_SV |
`define non_posted_pkt_test_SV |
|
class non_posted_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(non_posted_pkt_test) |
|
|
function new(string name = "non_posted_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",non_posted_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : non_posted_pkt_test |
|
`endif // non_posted_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_test/small_pkt_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_test sequence |
// |
// |
|
|
`ifndef small_pkt_test_SEQ_SV |
`define small_pkt_test_SEQ_SV |
|
class small_pkt_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_small_pkts_seq work; |
|
function new(string name="small_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(small_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting small_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "small_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : small_pkt_test_seq |
|
`endif // small_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_test/small_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef small_pkt_test_SV |
`define small_pkt_test_SV |
|
class small_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(small_pkt_test) |
|
|
function new(string name = "small_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",small_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : small_pkt_test |
|
`endif // small_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_zdelay_test/big_pkt_zdelay_test_seq.sv
0,0 → 1,82
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_zdelay_test sequence |
// |
// |
|
|
`ifndef big_pkt_zdelay_test_SEQ_SV |
`define big_pkt_zdelay_test_SEQ_SV |
|
class big_pkt_zdelay_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_big_pkts_zdelay_seq work; |
|
function new(string name="big_pkt_zdelay_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(big_pkt_zdelay_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting big_pkt_zdelay_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_info(get_type_name(), "big_pkt_zdelay_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : big_pkt_zdelay_test_seq |
|
`endif // big_pkt_zdelay_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_zdelay_test/big_pkt_zdelay_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_zdelay_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef big_pkt_zdelay_test_SV |
`define big_pkt_zdelay_test_SV |
|
class big_pkt_zdelay_test extends hmc_base_test; |
|
`uvm_component_utils(big_pkt_zdelay_test) |
|
|
function new(string name = "big_pkt_zdelay_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",big_pkt_zdelay_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : big_pkt_zdelay_test |
|
`endif // big_pkt_zdelay_test_SV |
/trunk/openHMC/sim/tb/common/testlib/bit_error_test/bit_error_test_seq.sv
0,0 → 1,94
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// bit_error_test sequence |
// |
// |
|
`ifndef bit_error_test_SEQ_SV |
`define bit_error_test_SEQ_SV |
|
class bit_error_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 2; |
} |
|
function new(string name="bit_error_test_seq"); |
super.new(name); |
endfunction : new |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
`uvm_object_utils(bit_error_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting bit_error_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
|
repeat (iterations) |
randcase |
1 : `uvm_do_with(work, {req_class == NON_POSTED; }) |
1 : `uvm_do_with(work, {req_class == POSTED; }) |
endcase |
|
`uvm_info(get_type_name(), "bit_error_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : bit_error_test_seq |
|
`endif // bit_error_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/bit_error_test/bit_error_test.sv
0,0 → 1,80
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// bit_error_test test |
// |
// |
|
`ifndef bit_error_test_SV |
`define bit_error_test_SV |
|
class bit_error_test extends hmc_base_test; |
|
`uvm_component_utils(bit_error_test) |
|
|
function new(string name = "bit_error_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",bit_error_test_seq::type_id::get()); |
|
super.build_phase(phase); |
link_cfg.requester.errors_enabled = 0; |
link_cfg.responder.errors_enabled = 0; |
|
link_cfg.requester.lane_errors_enabled = 1; |
link_cfg.responder.lane_errors_enabled = 1; |
|
link_cfg_randomize : assert (link_cfg.randomize()); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : bit_error_test |
|
`endif // bit_error_test_SV |
/trunk/openHMC/sim/tb/common/testlib/simple_test/simple_test.sv
0,0 → 1,73
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// simple_test test |
// |
// |
|
`ifndef simple_test_SV |
`define simple_test_SV |
|
class simple_test extends hmc_base_test; |
|
`uvm_component_utils(simple_test) |
|
|
function new(string name = "simple_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",simple_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : simple_test |
|
`endif // simple_test_SV |
/trunk/openHMC/sim/tb/common/testlib/simple_test/simple_test_seq.sv
0,0 → 1,94
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// simple_test sequence |
// |
// |
|
`ifndef simple_test_SEQ_SV |
`define simple_test_SEQ_SV |
|
class simple_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 10; |
} |
|
function new(string name="simple_test_seq"); |
super.new(name); |
endfunction : new |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
`uvm_object_utils(simple_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting simple_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
|
repeat (iterations) |
randcase |
1 : `uvm_do_with(work, {req_class == NON_POSTED;}) |
1 : `uvm_do_with(work, {req_class == POSTED;}) |
endcase |
|
`uvm_info(get_type_name(), "simple_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : simple_test_seq |
|
`endif // simple_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/atomic_pkt_test/atomic_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// atomic_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef atomic_pkt_test_SV |
`define atomic_pkt_test_SV |
|
class atomic_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(atomic_pkt_test) |
|
|
function new(string name = "atomic_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",atomic_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : atomic_pkt_test |
|
`endif // atomic_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/atomic_pkt_test/atomic_pkt_test_seq.sv
0,0 → 1,101
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// atomic_pkt_test sequence |
// |
// |
|
|
`ifndef atomic_pkt_test_SEQ_SV |
`define atomic_pkt_test_SEQ_SV |
|
class atomic_pkt_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 10; |
} |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
hmc_hdelay_seq hdelay; |
hmc_zdelay_seq zdelay; |
|
|
function new(string name="atomic_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(atomic_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting atomic_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
repeat(iterations) |
randcase |
1 : `uvm_do_with(work, {req_class == ATOMIC;}) |
1 : `uvm_do_with(hdelay, {req_class == ATOMIC;}) |
1 : `uvm_do_with(zdelay, {req_class == ATOMIC;}) |
endcase |
|
|
#1us; |
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "atomic_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : atomic_pkt_test_seq |
|
`endif // atomic_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/test_lib.sv
0,0 → 1,106
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
//-- the base test |
`include "hmc_base_test.sv" |
|
|
//-- sequence lib |
`include "seq_lib/hmc_seq_lib.sv" |
|
//-- the init sequence |
`include "openhmc_init_seq.sv" |
|
//-- Set the HMC model |
`include "hmc_model_init_seq.sv" |
|
//-- check registers after test ends |
`include "openhmc_check_seq.sv" |
|
`include "simple_test/simple_test_seq.sv" |
`include "simple_test/simple_test.sv" |
|
`include "single_pkt_test/single_pkt_test_seq.sv" |
`include "single_pkt_test/single_pkt_test.sv" |
|
`include "sleep_mode_test/sleep_mode_test_seq.sv" |
`include "sleep_mode_test/sleep_mode_test.sv" |
|
`include "atomic_pkt_test/atomic_pkt_test.sv" |
`include "atomic_pkt_test/atomic_pkt_test_seq.sv" |
|
`include "big_pkt_hdelay_test/big_pkt_hdelay_test.sv" |
`include "big_pkt_hdelay_test/big_pkt_hdelay_test_seq.sv" |
|
`include "big_pkt_test/big_pkt_test.sv" |
`include "big_pkt_test/big_pkt_test_seq.sv" |
|
`include "small_pkt_test/small_pkt_test.sv" |
`include "small_pkt_test/small_pkt_test_seq.sv" |
|
`include "big_pkt_zdelay_test/big_pkt_zdelay_test.sv" |
`include "big_pkt_zdelay_test/big_pkt_zdelay_test_seq.sv" |
|
`include "high_delay_pkt_test/high_delay_pkt_test.sv" |
`include "high_delay_pkt_test/high_delay_pkt_test_seq.sv" |
|
`include "zero_delay_pkt_test/zero_delay_pkt_test.sv" |
`include "zero_delay_pkt_test/zero_delay_pkt_test_seq.sv" |
|
`include "non_posted_pkt_test/non_posted_pkt_test.sv" |
`include "non_posted_pkt_test/non_posted_pkt_test_seq.sv" |
|
`include "posted_pkt_test/posted_pkt_test.sv" |
`include "posted_pkt_test/posted_pkt_test_seq.sv" |
|
`include "small_pkt_hdelay_test/small_pkt_hdelay_test.sv" |
`include "small_pkt_hdelay_test/small_pkt_hdelay_test_seq.sv" |
|
`include "small_pkt_zdelay_test/small_pkt_zdelay_test.sv" |
`include "small_pkt_zdelay_test/small_pkt_zdelay_test_seq.sv" |
|
`include "init_test/init_test.sv" |
`include "init_test/init_test_seq.sv" |
|
`ifdef HMC_UVC |
`include "error_pkt_test/error_pkt_test.sv" |
`include "error_pkt_test/error_pkt_test_seq.sv" |
`include "bit_error_test/bit_error_test.sv" |
`include "bit_error_test/bit_error_test_seq.sv" |
`endif |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_zdelay_test/small_pkt_zdelay_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_zdelay_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef small_pkt_zdelay_test_SV |
`define small_pkt_zdelay_test_SV |
|
class small_pkt_zdelay_test extends hmc_base_test; |
|
`uvm_component_utils(small_pkt_zdelay_test) |
|
|
function new(string name = "small_pkt_zdelay_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",small_pkt_zdelay_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : small_pkt_zdelay_test |
|
`endif // small_pkt_zdelay_test_SV |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_zdelay_test/small_pkt_zdelay_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_zdelay_test sequence |
// |
// |
|
|
`ifndef small_pkt_zdelay_test_SEQ_SV |
`define small_pkt_zdelay_test_SEQ_SV |
|
class small_pkt_zdelay_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_small_pkts_zdelay_seq work; |
|
function new(string name="small_pkt_zdelay_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(small_pkt_zdelay_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting small_pkt_zdelay_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "small_pkt_zdelay_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : small_pkt_zdelay_test_seq |
|
`endif // small_pkt_zdelay_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/single_pkt_test/single_pkt_test.sv
0,0 → 1,73
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// single_pkt_test test |
// |
// |
|
`ifndef single_pkt_test_SV |
`define single_pkt_test_SV |
|
class single_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(single_pkt_test) |
|
|
function new(string name = "single_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",single_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : single_pkt_test |
|
`endif // single_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/single_pkt_test/single_pkt_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// simple_test sequence |
// |
// |
|
`ifndef single_pkt_test_seq_SV |
`define single_pkt_test_seq_SV |
|
class single_pkt_test_seq extends hmc_base_seq; |
|
function new(string name="single_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
`uvm_object_utils(single_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting single_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
|
`uvm_do_with(work, {req_class == NON_POSTED;num_packets==1;}) |
|
`uvm_info(get_type_name(), "single_pkt_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : single_pkt_test_seq |
|
`endif // single_pkt_test_seq_SV |
/trunk/openHMC/sim/tb/common/testlib/init_test/init_test_seq.sv
0,0 → 1,80
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// init_test sequence |
// |
// |
|
`ifndef init_test_SEQ_SV |
`define init_test_SEQ_SV |
|
class init_test_seq extends hmc_base_seq; |
|
function new(string name="init_test_seq"); |
super.new(name); |
endfunction : new |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
|
`uvm_object_utils(init_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting init_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
|
`uvm_info(get_type_name(), "init_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : init_test_seq |
|
`endif // init_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/init_test/init_test.sv
0,0 → 1,75
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// init_test test |
// |
// |
|
`ifndef init_test_SV |
`define init_test_SV |
|
class init_test extends hmc_base_test; |
|
`uvm_component_utils(init_test) |
|
|
function new(string name = "init_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
// set_type_override_by_type(hmc_req_packet::get_type(),hmc_req_posted_packet::get_type()); |
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",init_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : init_test |
|
`endif // init_test_SV |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_hdelay_test/big_pkt_hdelay_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_hdelay_test sequence |
// |
// |
|
|
`ifndef big_pkt_hdelay_test_SEQ_SV |
`define big_pkt_hdelay_test_SEQ_SV |
|
class big_pkt_hdelay_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_big_pkts_hdelay_seq work; |
|
function new(string name="big_pkt_hdelay_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(big_pkt_hdelay_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting big_pkt_hdelay_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "big_pkt_hdelay_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : big_pkt_hdelay_test_seq |
|
`endif // big_pkt_hdelay_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_hdelay_test/big_pkt_hdelay_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_hdelay_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef big_pkt_hdelay_test_SV |
`define big_pkt_hdelay_test_SV |
|
class big_pkt_hdelay_test extends hmc_base_test; |
|
`uvm_component_utils(big_pkt_hdelay_test) |
|
|
function new(string name = "big_pkt_hdelay_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",big_pkt_hdelay_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : big_pkt_hdelay_test |
|
`endif // big_pkt_hdelay_test_SV |
/trunk/openHMC/sim/tb/common/testlib/error_pkt_test/error_pkt_test_seq.sv
0,0 → 1,94
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// error_pkt_test sequence |
// |
// |
|
`ifndef error_pkt_test_SEQ_SV |
`define error_pkt_test_SEQ_SV |
|
class error_pkt_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 20; |
} |
|
function new(string name="error_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
`uvm_object_utils(error_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting error_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
|
repeat (iterations) |
randcase |
1 : `uvm_do_with(work, {req_class == NON_POSTED;}) |
1 : `uvm_do_with(work, {req_class == POSTED;}) |
endcase |
|
`uvm_info(get_type_name(), "error_pkt_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : error_pkt_test_seq |
|
`endif // error_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/error_pkt_test/error_pkt_test.sv
0,0 → 1,78
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// error_pkt_test test |
// |
// |
|
`ifndef error_pkt_test_SV |
`define error_pkt_test_SV |
|
class error_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(error_pkt_test) |
|
|
function new(string name = "error_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",error_pkt_test_seq::type_id::get()); |
super.build_phase(phase); |
link_cfg.requester.errors_enabled = 1; |
link_cfg.responder.errors_enabled = 1; |
|
link_cfg.requester.lane_errors_enabled = 0; |
link_cfg.responder.lane_errors_enabled = 0; |
|
link_cfg_randomize : assert (link_cfg.randomize()); |
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : error_pkt_test |
|
`endif // error_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/zero_delay_pkt_test/zero_delay_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// zero_delay_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef zero_delay_pkt_test_SV |
`define zero_delay_pkt_test_SV |
|
class zero_delay_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(zero_delay_pkt_test) |
|
|
function new(string name = "zero_delay_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",zero_delay_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : zero_delay_pkt_test |
|
`endif // zero_delay_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/zero_delay_pkt_test/zero_delay_pkt_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// zero_delay_pkt_test sequence |
// |
// |
|
|
`ifndef zero_delay_pkt_test_SEQ_SV |
`define zero_delay_pkt_test_SEQ_SV |
|
class zero_delay_pkt_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_zdelay_seq work; |
|
function new(string name="zero_delay_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(zero_delay_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting zero_delay_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "zero_delay_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : zero_delay_pkt_test_seq |
|
`endif // zero_delay_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/high_delay_pkt_test/high_delay_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// high_delay_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef high_delay_pkt_test_SV |
`define high_delay_pkt_test_SV |
|
class high_delay_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(high_delay_pkt_test) |
|
|
function new(string name = "high_delay_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",high_delay_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : high_delay_pkt_test |
|
`endif // high_delay_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/high_delay_pkt_test/high_delay_pkt_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// high_delay_pkt_test sequence |
// |
// |
|
|
`ifndef high_delay_pkt_test_SEQ_SV |
`define high_delay_pkt_test_SEQ_SV |
|
class high_delay_pkt_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_hdelay_seq work; |
|
function new(string name="high_delay_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(high_delay_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting high_delay_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "high_delay_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : high_delay_pkt_test_seq |
|
`endif // high_delay_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_hdelay_test/small_pkt_hdelay_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_hdelay_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef small_pkt_hdelay_test_SV |
`define small_pkt_hdelay_test_SV |
|
class small_pkt_hdelay_test extends hmc_base_test; |
|
`uvm_component_utils(small_pkt_hdelay_test) |
|
|
function new(string name = "small_pkt_hdelay_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",small_pkt_hdelay_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : small_pkt_hdelay_test |
|
`endif // small_pkt_hdelay_test_SV |
/trunk/openHMC/sim/tb/common/testlib/small_pkt_hdelay_test/small_pkt_hdelay_test_seq.sv
0,0 → 1,84
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// small_pkt_hdelay_test sequence |
// |
// |
|
|
`ifndef small_pkt_hdelay_test_SEQ_SV |
`define small_pkt_hdelay_test_SEQ_SV |
|
class small_pkt_hdelay_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_small_pkts_hdelay_seq work; |
|
function new(string name="small_pkt_hdelay_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(small_pkt_hdelay_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting small_pkt_hdelay_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
|
#1us; |
`uvm_info(get_type_name(), "small_pkt_hdelay_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : small_pkt_hdelay_test_seq |
|
`endif // small_pkt_hdelay_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/sleep_mode_test/sleep_mode_test.sv
0,0 → 1,73
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// slep_mode_test test |
// |
// |
|
`ifndef slep_mode_test_SV |
`define slep_mode_test_SV |
|
class sleep_mode_test extends hmc_base_test; |
|
`uvm_component_utils(sleep_mode_test) |
|
|
function new(string name = "sleep_mode_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",sleep_mode_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : sleep_mode_test |
|
`endif // slep_mode_test_SV |
/trunk/openHMC/sim/tb/common/testlib/sleep_mode_test/sleep_mode_test_seq.sv
0,0 → 1,170
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// sleep_mode_test sequence |
// |
// |
|
`ifndef sleep_mode_test_SEQ_SV |
`define sleep_mode_test_SEQ_SV |
|
class sleep_mode_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 10; |
} |
|
function new(string name="sleep_mode_test_seq"); |
super.new(name); |
endfunction : new |
|
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
reg_openhmc_rf_status_general_c status; |
reg_openhmc_rf_control_c control; |
reg_openhmc_rf_sent_np_c sent_np; |
reg_openhmc_rf_rcvd_rsp_c rcvd_rsp; |
|
`uvm_object_utils(sleep_mode_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
int timer; |
|
task wait_for_idle (); |
timer = 0; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
p_sequencer.rf_seqr_hmc.read_reg(sent_np); |
p_sequencer.rf_seqr_hmc.read_reg(rcvd_rsp); |
p_sequencer.rf_seqr_hmc.read_reg(control); |
#1us; |
|
while( ((sent_np.fields.cnt_ != rcvd_rsp.fields.cnt_) || |
(status.fields.hmc_tokens_remaining_ != p_sequencer.link_cfg.hmc_tokens) || |
(status.fields.rx_tokens_remaining_ != p_sequencer.link_cfg.rx_tokens)) |
&& |
(timer < 200)) begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
p_sequencer.rf_seqr_hmc.read_reg(sent_np); |
p_sequencer.rf_seqr_hmc.read_reg(rcvd_rsp); |
`uvm_info(get_type_name(),$psprintf("RX token count in TX_LINK = %0d, should be %0d" , status.fields.rx_tokens_remaining_ , p_sequencer.link_cfg.rx_tokens),UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("HMC token count in TX_LINK = %0d, should be %0d", status.fields.hmc_tokens_remaining_, p_sequencer.link_cfg.hmc_tokens),UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("sent = %0d non-posted packets, received %0d responses", sent_np.fields.cnt_, rcvd_rsp.fields.cnt_),UVM_LOW) |
timer++; |
end |
#3us; |
endtask |
|
|
virtual task body(); |
time sleep_time = 10us; |
|
`uvm_info(get_type_name(), "starting sleep_mode_test_seq", UVM_NONE) |
|
//initiate all the registers |
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
|
$cast(control,p_sequencer.rf_seqr_hmc.get_by_name("control")); |
control.set_check_on_read(1'b0); |
|
$cast(sent_np,p_sequencer.rf_seqr_hmc.get_by_name("sent_np")); |
sent_np.set_check_on_read(1'b0); |
|
$cast(rcvd_rsp,p_sequencer.rf_seqr_hmc.get_by_name("rcvd_rsp")); |
rcvd_rsp.set_check_on_read(1'b0); |
|
//-- write your test here |
`uvm_do(bfm) |
|
#1us; |
`uvm_do(init) |
#1us; |
|
repeat (iterations) begin |
repeat(5) begin |
randcase |
1 : `uvm_do_with(work, {req_class == NON_POSTED;}) |
1 : `uvm_do_with(work, {req_class == POSTED;}) |
endcase |
end |
//Sleep Mode entry and exit |
`uvm_info(get_type_name(),$psprintf("SLEEP MODE: WAIT FOR IDLE"),UVM_LOW) |
wait_for_idle(); |
`uvm_info(get_type_name(),$psprintf("SLEEP MODE: SET"),UVM_LOW) |
//Set the sleep_mode_test bit within the Register File |
control.fields.set_hmc_sleep_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
p_sequencer.rf_seqr_hmc.read_reg(status); |
#1us; |
while(!status.fields.sleep_mode_) begin |
p_sequencer.rf_seqr_hmc.read_reg(status); |
end |
//Stay in Sleep for up to 22 us |
sleep_time_rand_succeeds : assert (std::randomize(sleep_time) |
with {sleep_time >= 2us && sleep_time < 22us;}); //-- should be 1ms in real system |
#(sleep_time); |
`uvm_info(get_type_name(),$psprintf("SLEEP MODE: EXIT"),UVM_LOW) |
//Force openHMC controller to exit sleep mode |
control.fields.set_hmc_sleep_ = 0; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
while(!status.fields.link_up_) begin |
p_sequencer.rf_seqr_hmc.read_reg(status); |
end |
end |
|
#1us; |
`uvm_info(get_type_name(), "sleep_mode_test_seq done", UVM_NONE) |
`uvm_do(check) |
|
endtask : body |
|
endclass : sleep_mode_test_seq |
|
`endif // sleep_mode_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/posted_pkt_test/posted_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// posted_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef posted_pkt_test_SV |
`define posted_pkt_test_SV |
|
class posted_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(posted_pkt_test) |
|
|
function new(string name = "posted_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",posted_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : posted_pkt_test |
|
`endif // posted_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/posted_pkt_test/posted_pkt_test_seq.sv
0,0 → 1,110
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// posted_pkt_test sequence |
// |
// |
|
|
`ifndef posted_pkt_test_SEQ_SV |
`define posted_pkt_test_SEQ_SV |
|
class posted_pkt_test_seq extends hmc_base_seq; |
|
rand int iterations; |
|
constraint iterations_c { |
iterations >= 1; |
iterations <= 10; |
} |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_base_pkt_seq work; |
|
hmc_big_pkts_seq b_pkt; |
hmc_small_pkts_seq s_pkt; |
|
hmc_big_pkts_hdelay_seq b_h_pkt; |
hmc_big_pkts_zdelay_seq b_z_pkt; |
hmc_small_pkts_hdelay_seq s_h_pkt; |
hmc_small_pkts_zdelay_seq s_z_pkt; |
|
function new(string name="posted_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(posted_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting posted_pkt_test_seq", UVM_NONE) |
|
//-- write your test here |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
repeat(iterations) |
randcase |
1 : `uvm_do_with( work,{req_class == POSTED;}) |
1 : `uvm_do_with( b_pkt,{req_class == POSTED;}) |
1 : `uvm_do_with( s_pkt,{req_class == POSTED;}) |
1 : `uvm_do_with(b_h_pkt,{req_class == POSTED;}) |
1 : `uvm_do_with(s_h_pkt,{req_class == POSTED;}) |
1 : `uvm_do_with(b_z_pkt,{req_class == POSTED;}) |
1 : `uvm_do_with(s_z_pkt,{req_class == POSTED;}) |
endcase |
|
#1us |
`uvm_do(check) |
|
#1us; |
`uvm_info(get_type_name(), "posted_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : posted_pkt_test_seq |
|
`endif // posted_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_small_pkts_seq.sv
0,0 → 1,50
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
class hmc_small_pkts_seq extends hmc_base_pkt_seq; |
|
constraint p_length_c { |
max_packet_length == 2; |
} |
`uvm_object_utils(hmc_small_pkts_seq) |
|
function new(string name="hmc_small_pkts_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_small_pkts_seq |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_big_pkts_zdelay_seq.sv
0,0 → 1,63
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_BIG_PKTS_ZDELAY |
`define HMC_BIG_PKTS_ZDELAY |
|
class hmc_big_pkts_zdelay_seq extends hmc_base_pkt_seq; |
|
hmc_big_pkts_seq seq; |
|
|
constraint mx_delay_c { |
max_flit_delay == 0; |
} |
|
constraint big_pkts_c { |
min_packet_length == 6; |
} |
|
`uvm_object_utils(hmc_big_pkts_zdelay_seq) |
|
function new(string name="hmc_big_pkts_zdelay_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_big_pkts_zdelay_seq |
|
`endif |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_single_pkt_cycle_seq.sv
0,0 → 1,57
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef SINGLE_PKT_CYCLE_SEQ |
`define SINGLE_PKT_CYCLE_SEQ |
|
class hmc_single_pkt_cycle_seq extends hmc_base_pkt_seq; |
|
constraint pkts_per_req_c{ |
pkts_per_req == 1; |
} |
|
`uvm_object_utils(hmc_single_pkt_cycle_seq) |
|
function new(string name="hmc_single_pkt_cycle_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_single_pkt_cycle_seq |
|
|
`endif |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_small_pkts_hdelay_seq.sv
0,0 → 1,62
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef SMALL_PKTS_HDELAY_SEQ |
`define SMALL_PKTS_HDELAY_SEQ |
|
class hmc_small_pkts_hdelay_seq extends hmc_small_pkts_seq; |
|
constraint high_delay { |
min_flit_delay >= 90; |
max_flit_delay <= 200; |
} |
|
constraint small_pkts_c { |
max_packet_length == 2; |
} |
|
`uvm_object_utils(hmc_small_pkts_hdelay_seq) |
|
function new(string name="hmc_small_pkts_hdelay_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_small_pkts_hdelay_seq |
|
|
`endif //SMALL_PKTS_HDELAY_SEQ |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_small_pkts_zdelay_seq.sv
0,0 → 1,56
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
class hmc_small_pkts_zdelay_seq extends hmc_base_pkt_seq; |
|
hmc_small_pkts_seq seq; |
|
constraint mx_delay_c { |
max_flit_delay == 0; |
} |
|
constraint small_pkts_c { |
max_packet_length == 2; |
} |
`uvm_object_utils(hmc_small_pkts_zdelay_seq) |
|
function new(string name="hmc_small_pkts_zdelay_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_small_pkts_zdelay_seq |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_big_pkts_seq.sv
0,0 → 1,51
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
class hmc_big_pkts_seq extends hmc_base_pkt_seq; |
|
|
constraint min_max_length_c { |
min_packet_length >= 6; |
} |
|
`uvm_object_utils(hmc_big_pkts_seq) |
|
function new(string name="hmc_big_pkts_seq"); |
super.new(name); |
endfunction : new |
endclass : hmc_big_pkts_seq |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_hdelay_seq.sv
0,0 → 1,51
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
class hmc_hdelay_seq extends hmc_base_pkt_seq; |
|
constraint p_delay_c { |
min_flit_delay == 90; |
max_flit_delay == 200; |
} |
|
`uvm_object_utils(hmc_hdelay_seq) |
|
function new(string name="hmc_hdelay_seq"); |
super.new(name); |
endfunction : new |
endclass : hmc_hdelay_seq |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_seq_lib.sv
0,0 → 1,57
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_PACKET_SEQ_LIB |
`define HMC_PACKET_SEQ_LIB |
|
|
`include "seq_lib/hmc_base_pkt_seq.sv" |
`include "seq_lib/hmc_small_pkts_seq.sv" |
`include "seq_lib/hmc_big_pkts_seq.sv" |
`include "seq_lib/hmc_hdelay_seq.sv" |
`include "seq_lib/hmc_zdelay_seq.sv" |
|
`include "seq_lib/hmc_big_pkts_zdelay_seq.sv" |
`include "seq_lib/hmc_small_pkts_zdelay_seq.sv" |
|
`include "seq_lib/hmc_big_pkts_hdelay_seq.sv" |
`include "seq_lib/hmc_small_pkts_hdelay_seq.sv" |
|
`include "seq_lib/hmc_single_pkt_cycle_seq.sv" |
|
`endif |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_base_pkt_seq.sv
0,0 → 1,189
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_BASE_PKT_SEQ |
`define HMC_BASE_PKT_SEQ |
|
typedef enum { |
POSTED, |
ATOMIC, |
NON_POSTED, |
ALL_TYPES |
// MISC |
} request_class_e; |
|
class hmc_base_pkt_seq extends hmc_base_seq; |
|
|
|
rand int num_packets ; |
rand int pkts_per_req; |
|
|
rand request_class_e req_class; |
|
//-- delay constraints |
rand int min_flit_delay ; |
rand int max_flit_delay ; |
|
rand int min_packet_length ; |
rand int max_packet_length ; |
|
|
|
constraint delay_c { |
!(min_flit_delay > max_flit_delay); |
min_flit_delay >= 0; |
soft max_flit_delay <= 50; |
} |
|
constraint pkt_length_c { |
min_packet_length <= max_packet_length; |
min_packet_length >= 0; |
max_packet_length <= 9; |
} |
|
constraint num_packets_c { |
num_packets > 0; |
soft num_packets <= 50; |
} |
|
constraint pkts_per_req_c { |
pkts_per_req > 0; |
soft pkts_per_req <= 10; |
pkts_per_req <= num_packets; |
} |
|
`uvm_object_utils(hmc_base_pkt_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
|
function new(string name="hmc_base_pkt_seq"); |
super.new(name); |
endfunction : new |
|
virtual task body(); |
`uvm_info(get_type_name(), "starting...", UVM_HIGH) |
|
while (num_packets > 0) begin |
`uvm_create_on(requests, p_sequencer.axi4_req_seqr) |
if(req_class == POSTED) |
`uvm_info(get_type_name(),$psprintf("sending posted requests"), UVM_MEDIUM) |
else if (req_class == NON_POSTED) |
`uvm_info(get_type_name(),$psprintf("sending non_posted requests"), UVM_MEDIUM) |
else if (req_class == ATOMIC) |
`uvm_info(get_type_name(),$psprintf("sending atomic requests"), UVM_MEDIUM) |
else if (req_class == ALL) |
`uvm_info(get_type_name(),$psprintf("sending all requests"), UVM_MEDIUM) |
requests.num_packets = pkts_per_req; |
void'(requests.randomize() with { |
foreach(requests.hmc_items[i]) { |
requests.hmc_items[i].flit_delay inside {[min_flit_delay:max_flit_delay]}; |
soft requests.hmc_items[i].packet_length inside {[min_packet_length:max_packet_length]}; |
if(req_class == POSTED) { |
requests.hmc_items[i].command inside { |
HMC_POSTED_WRITE_16, |
HMC_POSTED_WRITE_32, |
HMC_POSTED_WRITE_48, |
HMC_POSTED_WRITE_64, |
HMC_POSTED_WRITE_80, |
HMC_POSTED_WRITE_96, |
HMC_POSTED_WRITE_112, |
HMC_POSTED_WRITE_128, |
HMC_POSTED_BIT_WRIT |
}; |
} |
if(req_class == NON_POSTED) { |
requests.hmc_items[i].command inside { |
HMC_WRITE_16, |
HMC_WRITE_32, |
HMC_WRITE_48, |
HMC_WRITE_64, |
HMC_WRITE_80, |
HMC_WRITE_96, |
HMC_WRITE_112, |
HMC_WRITE_128, |
|
HMC_MODE_READ, |
HMC_READ_16, |
HMC_READ_32, |
HMC_READ_48, |
HMC_READ_64, |
HMC_READ_80, |
HMC_READ_96, |
HMC_READ_112, |
HMC_READ_128}; |
} |
if(req_class == ATOMIC) { |
requests.hmc_items[i].command inside { |
//HMC_MODE_WRITE, |
HMC_BIT_WRITE, |
HMC_DUAL_8B_ADDI, |
HMC_SINGLE_16B_ADDI, |
HMC_POSTED_BIT_WRIT, |
|
HMC_POSTED_BIT_WRIT, |
HMC_POSTED_DUAL_8B_ADDI, |
HMC_POSTED_SINGLE_16B_ADDI |
|
// HMC_MODE_READ |
}; |
} |
// if(req_class == MISC) { |
// requests.hmc_items[i].command inside { |
// // //HMC_MODE_WRITE |
// HMC_MODE_READ}; |
// } |
|
|
|
} |
}); |
num_packets -= pkts_per_req; |
`uvm_info(get_type_name(),$psprintf("Packets sent!"), UVM_MEDIUM) |
|
`uvm_send(requests) |
end |
|
endtask : body |
|
endclass : hmc_base_pkt_seq |
|
|
`endif |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_zdelay_seq.sv
0,0 → 1,51
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
class hmc_zdelay_seq extends hmc_base_pkt_seq; |
|
constraint zdelay { |
max_flit_delay == 0; |
} |
|
`uvm_object_utils(hmc_zdelay_seq) |
|
function new(string name="hmc_zdelay_seq"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_zdelay_seq |
/trunk/openHMC/sim/tb/common/testlib/seq_lib/hmc_big_pkts_hdelay_seq.sv
0,0 → 1,64
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef BIG_PKTS_HDELAY_SEQ |
`define BIG_PKTS_HDELAY_SEQ |
|
class hmc_big_pkts_hdelay_seq extends hmc_big_pkts_seq; |
|
constraint high_delay { |
min_flit_delay >= 90; |
max_flit_delay <= 200; |
} |
constraint big_pkts_c { |
min_packet_length == 6; |
} |
|
|
|
`uvm_object_utils(hmc_big_pkts_hdelay_seq) |
|
function new(string name="hmc_big_pkts_hdelay_seq"); |
super.new(name); |
endfunction : new |
|
|
endclass : hmc_big_pkts_hdelay_seq |
|
|
`endif // BIG_PKTS_HDELAY_SEQ |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_test/big_pkt_test.sv
0,0 → 1,77
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_test test |
// |
// |
|
// test description: |
// add a description of the test here |
|
|
`ifndef big_pkt_test_SV |
`define big_pkt_test_SV |
|
class big_pkt_test extends hmc_base_test; |
|
`uvm_component_utils(big_pkt_test) |
|
|
function new(string name = "big_pkt_test", uvm_component parent = null); |
super.new(name,parent); |
endfunction : new |
|
|
virtual function void build_phase(uvm_phase phase); |
|
uvm_config_db#(uvm_object_wrapper)::set(this,"hmc_tb0.v_seqr.run_phase","default_sequence",big_pkt_test_seq::type_id::get()); |
|
super.build_phase(phase); |
|
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 1us); |
endtask : run_phase |
|
endclass : big_pkt_test |
|
`endif // big_pkt_test_SV |
/trunk/openHMC/sim/tb/common/testlib/big_pkt_test/big_pkt_test_seq.sv
0,0 → 1,83
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// big_pkt_test sequence |
// |
// |
|
|
`ifndef big_pkt_test_SEQ_SV |
`define big_pkt_test_SEQ_SV |
|
class big_pkt_test_seq extends hmc_base_seq; |
|
openhmc_init_seq init; |
hmc_model_init_seq bfm; |
openhmc_check_seq check; |
hmc_big_pkts_seq work; |
|
function new(string name="big_pkt_test_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(big_pkt_test_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting big_pkt_test_seq", UVM_NONE) |
|
`uvm_do(bfm) |
#1us; |
`uvm_do(init) |
#1us; |
//-- write your test here |
`uvm_do(work) |
|
`uvm_do(check) |
#1us; |
`uvm_info(get_type_name(), "big_pkt_test_seq done", UVM_NONE) |
|
endtask : body |
|
endclass : big_pkt_test_seq |
|
`endif // big_pkt_test_SEQ_SV |
/trunk/openHMC/sim/tb/common/src/tag_handler.sv
0,0 → 1,178
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// tag handler |
// |
// |
|
`ifndef TAG_HANDLER_SV |
`define TAG_HANDLER_SV |
|
class tag_handler extends uvm_component; |
|
int tag_count = 512; //-- tags available at the beginning |
bit tags_in_use[]; //-- bitmap of current used tags |
int tag_fifo[$]; |
int transaction_count; |
int max_tags_in_use; |
int num_tags_in_use; |
int used_tag; |
|
event tag_avail_event; |
|
covergroup tags_used_cg; |
TAGS_USED : coverpoint used_tag{ |
bins valid_tags [] = {[0:tag_count-1]}; |
bins illegal_tags = {[tag_count:$]}; |
} |
endgroup |
|
`uvm_analysis_imp_decl(_hmc_rsp) |
uvm_analysis_imp_hmc_rsp #(hmc_packet, tag_handler) hmc_rsp_port; |
|
`uvm_component_utils_begin(tag_handler) |
`uvm_field_int(tag_count, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new ( string name="tag_handler", uvm_component parent ); |
super.new(name, parent); |
tags_used_cg = new(); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
hmc_rsp_port = new("hmc_rsp_port",this); |
|
tags_in_use = new [tag_count]; |
|
max_tags_in_use = 0; |
transaction_count = 0; |
reset(); |
endfunction : build_phase |
|
function void reset(); |
|
foreach (tags_in_use[i]) begin |
tags_in_use[i] =0; |
end |
|
num_tags_in_use = 0; |
tag_fifo = {}; |
|
for (int i=0; i< tag_count; i++) |
tag_fifo.push_back(tag_count-1-i); |
endfunction : reset |
|
task get_tag(ref int tag ); |
//-- wait until at least 1 tag available |
if (tag_fifo.size() == 0) begin |
`uvm_info(get_type_name(), $psprintf("get_tag: no tags available...waiting"), UVM_HIGH) |
@(tag_avail_event); |
`uvm_info(get_type_name(), $psprintf("get_tag: one tag is now available"), UVM_HIGH) |
end |
|
//-- flag tag as used |
tag = tag_fifo.pop_front(); |
tags_in_use[tag] = 1'b1; |
used_tag = tag; |
tags_used_cg.sample(); |
|
num_tags_in_use++; |
if (num_tags_in_use > max_tags_in_use) |
max_tags_in_use = num_tags_in_use; |
endtask : get_tag |
|
task try_get_tag(ref int tag ); |
//-- wait until at least 1 tag available |
if (tag_fifo.size() == 0) begin |
`uvm_info(get_type_name(), $psprintf("get_tag: no tags available...returning NULL"), UVM_HIGH) |
tag = -1; |
end else begin |
|
//-- flag tag as used |
tag = tag_fifo.pop_front(); |
tags_in_use[tag] = 1'b1; |
used_tag = tag; |
tags_used_cg.sample(); |
|
num_tags_in_use++; |
if (num_tags_in_use > max_tags_in_use) |
max_tags_in_use = num_tags_in_use; |
end |
endtask : try_get_tag |
|
function void release_tag(input int tag); |
if (!tags_in_use[tag]) |
`uvm_fatal(get_type_name(), $psprintf("release_tag: tag (%0d) not in use!", tag)) |
//-- release tag |
tags_in_use[tag] = 1'b0; |
num_tags_in_use--; |
transaction_count++; |
tag_fifo.push_back(tag); |
|
//-- signal that tag is available |
-> tag_avail_event; |
endfunction : release_tag |
|
function void write_hmc_rsp(input hmc_packet packet); |
if (packet.command != HMC_ERROR_RESPONSE) |
release_tag(packet.tag); |
endfunction : write_hmc_rsp |
|
function void idle_check(); |
if (num_tags_in_use > 0) |
for (int i=0; i<tag_count; i++) |
if (tags_in_use[i]) |
`uvm_fatal(get_type_name(), $psprintf("%0d tags still in use, first one is %0d!", num_tags_in_use, i)) |
if (tag_fifo.size() != tag_count) |
`uvm_fatal(get_type_name(), $psprintf("tag FIFO should have num_tags (%0d) entries it has %0d!", tag_count, tag_fifo.size())) |
endfunction : idle_check |
|
function void check_phase(uvm_phase phase); |
idle_check(); |
endfunction : check_phase |
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("max_tags_in_use %0d, transaction_count %0d", max_tags_in_use, transaction_count), UVM_LOW) |
endfunction : report_phase |
|
endclass : tag_handler |
|
`endif // TAG_HANDLER_SV |
/trunk/openHMC/sim/tb/common/src/rgm/openhmc/register_file_model_16x.sv
0,0 → 1,436
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// HMC controller status |
// |
class reg_openhmc_rf_status_general_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [15:0] lane_polarity_reversed_; |
bit [5:0] Reserved_0; |
bit [9:0] rx_tokens_remaining_; |
bit [5:0] Reserved_1; |
bit [9:0] hmc_tokens_remaining_; |
bit [5:0] Reserved_2; |
bit [0:0] phy_rx_ready_; |
bit [0:0] phy_tx_ready_; |
bit [2:0] Reserved_3; |
bit [0:0] lanes_reversed_; |
bit [0:0] FERR_N_; |
bit [0:0] sleep_mode_; |
bit [0:0] link_training_; |
bit [0:0] link_up_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_status_general_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_status_general_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
endfunction : new |
|
endclass : reg_openhmc_rf_status_general_c |
|
// |
// HMC controller initialization status |
// |
class reg_openhmc_rf_status_init_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [1:0] tx_init_state_; |
bit [2:0] rx_init_state_; |
bit [0:0] all_descramblers_aligned_; |
bit [15:0] descrambler_aligned_; |
bit [15:0] descrambler_part_aligned_; |
bit [15:0] lane_descramblers_locked_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_status_init_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_status_init_c"); |
super.new(name); |
this.name = name; |
set_address('h8); |
endfunction : new |
|
endclass : reg_openhmc_rf_status_init_c |
|
// |
// HMC controller control |
// |
class reg_openhmc_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [5:0] bit_slip_time_; |
bit [2:0] Reserved_4; |
bit [4:0] irtry_to_send_; |
bit [2:0] Reserved_5; |
bit [4:0] irtry_received_threshold_; |
bit [5:0] Reserved_6; |
bit [9:0] rx_token_count_; |
bit [4:0] Reserved_7; |
bit [0:0] debug_halt_on_tx_retry_; |
bit [0:0] debug_halt_on_error_abort_; |
bit [0:0] debug_dont_send_tret_; |
bit [1:0] Reserved_8; |
bit [0:0] run_length_enable_; |
bit [0:0] scrambler_disable_; |
bit [0:0] warm_reset_; |
bit [0:0] set_hmc_sleep_; |
bit [0:0] hmc_init_cont_set_; |
bit [0:0] p_rst_n_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h10); |
endfunction : new |
|
endclass : reg_openhmc_rf_control_c |
|
// |
// Posted requests sent to the HMC |
// |
class reg_openhmc_rf_sent_p_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_p_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_p_c"); |
super.new(name); |
this.name = name; |
set_address('h18); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_p_c |
|
// |
// Nonposted requests sent to the HMC |
// |
class reg_openhmc_rf_sent_np_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_np_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_np_c"); |
super.new(name); |
this.name = name; |
set_address('h20); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_np_c |
|
// |
// Read requests sent to the HMC |
// |
class reg_openhmc_rf_sent_r_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_r_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_r_c"); |
super.new(name); |
this.name = name; |
set_address('h28); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_r_c |
|
// |
// Count of packets that had data errors but valid flow information |
// |
class reg_openhmc_rf_poisoned_packets_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_poisoned_packets_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_poisoned_packets_c"); |
super.new(name); |
this.name = name; |
set_address('h30); |
endfunction : new |
|
endclass : reg_openhmc_rf_poisoned_packets_c |
|
// |
// Responses received from the HMC |
// |
class reg_openhmc_rf_rcvd_rsp_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_rcvd_rsp_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_rcvd_rsp_c"); |
super.new(name); |
this.name = name; |
set_address('h38); |
endfunction : new |
|
endclass : reg_openhmc_rf_rcvd_rsp_c |
|
// |
// Reset performance counters |
// |
class reg_openhmc_rf_counter_reset_c extends cag_rgm_register; |
|
typedef struct packed { |
bit rreinit_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_counter_reset_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_counter_reset_c"); |
super.new(name); |
this.name = name; |
set_address('h40); |
endfunction : new |
|
endclass : reg_openhmc_rf_counter_reset_c |
|
// |
// Count of re-transmit requests |
// |
class reg_openhmc_rf_tx_link_retries_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_tx_link_retries_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_tx_link_retries_c"); |
super.new(name); |
this.name = name; |
set_address('h48); |
endfunction : new |
|
endclass : reg_openhmc_rf_tx_link_retries_c |
|
// |
// Count of errors seen on RX |
// |
class reg_openhmc_rf_errors_on_rx_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_errors_on_rx_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_errors_on_rx_c"); |
super.new(name); |
this.name = name; |
set_address('h50); |
endfunction : new |
|
endclass : reg_openhmc_rf_errors_on_rx_c |
|
// |
// The number of bit_flips forced by the run length limiter |
// |
class reg_openhmc_rf_run_length_bit_flip_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_run_length_bit_flip_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_run_length_bit_flip_c"); |
super.new(name); |
this.name = name; |
set_address('h58); |
endfunction : new |
|
endclass : reg_openhmc_rf_run_length_bit_flip_c |
|
// |
// Indicates the number of error abort modes not cleared in time |
// |
class reg_openhmc_rf_error_abort_not_cleared_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_error_abort_not_cleared_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_error_abort_not_cleared_c"); |
super.new(name); |
this.name = name; |
set_address('h60); |
endfunction : new |
|
endclass : reg_openhmc_rf_error_abort_not_cleared_c |
|
class rf_openhmc_rf_c extends cag_rgm_register_file; |
|
rand reg_openhmc_rf_status_general_c status_general; |
rand reg_openhmc_rf_status_init_c status_init; |
rand reg_openhmc_rf_control_c control; |
rand reg_openhmc_rf_sent_p_c sent_p; |
rand reg_openhmc_rf_sent_np_c sent_np; |
rand reg_openhmc_rf_sent_r_c sent_r; |
rand reg_openhmc_rf_poisoned_packets_c poisoned_packets; |
rand reg_openhmc_rf_rcvd_rsp_c rcvd_rsp; |
rand reg_openhmc_rf_counter_reset_c counter_reset; |
rand reg_openhmc_rf_tx_link_retries_c tx_link_retries; |
rand reg_openhmc_rf_errors_on_rx_c errors_on_rx; |
rand reg_openhmc_rf_run_length_bit_flip_c run_length_bit_flip; |
rand reg_openhmc_rf_error_abort_not_cleared_c error_abort_not_cleared; |
|
`uvm_object_utils(rf_openhmc_rf_c) |
|
function new(string name="rf_openhmc_rf_c"); |
super.new(name); |
this.name = name; |
status_general = reg_openhmc_rf_status_general_c::type_id::create("status_general"); |
status_general.set_address('h0); |
add_register(status_general); |
status_init = reg_openhmc_rf_status_init_c::type_id::create("status_init"); |
status_init.set_address('h8); |
add_register(status_init); |
control = reg_openhmc_rf_control_c::type_id::create("control"); |
control.set_address('h10); |
add_register(control); |
sent_p = reg_openhmc_rf_sent_p_c::type_id::create("sent_p"); |
sent_p.set_address('h18); |
add_register(sent_p); |
sent_np = reg_openhmc_rf_sent_np_c::type_id::create("sent_np"); |
sent_np.set_address('h20); |
add_register(sent_np); |
sent_r = reg_openhmc_rf_sent_r_c::type_id::create("sent_r"); |
sent_r.set_address('h28); |
add_register(sent_r); |
poisoned_packets = reg_openhmc_rf_poisoned_packets_c::type_id::create("poisoned_packets"); |
poisoned_packets.set_address('h30); |
add_register(poisoned_packets); |
rcvd_rsp = reg_openhmc_rf_rcvd_rsp_c::type_id::create("rcvd_rsp"); |
rcvd_rsp.set_address('h38); |
add_register(rcvd_rsp); |
counter_reset = reg_openhmc_rf_counter_reset_c::type_id::create("counter_reset"); |
counter_reset.set_address('h40); |
add_register(counter_reset); |
tx_link_retries = reg_openhmc_rf_tx_link_retries_c::type_id::create("tx_link_retries"); |
tx_link_retries.set_address('h48); |
add_register(tx_link_retries); |
errors_on_rx = reg_openhmc_rf_errors_on_rx_c::type_id::create("errors_on_rx"); |
errors_on_rx.set_address('h50); |
add_register(errors_on_rx); |
run_length_bit_flip = reg_openhmc_rf_run_length_bit_flip_c::type_id::create("run_length_bit_flip"); |
run_length_bit_flip.set_address('h58); |
add_register(run_length_bit_flip); |
error_abort_not_cleared = reg_openhmc_rf_error_abort_not_cleared_c::type_id::create("error_abort_not_cleared"); |
error_abort_not_cleared.set_address('h60); |
add_register(error_abort_not_cleared); |
endfunction : new |
|
endclass : rf_openhmc_rf_c |
|
/trunk/openHMC/sim/tb/common/src/rgm/openhmc/register_file_model_8x.sv
0,0 → 1,439
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// HMC controller status |
// |
class reg_openhmc_rf_status_general_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [7:0] lane_polarity_reversed_; |
bit [5:0] Reserved_0; |
bit [9:0] rx_tokens_remaining_; |
bit [5:0] Reserved_1; |
bit [9:0] hmc_tokens_remaining_; |
bit [5:0] Reserved_2; |
bit [0:0] phy_rx_ready_; |
bit [0:0] phy_tx_ready_; |
bit [2:0] Reserved_3; |
bit [0:0] lanes_reversed_; |
bit [0:0] FERR_N_; |
bit [0:0] sleep_mode_; |
bit [0:0] link_training_; |
bit [0:0] link_up_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_status_general_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_status_general_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
endfunction : new |
|
endclass : reg_openhmc_rf_status_general_c |
|
// |
// HMC controller initialization status |
// |
class reg_openhmc_rf_status_init_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [1:0] tx_init_state_; |
bit [2:0] rx_init_state_; |
bit [0:0] all_descramblers_aligned_; |
bit [7:0] Reserved_4; |
bit [7:0] descrambler_aligned_; |
bit [7:0] Reserved_5; |
bit [7:0] descrambler_part_aligned_; |
bit [7:0] Reserved_6; |
bit [7:0] lane_descramblers_locked_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_status_init_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_status_init_c"); |
super.new(name); |
this.name = name; |
set_address('h8); |
endfunction : new |
|
endclass : reg_openhmc_rf_status_init_c |
|
// |
// HMC controller control |
// |
class reg_openhmc_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [5:0] bit_slip_time_; |
bit [2:0] Reserved_7; |
bit [4:0] irtry_to_send_; |
bit [2:0] Reserved_8; |
bit [4:0] irtry_received_threshold_; |
bit [5:0] Reserved_9; |
bit [9:0] rx_token_count_; |
bit [4:0] Reserved_10; |
bit [0:0] debug_halt_on_tx_retry_; |
bit [0:0] debug_halt_on_error_abort_; |
bit [0:0] debug_dont_send_tret_; |
bit [1:0] Reserved_11; |
bit [0:0] run_length_enable_; |
bit [0:0] scrambler_disable_; |
bit [0:0] warm_reset_; |
bit [0:0] set_hmc_sleep_; |
bit [0:0] hmc_init_cont_set_; |
bit [0:0] p_rst_n_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h10); |
endfunction : new |
|
endclass : reg_openhmc_rf_control_c |
|
// |
// Posted requests sent to the HMC |
// |
class reg_openhmc_rf_sent_p_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_p_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_p_c"); |
super.new(name); |
this.name = name; |
set_address('h18); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_p_c |
|
// |
// Nonposted requests sent to the HMC |
// |
class reg_openhmc_rf_sent_np_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_np_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_np_c"); |
super.new(name); |
this.name = name; |
set_address('h20); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_np_c |
|
// |
// Read requests sent to the HMC |
// |
class reg_openhmc_rf_sent_r_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_sent_r_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_sent_r_c"); |
super.new(name); |
this.name = name; |
set_address('h28); |
endfunction : new |
|
endclass : reg_openhmc_rf_sent_r_c |
|
// |
// Count of packets that had data errors but valid flow information |
// |
class reg_openhmc_rf_poisoned_packets_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_poisoned_packets_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_poisoned_packets_c"); |
super.new(name); |
this.name = name; |
set_address('h30); |
endfunction : new |
|
endclass : reg_openhmc_rf_poisoned_packets_c |
|
// |
// Responses received from the HMC |
// |
class reg_openhmc_rf_rcvd_rsp_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [63:0] cnt_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_rcvd_rsp_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_rcvd_rsp_c"); |
super.new(name); |
this.name = name; |
set_address('h38); |
endfunction : new |
|
endclass : reg_openhmc_rf_rcvd_rsp_c |
|
// |
// Reset performance counters |
// |
class reg_openhmc_rf_counter_reset_c extends cag_rgm_register; |
|
typedef struct packed { |
bit rreinit_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_counter_reset_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_counter_reset_c"); |
super.new(name); |
this.name = name; |
set_address('h40); |
endfunction : new |
|
endclass : reg_openhmc_rf_counter_reset_c |
|
// |
// Count of re-transmit requests |
// |
class reg_openhmc_rf_tx_link_retries_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_tx_link_retries_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_tx_link_retries_c"); |
super.new(name); |
this.name = name; |
set_address('h48); |
endfunction : new |
|
endclass : reg_openhmc_rf_tx_link_retries_c |
|
// |
// Count of errors seen on RX |
// |
class reg_openhmc_rf_errors_on_rx_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_errors_on_rx_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_errors_on_rx_c"); |
super.new(name); |
this.name = name; |
set_address('h50); |
endfunction : new |
|
endclass : reg_openhmc_rf_errors_on_rx_c |
|
// |
// The number of bit_flips forced by the run length limiter |
// |
class reg_openhmc_rf_run_length_bit_flip_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_run_length_bit_flip_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_run_length_bit_flip_c"); |
super.new(name); |
this.name = name; |
set_address('h58); |
endfunction : new |
|
endclass : reg_openhmc_rf_run_length_bit_flip_c |
|
// |
// Indicates the number of error abort modes not cleared in time |
// |
class reg_openhmc_rf_error_abort_not_cleared_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [47:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_openhmc_rf_error_abort_not_cleared_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_openhmc_rf_error_abort_not_cleared_c"); |
super.new(name); |
this.name = name; |
set_address('h60); |
endfunction : new |
|
endclass : reg_openhmc_rf_error_abort_not_cleared_c |
|
class rf_openhmc_rf_c extends cag_rgm_register_file; |
|
rand reg_openhmc_rf_status_general_c status_general; |
rand reg_openhmc_rf_status_init_c status_init; |
rand reg_openhmc_rf_control_c control; |
rand reg_openhmc_rf_sent_p_c sent_p; |
rand reg_openhmc_rf_sent_np_c sent_np; |
rand reg_openhmc_rf_sent_r_c sent_r; |
rand reg_openhmc_rf_poisoned_packets_c poisoned_packets; |
rand reg_openhmc_rf_rcvd_rsp_c rcvd_rsp; |
rand reg_openhmc_rf_counter_reset_c counter_reset; |
rand reg_openhmc_rf_tx_link_retries_c tx_link_retries; |
rand reg_openhmc_rf_errors_on_rx_c errors_on_rx; |
rand reg_openhmc_rf_run_length_bit_flip_c run_length_bit_flip; |
rand reg_openhmc_rf_error_abort_not_cleared_c error_abort_not_cleared; |
|
`uvm_object_utils(rf_openhmc_rf_c) |
|
function new(string name="rf_openhmc_rf_c"); |
super.new(name); |
this.name = name; |
status_general = reg_openhmc_rf_status_general_c::type_id::create("status_general"); |
status_general.set_address('h0); |
add_register(status_general); |
status_init = reg_openhmc_rf_status_init_c::type_id::create("status_init"); |
status_init.set_address('h8); |
add_register(status_init); |
control = reg_openhmc_rf_control_c::type_id::create("control"); |
control.set_address('h10); |
add_register(control); |
sent_p = reg_openhmc_rf_sent_p_c::type_id::create("sent_p"); |
sent_p.set_address('h18); |
add_register(sent_p); |
sent_np = reg_openhmc_rf_sent_np_c::type_id::create("sent_np"); |
sent_np.set_address('h20); |
add_register(sent_np); |
sent_r = reg_openhmc_rf_sent_r_c::type_id::create("sent_r"); |
sent_r.set_address('h28); |
add_register(sent_r); |
poisoned_packets = reg_openhmc_rf_poisoned_packets_c::type_id::create("poisoned_packets"); |
poisoned_packets.set_address('h30); |
add_register(poisoned_packets); |
rcvd_rsp = reg_openhmc_rf_rcvd_rsp_c::type_id::create("rcvd_rsp"); |
rcvd_rsp.set_address('h38); |
add_register(rcvd_rsp); |
counter_reset = reg_openhmc_rf_counter_reset_c::type_id::create("counter_reset"); |
counter_reset.set_address('h40); |
add_register(counter_reset); |
tx_link_retries = reg_openhmc_rf_tx_link_retries_c::type_id::create("tx_link_retries"); |
tx_link_retries.set_address('h48); |
add_register(tx_link_retries); |
errors_on_rx = reg_openhmc_rf_errors_on_rx_c::type_id::create("errors_on_rx"); |
errors_on_rx.set_address('h50); |
add_register(errors_on_rx); |
run_length_bit_flip = reg_openhmc_rf_run_length_bit_flip_c::type_id::create("run_length_bit_flip"); |
run_length_bit_flip.set_address('h58); |
add_register(run_length_bit_flip); |
error_abort_not_cleared = reg_openhmc_rf_error_abort_not_cleared_c::type_id::create("error_abort_not_cleared"); |
error_abort_not_cleared.set_address('h60); |
add_register(error_abort_not_cleared); |
endfunction : new |
|
endclass : rf_openhmc_rf_c |
|
/trunk/openHMC/sim/tb/common/src/serdes/behavioral/serdes_behavioral.f
0,0 → 1,40
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
${OPENHMC_SIM}/tb/common/src/serdes/behavioral/deserializer.v |
${OPENHMC_SIM}/tb/common/src/serdes/behavioral/serializer.v |
/trunk/openHMC/sim/tb/common/src/serdes/behavioral/deserializer.v
0,0 → 1,113
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
module deserializer #( |
parameter LOG_DWIDTH=7, |
parameter DWIDTH=64 |
) |
( |
input wire clk, |
input wire res_n, |
input wire fast_clk, |
input wire bit_slip, |
input wire data_in, |
output wire [DWIDTH-1:0]data_out, |
input wire lane_polarity |
); |
|
reg [DWIDTH-1:0] tmp_buffer; |
reg [DWIDTH-1:0] buffer; |
reg [DWIDTH-1:0] buffer2; |
reg [DWIDTH-1:0] data_out_temp; |
reg [LOG_DWIDTH-1:0]curr_bit = 'h0; |
reg [5:0] bit_slip_cnt; |
reg bit_slip_done = 1'b0; |
|
reg d_in_dly; |
|
assign data_out = lane_polarity ? data_out_temp^{DWIDTH{1'b1}} : data_out_temp; |
|
// SEQUENTIAL PROCESS |
always @ (posedge fast_clk) begin |
if(!res_n) begin |
curr_bit <= {LOG_DWIDTH{1'b0}}; |
bit_slip_done <= 1'b0; |
end else begin |
|
#1ps d_in_dly <= data_in; |
|
if (!bit_slip || bit_slip_done) begin |
if(curr_bit == DWIDTH-1) begin |
curr_bit <= 0; |
end else begin |
curr_bit <= curr_bit + 1; |
end |
end |
|
if (bit_slip && !bit_slip_done) |
bit_slip_done <= 1'b1; |
|
if (bit_slip_done && !bit_slip) |
bit_slip_done <= 1'b0; |
|
if (|curr_bit == 1'b0) begin |
buffer <= tmp_buffer; |
end |
tmp_buffer[curr_bit] <= d_in_dly; |
end |
end |
|
always @ (posedge clk) begin |
if(!res_n) begin |
bit_slip_cnt <= 6'h0; |
end else begin |
if(bit_slip) |
bit_slip_cnt <= bit_slip_cnt + 1; |
|
buffer2 <= buffer; |
|
if(bit_slip_cnt < DWIDTH-1) begin |
data_out_temp <= buffer2; |
end else begin |
data_out_temp <= buffer; |
end |
end |
end |
|
endmodule |
|
/trunk/openHMC/sim/tb/common/src/serdes/behavioral/serializer.v
0,0 → 1,68
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
module serializer #( |
parameter DWIDTH=64 |
) |
( |
input wire clk, |
input wire fast_clk, |
input wire res_n, |
input wire [DWIDTH-1:0] data_in, |
output wire data_out |
); |
|
reg [7:0] curr_bit = 'h0; |
|
always @ (posedge fast_clk) |
begin |
if(!res_n) begin |
curr_bit <= 0; |
end else begin |
if(curr_bit == DWIDTH-1) |
curr_bit <= 0; |
else |
curr_bit <= curr_bit + 1; |
end |
end |
|
assign data_out = data_in[curr_bit]; |
|
endmodule |
|
/trunk/openHMC/sim/tb/common/src/bfm_2_hmc_monitor.sv
0,0 → 1,352
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef BFM_2_HMC |
`define BFM_2_HMC |
class bfm_2_hmc_mon extends hmc_module_mon; |
|
typedef enum { |
LENGTH_ERROR, |
CRC_ERROR, |
SEQ_ERROR, |
POISON |
}error_class_e; |
|
mailbox#(cls_pkt) in_mb; |
cls_pkt pkt; |
|
bit [2:0] seq_number = 0; |
|
bit bitstream[]; |
|
int phit_size = 64; |
bit [64:0] header; //-- phit size |
bit [64:0] tail ; //-- phit size |
int data_phit_count; |
|
int flit_size = 128; |
|
bit error_abort_mode = 0; |
int irtry_cnt = 0; |
|
int irtry = 0; |
|
|
hmc_link_config link_cfg; |
|
error_class_e current_error; |
hmc_command_encoding current_command; |
|
|
int lng_error = 0; |
int crc_error = 0; |
int seq_error = 0; |
int poisoned_pkt =0; |
|
int rsp_rcvd = 0; |
int err_rsp_rcvd = 0; |
int req_rcvd = 0; |
|
hmc_link_config hmc_link_cfg; |
|
`uvm_component_utils_begin(bfm_2_hmc_mon) |
`uvm_field_object(link_cfg, UVM_DEFAULT) |
`uvm_component_utils_end |
covergroup hmc_pkt_error_cg; |
option.per_instance = 1; |
ERROR_TYPE: coverpoint current_error; |
|
HMC_COMMAND: coverpoint current_command { |
//bins request_commands[] = |
bins flow_types[] = { |
HMC_TRET, |
HMC_PRET, |
HMC_NULL |
}; |
bins requests[] = { |
HMC_WRITE_16, |
HMC_WRITE_32, |
HMC_WRITE_48, |
HMC_WRITE_64, |
HMC_WRITE_80, |
HMC_WRITE_96, |
HMC_WRITE_112, |
HMC_WRITE_128, |
|
HMC_MODE_WRITE, |
HMC_BIT_WRITE, |
HMC_DUAL_8B_ADDI, |
HMC_SINGLE_16B_ADDI, |
|
HMC_POSTED_WRITE_16, |
HMC_POSTED_WRITE_32, |
HMC_POSTED_WRITE_48, |
HMC_POSTED_WRITE_64, |
HMC_POSTED_WRITE_80, |
HMC_POSTED_WRITE_96, |
HMC_POSTED_WRITE_112, |
HMC_POSTED_WRITE_128, |
HMC_POSTED_BIT_WRIT, |
|
HMC_POSTED_BIT_WRIT, |
HMC_POSTED_DUAL_8B_ADDI, |
HMC_POSTED_SINGLE_16B_ADDI, |
|
HMC_MODE_READ, |
HMC_READ_16, |
HMC_READ_32, |
HMC_READ_48, |
HMC_READ_64, |
HMC_READ_80, |
HMC_READ_96, |
HMC_READ_112, |
HMC_READ_128}; |
|
bins response[] = { |
HMC_READ_RESPONSE, |
HMC_WRITE_RESPONSE, |
HMC_MODE_READ_RESPONSE, |
HMC_MODE_WRITE_RESPONSE, |
HMC_ERROR_RESPONSE |
}; |
|
illegal_bins n_used = default; |
} |
CROSS_ERROR_TYPPE_COMMAND : cross ERROR_TYPE, HMC_COMMAND; |
|
endgroup |
|
function new ( string name="bfm_2_hmc_mon", uvm_component parent ); |
super.new(name, parent); |
hmc_pkt_cg = new(); |
hmc_pkt_error_cg = new(); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if (!uvm_config_db#(hmc_link_config)::get(this, "", "link_cfg", link_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("hmc_link_config not set via config_db")); |
end |
endfunction : build_phase |
|
task run(); |
cls_pkt old_pkt; |
`uvm_info(get_type_name(),$psprintf("starting BFM_2_HMC converter"), UVM_MEDIUM) |
forever begin |
//mb_pkt.get(pkt); |
old_pkt = pkt; |
in_mb.peek(pkt); |
if (pkt != old_pkt) |
extract_hmc_pkt(pkt); |
else |
#5; |
end |
|
endtask |
|
task extract_hmc_pkt(cls_pkt pkt); |
header = pkt.get_header(); |
tail = pkt.get_tail(); |
data_phit_count = pkt.data.size(); //-- 7 flits->14 phits --> 14-2 =12 data_phits |
|
bitstream = new [2*phit_size + data_phit_count*phit_size]; |
|
//-- generate Bitstream |
|
if (header !=64'b0) begin |
|
//-- check length |
if( (header[10:7] != header[14:11]) || (header[10:7] != 1+data_phit_count /2)) begin |
lng_error ++; |
error_abort_mode = 1; |
`uvm_info(get_type_name(),$psprintf("Set error abort mode: LNG/DLN ERROR, Command with header: %h", header), UVM_NONE) |
irtry_cnt = 0; |
|
|
current_error = LENGTH_ERROR; |
current_command[5:0] = header[5:0]; |
hmc_pkt_error_cg.sample(); |
end else begin |
|
//-- convert the cls_pkt pkt to hmc_packet packet |
cls_pkt_to_hmc_packet(pkt); |
|
//-- check crc error |
check_crc_error(packet); |
|
|
//-- wait for irtry |
if (error_abort_mode) |
clear_error_abort_mode(); |
|
else begin |
|
//-- count Start Error Mode IRTRY |
if (packet.start_retry) begin |
irtry++; |
`uvm_info(get_type_name(),$psprintf("Start Retry: %0d", irtry), UVM_HIGH) |
end |
|
//-- packet sequence check |
if ((packet.command == HMC_TRET) || (packet.get_command_type() != HMC_FLOW_TYPE)) begin |
irtry = 0; //-- reset start retry mode counter |
|
if (packet.sequence_number != seq_number+1'b1) begin |
seq_error ++; |
error_abort_mode = 1; |
`uvm_info(get_type_name(),$psprintf("Set error abort mode: SEQ ERROR, Command: %s", packet.command.name()), UVM_NONE) |
irtry_cnt = 0; |
|
|
//-- sample seq error |
current_error = SEQ_ERROR; |
current_command = packet.command; |
hmc_pkt_error_cg.sample(); |
|
end else begin |
|
seq_number = packet.sequence_number; |
|
//-- check if poisoned |
if ( packet.poisoned) begin |
poisoned_pkt++; |
|
//-- sample poison |
current_error = POISON; |
current_command = packet.command; |
hmc_pkt_error_cg.sample(); |
end else |
if((packet.get_command_type() != HMC_FLOW_TYPE)) |
write_packet(packet); |
end |
end |
end |
end |
end |
|
endtask : extract_hmc_pkt |
|
|
|
function void check_crc_error(hmc_packet packet); |
if (packet.crc_error) begin |
crc_error++; |
error_abort_mode = 1; |
`uvm_info(get_type_name(),$psprintf("Set error abort mode: CRC ERROR, Command: %s", packet.command.name()), UVM_NONE) |
irtry_cnt = 0; |
|
current_error = CRC_ERROR; |
current_command = packet.command; |
hmc_pkt_error_cg.sample(); |
end |
endfunction : check_crc_error |
|
function void clear_error_abort_mode(); |
if ((packet.clear_error_abort)) begin |
`uvm_info(get_type_name(), $psprintf("Clear Error Abort Mode: %0d",irtry_cnt ), UVM_HIGH) |
irtry_cnt ++; |
end else begin |
irtry_cnt = 0; //-- reset counter |
end |
|
if (irtry_cnt >= link_cfg.cfg_init_retry_rxcnt) begin //-- test threshold |
error_abort_mode = 0; |
`uvm_info(get_type_name(), $psprintf("Clear Error Abort Mode" ), UVM_NONE) |
end |
endfunction : clear_error_abort_mode |
|
|
function void cls_pkt_to_hmc_packet (cls_pkt pkt); |
//-- Convert the CLS_PKT to HMC_PKT |
for (int b = 0; b < 64; b++) begin //-- read header to bitmap |
bitstream[b]=header[b]; |
end |
|
if (data_phit_count > 0) |
for (int phit = 0; phit < data_phit_count; phit++) //-- read data to bitmap |
for (int b = 0; b < phit_size; b++) |
bitstream[(phit + 1) * phit_size + b] = pkt.data[phit][b]; |
|
for (int b = 0; b < 64; b++) begin //-- read tail to bitmap |
bitstream[(data_phit_count+1)*phit_size+b]=tail[b]; |
end |
|
//-- create hmc packet |
`uvm_info(get_type_name(),$psprintf("Got a BFM Packet: %s",pkt.convert2string()), UVM_HIGH) |
packet = hmc_packet::type_id::create("packet", this); |
void'(packet.unpack(bitstream)); |
|
endfunction : cls_pkt_to_hmc_packet |
|
task write_packet(hmc_packet packet); |
|
if(packet.get_command_type() == HMC_RESPONSE_TYPE)begin |
if(packet.command != HMC_ERROR_RESPONSE) begin |
`uvm_info(get_type_name(),$psprintf("Rsp #%0d : %s",rsp_rcvd, packet.command.name()), UVM_HIGH) |
`uvm_info(get_type_name(),$psprintf("Rsp #%0d : %s",rsp_rcvd, packet.sprint()), UVM_HIGH) |
rsp_rcvd++; |
end else begin |
`uvm_info(get_type_name(),$psprintf("Err Rsp %0d : %s with error code %b",err_rsp_rcvd, packet.command.name(), packet.error_status), UVM_HIGH) |
err_rsp_rcvd++; |
end |
end else begin |
`uvm_info(get_type_name(),$psprintf("Req %0d : %s",req_rcvd, packet.command.name()), UVM_HIGH) |
req_rcvd++; |
end |
|
|
hmc_pkt_cg.sample(); |
|
item_collected_port.write(packet); |
|
endtask : write_packet |
|
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("LNG error count %0d", lng_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("CRC error count %0d", crc_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("SEQ error count %0d", seq_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("poisoned packets %0d", poisoned_pkt), UVM_NONE) |
endfunction : report_phase |
|
endclass |
|
|
`endif |
/trunk/openHMC/sim/tb/common/src/hmc_req_packet.sv
0,0 → 1,111
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// hmc_req_packet |
// |
|
// Only requests should be sent to test the controller |
// All of the tail fields should be zero |
|
`ifndef HMC_REQ_PACKET_SV |
`define HMC_REQ_PACKET_SV |
|
class hmc_req_packet extends hmc_packet; |
`uvm_object_utils(hmc_req_packet) |
|
constraint req_command_c { |
command inside { HMC_WRITE_16, |
HMC_WRITE_32, |
HMC_WRITE_48, |
HMC_WRITE_64, |
HMC_WRITE_80, |
HMC_WRITE_96, |
HMC_WRITE_112, |
HMC_WRITE_128, |
|
//HMC_MODE_WRITE, |
HMC_BIT_WRITE, |
HMC_DUAL_8B_ADDI, |
HMC_SINGLE_16B_ADDI, |
|
HMC_POSTED_WRITE_16, |
HMC_POSTED_WRITE_32, |
HMC_POSTED_WRITE_48, |
HMC_POSTED_WRITE_64, |
HMC_POSTED_WRITE_80, |
HMC_POSTED_WRITE_96, |
HMC_POSTED_WRITE_112, |
HMC_POSTED_WRITE_128, |
HMC_POSTED_BIT_WRIT, |
|
HMC_POSTED_BIT_WRIT, |
HMC_POSTED_DUAL_8B_ADDI, |
HMC_POSTED_SINGLE_16B_ADDI, |
|
// HMC_MODE_READ, |
HMC_READ_16, |
HMC_READ_32, |
HMC_READ_48, |
HMC_READ_64, |
HMC_READ_80, |
HMC_READ_96, |
HMC_READ_112, |
HMC_READ_128 |
|
}; |
} |
|
|
constraint c_zero_tail_fields { |
return_token_count == 0; |
sequence_number == 0; |
forward_retry_pointer == 0; |
return_retry_pointer == 0; |
packet_crc == 0; |
} |
|
function new (string name = "hmc_req_packet"); |
super.new(name); |
endfunction : new |
|
endclass : hmc_req_packet |
|
`endif // HMC_REQ_PACKET_SV |
|
/trunk/openHMC/sim/tb/common/src/hmc_2_axi4_sequence.sv
0,0 → 1,304
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// hmc_2_axi4_sequence |
// |
// |
|
`ifndef HMC_2_AXI4_SEQUENCE_SV |
`define HMC_2_AXI4_SEQUENCE_SV |
|
class hmc_2_axi4_sequence #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_sequence #(axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))); |
|
int unsigned num_packets = 1; //-- packets to generate |
int unsigned max_pkts_per_cycle = 4; //-- maximum packets in single AXI4 cycle |
|
|
rand hmc_req_packet hmc_items[]; |
hmc_packet hmc_packets_ready[$]; |
|
int working_pos = 0; |
|
|
typedef bit [1+1+1+127:0] tail_header_flit_t; |
tail_header_flit_t flit_queue[$]; |
rand int tag = 0; |
|
constraint tag_value_c { |
tag >= 0; |
tag < 512; |
} |
|
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH)) axi4_queue[$]; |
|
`uvm_object_param_utils_begin(hmc_2_axi4_sequence #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_int(num_packets, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(max_pkts_per_cycle, UVM_DEFAULT | UVM_DEC) |
`uvm_object_utils_end |
|
`uvm_declare_p_sequencer(hmc_2_axi4_sequencer #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH))) |
|
|
function new(string name="hmc_2_axi4_sequence"); |
super.new(name); |
|
endfunction : new |
|
function void pre_randomize (); |
super.pre_randomize(); |
|
hmc_items = new[num_packets]; |
|
foreach (hmc_items[i]) begin |
hmc_items[i] = hmc_req_packet::type_id::create($psprintf("hmc_item[%0d]", i) ); |
end |
|
`uvm_info(get_type_name(),$psprintf("%0d HMC packets generated", num_packets), UVM_HIGH) |
endfunction : pre_randomize |
|
function void pack_hmc_packet(hmc_packet pkt); |
bit bitstream[]; |
tail_header_flit_t tmp_flit; |
|
int unsigned bitcount; |
int unsigned packet_count=1; |
|
bitcount = pkt.pack(bitstream); |
|
pkt_successfully_packed : assert (bitcount > 0); |
|
//-- For each FLIT in the packet, add the flit entry |
for (int f=0; f<bitcount/128; f++) begin |
for (int i=0; i< 128; i++) |
tmp_flit[i] = bitstream[f*128+i]; |
|
tmp_flit[128] = (f==0); //-- Header |
|
tmp_flit[129] = (f==bitcount/128-1); //-- Tail |
|
tmp_flit[130] = 1'b1; //-- Flit is valid |
|
flit_queue.push_back(tmp_flit); |
end |
endfunction : pack_hmc_packet |
|
function void hmc_packet_2_axi_cycles(); |
|
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH)) axi4_item; |
|
int unsigned FPW = DATA_BYTES/16; //--FPW: desired Data width in Flits (HMC packet length) valid: 4.6.8 databytes= tdata_width /8 fpw = tdata_width /128 |
int unsigned HEADERS = 1*FPW; |
int unsigned TAILS = 2*FPW; |
int unsigned VALIDS = 0; |
|
int unsigned pkts_in_cycle = 0; //-- HMC tails inserted in current AXI4 cycle |
int unsigned header_in_cycle = 0; //-- HMC headers inserted in current AXI4 cycle |
int unsigned valids_in_cycle = 0; |
hmc_packet hmc_pkt; |
|
|
int flit_offset=0; //-- flit offset First flit-> create new axi_item |
tail_header_flit_t current_flit; |
tail_header_flit_t next_flit; |
|
|
//-- create empty vc |
`uvm_create_on(axi4_item, p_sequencer) |
axi4_item.tdata = 0; |
axi4_item.tuser = 0; |
axi4_item.delay = hmc_packets_ready[0].flit_delay / FPW; //-- measured in flits |
|
while (hmc_packets_ready.size() >0 ) begin |
hmc_pkt = hmc_packets_ready.pop_front(); |
pack_hmc_packet(hmc_pkt); |
|
|
//-- write flits 2 axi4_queue |
while( flit_queue.size > 0 ) begin //-- flit queue contains flits |
|
|
current_flit = flit_queue.pop_front(); |
|
if (current_flit[128]) begin //-- If current flit is header |
flit_offset += hmc_pkt.flit_delay; |
end |
|
//-- check if axi4_item is full |
if ((flit_offset >= FPW) || pkts_in_cycle == max_pkts_per_cycle ) begin |
//-- push full axi item to axi4_queue |
`uvm_info(get_type_name(),$psprintf("axi4_item is full (offset = %0d), writing element %0d to queue ", flit_offset, axi4_queue.size()), UVM_MEDIUM) |
|
if (valids_in_cycle != 0) |
axi4_queue.push_back(axi4_item); |
|
//-- create new AXI4 cycle |
`uvm_create_on(axi4_item, p_sequencer) |
axi4_item.tdata = 0; |
axi4_item.tuser = 0; |
|
//-- set AXI4 cycle delay |
axi4_item.delay = (flit_offset / FPW) -1; //-- flit offset contains also empty flits |
if (flit_offset % FPW >0) |
axi4_item.delay += 1; |
|
//-- reset counter |
`uvm_info(get_type_name(),$psprintf("HMC Packets in last cycle: %0d, %0d", pkts_in_cycle, header_in_cycle), UVM_HIGH) |
pkts_in_cycle = 0; //-- reset HMC packet counter in AXI4 Cycle |
header_in_cycle = 0; |
valids_in_cycle = 0; |
`uvm_info(get_type_name(),$psprintf("axi_delay is %0d", axi4_item.delay), UVM_MEDIUM) |
|
//-- reset flit_offset |
flit_offset = 0; |
end |
|
//-- write flit to axi4_item |
for (int i =0;i<128;i++) begin |
axi4_item.tdata[(flit_offset*128)+i] = current_flit[i]; |
end |
|
//-- Write tuser flags |
//-- write valid |
axi4_item.tuser[VALIDS +flit_offset] = current_flit[130]; //-- valid [fpw-1:0] |
//-- write header |
axi4_item.tuser[HEADERS +flit_offset] = current_flit[128]; //-- only 1 if header |
//-- write tail |
axi4_item.tuser[TAILS +flit_offset] = current_flit[129]; //-- only 1 if tail |
|
valids_in_cycle ++; |
|
|
if(current_flit[129]) begin //-- count tails in current cycle |
pkts_in_cycle ++; |
end |
|
if(current_flit[128]) begin //-- count headers in current cycle |
header_in_cycle ++; |
end |
|
//-- debugging output |
if(current_flit[128]) begin |
`uvm_info(get_type_name(),$psprintf("FLIT is header at pos %d", flit_offset), UVM_MEDIUM) |
end |
if(current_flit[129]) begin |
`uvm_info(get_type_name(),$psprintf("FLIT is tail at pos %d", flit_offset), UVM_MEDIUM) |
end |
|
flit_offset++; |
end |
end |
//-- push last axi4_item to axi4_queue |
axi4_queue.push_back(axi4_item); |
|
endfunction : hmc_packet_2_axi_cycles |
|
|
task aquire_tags(); |
for (int i = working_pos; i < hmc_items.size(); i++) begin //-- get a tag for each packet |
//-- only register a tag if response required! |
if (hmc_items[i].get_command_type() == HMC_WRITE_TYPE || |
hmc_items[i].get_command_type() == HMC_MISC_WRITE_TYPE || |
hmc_items[i].get_command_type() == HMC_READ_TYPE || |
hmc_items[i].get_command_type() == HMC_MODE_READ_TYPE) |
begin |
p_sequencer.handler.get_tag(tag); |
end else begin |
tag = 0; |
end |
|
hmc_items[i].tag = tag; |
|
//-- move packet to ready queue if tag valid |
if (tag >= 0) begin |
|
`uvm_info(get_type_name(),$psprintf("Tag for HMC Packet Type %0d is: %0d", hmc_items[i].get_command_type(), hmc_items[i]), UVM_HIGH) |
hmc_packets_ready.push_back(hmc_items[i]); |
working_pos = i+1; |
end else begin |
break; //-- send all already processed AXI4 Cycles if tag_handler can not provide an additional tag |
end |
end |
|
endtask : aquire_tags |
|
task send_axi4_cycles(); |
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH)) axi4_item; |
while( axi4_queue.size() > 0 ) begin |
`uvm_info(get_type_name(),$psprintf("axi4_queue contains %0d items", axi4_queue.size()), UVM_MEDIUM) |
|
axi4_item = axi4_queue.pop_front(); |
|
if ((axi4_item.tuser == {{(TUSER_WIDTH){1'b0}}})) begin |
axi4_item.print(); |
`uvm_fatal("AXI4_Master_Driver", "sent an empty cycle") |
end |
`uvm_send(axi4_item); |
|
`uvm_info(get_type_name(),$psprintf("\n%s", axi4_item.sprint()), UVM_HIGH) |
end |
|
|
endtask : send_axi4_cycles |
|
task body(); |
|
`uvm_info(get_type_name(),$psprintf("HMC Packets to send: %0d", hmc_items.size()), UVM_MEDIUM) |
|
while (hmc_items.size-1 >= working_pos)begin //-- cycle until all hmc_packets have been sent |
//-- try to aquire a tag for each non posted packet |
aquire_tags(); |
|
//-- send all packets with tags |
if (hmc_packets_ready.size()>0) begin |
|
//-- generate axi4_queue |
hmc_packet_2_axi_cycles(); |
|
//-- send axi4_queue |
send_axi4_cycles(); |
end |
end |
endtask : body |
|
endclass : hmc_2_axi4_sequence |
|
`endif // HMC_2_AXI4_SEQUENCE_SV |
|
/trunk/openHMC/sim/tb/common/src/hmc_2_axi4_sequencer.sv
0,0 → 1,70
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
// |
// |
// hmc_2_axi4_sequencer |
// |
// |
|
`ifndef HMC_2_AXI4_SEQUENCER_SV |
`define HMC_2_AXI4_SEQUENCER_SV |
|
typedef class hmc_2_axi4_sequence; |
|
class hmc_2_axi4_sequencer #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends axi4_stream_master_sequencer #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)); |
|
tag_handler handler; //-- a tag handler is used to handle tags of non posted packets |
|
`uvm_component_param_utils_begin(hmc_2_axi4_sequencer #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(handler, UVM_DEFAULT) |
`uvm_component_utils_end |
function new (string name = "hmc_2_axi4_sequencer", uvm_component parent); |
super.new(name, parent); |
|
endfunction : new |
|
|
function void build_phase(uvm_phase phase); |
handler = tag_handler::type_id::create("handler", this); |
endfunction : build_phase |
endclass : hmc_2_axi4_sequencer |
|
`endif // HMC_2_AXI4_SEQUENCER_SV |
|
/trunk/openHMC/sim/tb/uvc/build/ncsim.tcl
0,0 → 1,23
database -open waves -into waves.shm -default |
|
probe -create tb_top.dut_I -depth all -tasks -functions -all -database waves |
probe -create tb_top.dut_I.openhmc_instance.rx_link_I -all -database waves -memories |
probe -create tb_top.dut_I.openhmc_instance.tx_link_I -all -database waves -memories |
|
probe -create tb_top.axi4_hmc_rsp_if -all -database waves |
probe -create tb_top.axi4_hmc_req_if -all -database waves |
probe -create tb_top.hmc_if -all -database waves |
probe -create tb_top.hmc_int_if -all -database waves |
|
|
set assert_output_stop_level failed |
set assert_report_incompletes 0 |
|
#-- enable IDA probes |
#ida_database -open -name=ida.db -compress |
#ida_probe -log=on |
#ida_probe -wave=on |
#ida_probe -sv_flow=on |
|
run |
|
/trunk/openHMC/sim/tb/uvc/build/compile_ius_openhmc_behavioral_uvc.f
0,0 → 1,53
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# openHMC - An Open Source Hybrid Memory Cube Controller |
# (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
# www.ziti.uni-heidelberg.de |
# B6, 26 |
# 68159 Mannheim |
# Germany |
# |
# Contact: openhmc@ziti.uni-heidelberg.de |
# http://ra.ziti.uni-heidelberg.de/openhmc |
# |
# This source file is free software: you can redistribute it and/or modify |
# it under the terms of the GNU Lesser General Public License as published by |
# the Free Software Foundation, either version 3 of the License, or |
# (at your option) any later version. |
# |
# This source file is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public License |
# along with this source file. If not, see <http://www.gnu.org/licenses/>. |
# |
# |
|
+define+HMC_UVC |
|
###Include Sources |
#Behavioral serializer and routing models |
-f ${OPENHMC_SIM}/tb/common/src/serdes/behavioral/serdes_behavioral.f |
|
#Source top TB, HW, and DUT |
+incdir+${OPENHMC_SIM}/UVC/hmc/sv |
+incdir+${OPENHMC_SIM}/tb/uvc/src |
-f ${OPENHMC_SIM}/tb/common/build/compile_tb_openhmc.f |
+incdir+${OPENHMC_SIM}/tb/uvc/testlib |
-f ${OPENHMC_SIM}/tb/common/build/compile_hw_openhmc.f |
#${OPENHMC_SIM}/tb/uvc/src/hmc_tb.sv |
${OPENHMC_SIM}/tb/uvc/src/tb_top.sv |
${OPENHMC_SIM}/tb/uvc/src/targets/dut_openhmc_behavioral_uvc.sv |
/trunk/openHMC/sim/tb/uvc/testlib/hmc_base_test.sv
0,0 → 1,152
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef hmc_BASE_TEST_SV |
`define hmc_BASE_TEST_SV |
|
class hmc_base_test extends uvm_test; |
|
hmc_tb hmc_tb0; |
axi4_stream_config axi4_req_config; |
axi4_stream_config axi4_rsp_config; |
|
hmc_link_config link_cfg; |
//hmc_link_config link_cfg; |
|
uvm_table_printer printer; |
|
function new(string name="hmc_base_test", uvm_component parent=null); |
super.new(name,parent); |
endfunction : new |
|
virtual function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
//-- create config |
|
|
//-- AXI4 request config |
axi4_req_config = axi4_stream_config::type_id::create("axi4_req_config", this); |
axi4_req_config.master_active = UVM_ACTIVE; |
axi4_req_config.slave_active = UVM_PASSIVE; |
axi4_req_config.open_rsp_mode = UVM_PASSIVE; |
|
uvm_report_info(get_type_name(), $psprintf("Setting the axi4_req config:\n"), UVM_LOW); |
uvm_config_db#(axi4_stream_config)::set(this, "hmc_tb0", "axi4_req_config", axi4_req_config); |
|
//-- AXI4 response config |
axi4_rsp_config = axi4_stream_config::type_id::create("axi4_rsp_config", this); |
axi4_rsp_config.master_active = UVM_PASSIVE; |
axi4_rsp_config.slave_active = UVM_ACTIVE; |
axi4_rsp_config.open_rsp_mode = `OPEN_RSP_MODE==1 ? UVM_ACTIVE : UVM_PASSIVE; |
|
uvm_report_info(get_type_name(), $psprintf("Setting the axi4_rsp config:\n"), UVM_LOW); |
uvm_config_db#(axi4_stream_config)::set(this, "hmc_tb0", "axi4_rsp_config", axi4_rsp_config); |
|
//-- HMC link config |
link_cfg = hmc_link_config::type_id::create("link_config", this); |
|
link_cfg.cfg_rsp_open_loop = `OPEN_RSP_MODE==1 ? UVM_ACTIVE : UVM_PASSIVE; |
link_cfg.fpw = `FPW; |
|
//-- hmc_uvc_config |
link_cfg.requester.width = 2**`LOG_NUM_LANES; |
link_cfg.requester.active = UVM_PASSIVE;//`HMC_REQUESTER_IS_ACTIVE; |
link_cfg.requester.requester = 1; |
|
link_cfg.responder.width = 2**`LOG_NUM_LANES; |
link_cfg.responder.active = UVM_ACTIVE;//`HMC_RESPONDER_IS_ACTIVE; |
link_cfg.responder.requester = 0; |
|
link_cfg_randomize : assert (link_cfg.randomize()); |
|
uvm_report_info(get_type_name(), $psprintf("Setting the hmc uvc link config:\n"), UVM_LOW); |
uvm_config_db#(hmc_link_config)::set(this, "hmc_tb0", "link_cfg", link_cfg); |
|
|
set_config_int("*", "recording_detail", UVM_FULL); |
|
//-- create the testbench |
hmc_tb0 = hmc_tb#()::type_id::create("hmc_tb0", this); |
|
|
endfunction : build_phase |
|
function void end_of_elaboration_phase(uvm_phase phase); |
super.end_of_elaboration_phase(phase); |
printer = new(); |
printer.knobs.depth = 5; |
|
`uvm_info(get_type_name(), $psprintf("Printing hmc_config: %s",link_cfg.sprint()), UVM_NONE) |
`uvm_info(get_type_name(), $psprintf("Printing Requester Link config: %s", link_cfg.requester.sprint()), UVM_NONE) |
`uvm_info(get_type_name(), $psprintf("Printing Responder Link config: %s", link_cfg.responder.sprint()), UVM_NONE) |
uvm_report_info(get_type_name(), $psprintf("Printing the test topology :\n%s", this.sprint(printer)), UVM_HIGH); |
|
endfunction : end_of_elaboration_phase |
|
|
virtual task run_phase(uvm_phase phase); |
phase.phase_done.set_drain_time(this, 10us); |
endtask : run_phase |
|
endclass : hmc_base_test |
|
|
class hmc_base_seq extends uvm_sequence; |
|
function new(string name="hmc_base_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(hmc_base_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
virtual task pre_body(); |
if(starting_phase != null) |
starting_phase.raise_objection(this); |
endtask : pre_body |
|
virtual task post_body(); |
if(starting_phase != null) |
starting_phase.drop_objection(this); |
endtask : post_body |
|
endclass : hmc_base_seq |
|
`endif // hmc_BASE_TEST_SV |
/trunk/openHMC/sim/tb/uvc/testlib/hmc_model_init_seq.sv
0,0 → 1,61
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef HMC_MODEL_INIT_SEQ |
`define HMC_MODEL_INIT_SEQ |
|
class hmc_model_init_seq extends hmc_base_seq; |
|
function new(string name="hmc_model_init_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(hmc_model_init_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
task body(); |
|
`uvm_info(get_type_name(), $psprintf("HMC_Token Count is: %d", p_sequencer.link_cfg.hmc_tokens), UVM_NONE) |
`uvm_info(get_type_name(), $psprintf("RX_Token Count is: %d", p_sequencer.link_cfg.rx_tokens), UVM_NONE) |
|
endtask : body |
|
endclass : hmc_model_init_seq |
|
`endif // HMC_MODEL_INIT_SEQ |
/trunk/openHMC/sim/tb/uvc/testlib/openhmc_init_seq.sv
0,0 → 1,143
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef OPENHMC_INIT_SEQ |
`define OPENHMC_INIT_SEQ |
|
class openhmc_init_seq extends hmc_base_seq; |
|
// hmc_link_config link_config; |
|
function new(string name="openhmc_init_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(openhmc_init_seq) |
`uvm_declare_p_sequencer(vseqr) |
|
bit phy_tx_ready = 1'b0; |
bit phy_rx_ready = 1'b0; |
bit link_up = 1'b0; |
int timeout = 0; |
int delay; |
|
task body(); |
|
//-- configure the HMC controller |
reg_openhmc_rf_control_c control; |
reg_openhmc_rf_status_general_c status; |
reg_openhmc_rf_status_init_c status_init; |
reg_openhmc_rf_counter_reset_c cnt_reset; |
|
`uvm_info(get_type_name(), "Running init sequence", UVM_NONE) |
|
$cast(control,p_sequencer.rf_seqr_hmc.get_by_name("control")); |
control.set_check_on_read(1'b0); |
p_sequencer.rf_seqr_hmc.read_reg(control); |
|
control.fields.rx_token_count_ = p_sequencer.link_cfg.rx_tokens; |
control.fields.scrambler_disable_ = ~p_sequencer.link_cfg.scramblers_enabled; |
control.fields.bit_slip_time_ = 40; |
control.fields.set_hmc_sleep_ = 0; |
control.fields.run_length_enable_ = ~p_sequencer.link_cfg.scramblers_enabled; |
control.fields.irtry_to_send_ = p_sequencer.link_cfg.requester.irtry_flit_count_to_send; |
control.fields.irtry_received_threshold_ = p_sequencer.link_cfg.requester.irtry_flit_count_received_threshold; |
|
p_sequencer.rf_seqr_hmc.write_reg(control); |
|
//Dummy Read to status init |
$cast(status_init,p_sequencer.rf_seqr_hmc.get_by_name("status_init")); |
status_init.set_check_on_read(1'b0); |
p_sequencer.rf_seqr_hmc.read_reg(status_init); |
|
//Dummy counter reset |
$cast(cnt_reset,p_sequencer.rf_seqr_hmc.get_by_name("counter_reset")); |
cnt_reset.fields.rreinit_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(cnt_reset); |
|
//-- Wait until the PHY is out of reset |
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
while (phy_tx_ready == 1'b0) |
begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
phy_tx_ready = status.fields.phy_tx_ready_; |
`uvm_info(get_type_name(), "Waiting for the PHY TX to get ready", UVM_NONE) |
end |
`uvm_info(get_type_name(), "Phy TX ready", UVM_NONE) |
|
//------------------------------------------------------- Set Reset and Init Continue |
control.fields.p_rst_n_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
#1us; |
|
control.fields.hmc_init_cont_set_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
`uvm_info(get_type_name(), "Init cont in RF set", UVM_NONE) |
|
//------------------------------------------------------- Wait for the PHY to get ready |
while (phy_rx_ready == 1'b0) |
begin |
#1us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
phy_rx_ready = status.fields.phy_rx_ready_; |
`uvm_info(get_type_name(), "Waiting for PHY RX to get ready", UVM_NONE) |
end |
`uvm_info(get_type_name(), "Phy RX is ready", UVM_NONE) |
|
//-- Poll on link_up to make sure that it comes up. |
while (link_up == 1'b0) |
begin |
if (timeout == 8000) //-- Try Resetting it. |
begin |
`uvm_fatal(get_type_name(), "The link didn't come up...") |
end |
#4ns; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
link_up = status.fields.link_up_; |
timeout = timeout + 1; |
end |
`uvm_info(get_type_name(), "Link is UP !", UVM_NONE) |
|
endtask : body |
|
endclass : openhmc_init_seq |
|
`endif // OPENHMC_INIT_SEQ |
/trunk/openHMC/sim/tb/uvc/src/hmc_tb.sv
0,0 → 1,202
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef hmc_TB_SV |
`define hmc_TB_SV |
|
class hmc_tb #( parameter AXI4_DATA_BYTES=`AXI4BYTES, parameter AXI4_TUSER_WIDTH=`AXI4BYTES, parameter NUM_LANES=2**`LOG_NUM_LANES) extends uvm_env; |
//-- UVCs |
|
axi4_stream_env #( |
.DATA_BYTES(AXI4_DATA_BYTES), |
.TUSER_WIDTH(AXI4_TUSER_WIDTH) |
|
) axi4_req; |
|
axi4_stream_env #( |
.DATA_BYTES(AXI4_DATA_BYTES), |
.TUSER_WIDTH(AXI4_TUSER_WIDTH) |
|
) axi4_rsp; |
|
hmc_env # (.NUM_LANES(NUM_LANES))hmc; |
|
hmc_module_env hmc_module; |
|
axi4_stream_config axi4_rsp_config; |
axi4_stream_config axi4_req_config; |
|
hmc_link_config link_cfg; |
|
cag_rgm_rfs_env #( |
.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH) |
) rfs_hmc_I; |
|
rf_openhmc_rf_c rf_model_hmc; |
|
vseqr v_seqr; |
|
int i = 2; |
|
`uvm_component_param_utils(hmc_tb #(.AXI4_DATA_BYTES(AXI4_DATA_BYTES), .AXI4_TUSER_WIDTH(AXI4_TUSER_WIDTH), .NUM_LANES(NUM_LANES) )) |
|
function new (string name="hmc_tb", uvm_component parent=null); |
super.new(name,parent); |
endfunction : new |
|
virtual function void build_phase(uvm_phase phase); |
|
//-- factory overrides |
|
set_inst_override_by_type("axi4_req.master.sequencer", |
axi4_stream_master_sequencer #( .DATA_BYTES(AXI4_DATA_BYTES), .TUSER_WIDTH(AXI4_TUSER_WIDTH) |
)::get_type(), |
hmc_2_axi4_sequencer #( .DATA_BYTES(AXI4_DATA_BYTES), |
.TUSER_WIDTH(AXI4_TUSER_WIDTH) |
)::get_type() |
|
); |
|
set_inst_override_by_type("hmc_module.axi4_req_mon", |
hmc_module_mon::get_type(), |
axi4_stream_hmc_monitor #( .DATA_BYTES(AXI4_DATA_BYTES), |
.TUSER_WIDTH(AXI4_TUSER_WIDTH))::get_type() |
|
); |
set_inst_override_by_type("hmc_module.axi4_rsp_mon", |
hmc_module_mon::get_type(), |
axi4_stream_hmc_monitor #( .DATA_BYTES(AXI4_DATA_BYTES), |
.TUSER_WIDTH(AXI4_TUSER_WIDTH))::get_type() |
|
); |
|
super.build_phase(phase); |
|
//-- deploy configuration |
if (!uvm_config_db#(axi4_stream_config)::get(this, "", "axi4_req_config", axi4_req_config)) begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_config not set via config_db")); |
end else begin |
uvm_config_db#(axi4_stream_config)::set(this, "axi4_req", "axi4_stream_cfg", axi4_req_config); |
end |
|
if (!uvm_config_db#(axi4_stream_config)::get(this, "", "axi4_rsp_config", axi4_rsp_config)) begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_config not set via config_db")); |
end else begin |
uvm_config_db#(axi4_stream_config)::set(this, "axi4_rsp", "axi4_stream_cfg", axi4_rsp_config); |
end |
|
|
//hmc link uvc |
if (!uvm_config_db#(hmc_link_config)::get(this, "", "link_cfg", link_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("hmc_link_uvc_config not set via config_db")); |
end else begin |
uvm_config_db#(hmc_link_config)::set(this, "v_seqr", "link_cfg", link_cfg); |
|
uvm_config_db#(hmc_link_config)::set(this, "hmc", "link_config", link_cfg); |
|
end |
|
//-- create instances |
hmc = hmc_env #(.NUM_LANES(NUM_LANES))::type_id::create("hmc",this); |
|
|
axi4_req = axi4_stream_env #(.DATA_BYTES(AXI4_DATA_BYTES),.TUSER_WIDTH(AXI4_TUSER_WIDTH))::type_id::create("axi4_req",this); |
axi4_rsp = axi4_stream_env #(.DATA_BYTES(AXI4_DATA_BYTES),.TUSER_WIDTH(AXI4_TUSER_WIDTH))::type_id::create("axi4_rsp",this); |
|
hmc_module = hmc_module_env::type_id::create("hmc_module",this); |
|
rfs_hmc_I = cag_rgm_rfs_env #(.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), .READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH),.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH))::type_id::create("rfs_hmc_I", this); |
rf_model_hmc = rf_openhmc_rf_c::type_id::create("rf_model_hmc",this); |
|
v_seqr = vseqr::type_id::create("v_seqr", this); |
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
|
hmc_2_axi4_sequencer #(.DATA_BYTES(AXI4_DATA_BYTES),.TUSER_WIDTH(AXI4_TUSER_WIDTH)) axi4_req_seqr; |
|
axi4_stream_hmc_monitor #(.DATA_BYTES(AXI4_DATA_BYTES), .TUSER_WIDTH(AXI4_TUSER_WIDTH) ) axi4_hmc_req_mon; |
axi4_stream_hmc_monitor #(.DATA_BYTES(AXI4_DATA_BYTES), .TUSER_WIDTH(AXI4_TUSER_WIDTH) ) axi4_hmc_rsp_mon; |
|
super.connect_phase(phase); |
rfs_hmc_I.assign_vi(tb_top.rfs_hmc_if); |
rfs_hmc_I.set_rf(rf_model_hmc); |
|
//-- cast sequencer |
if ( !$cast(axi4_req_seqr, axi4_req.master.sequencer)) |
`uvm_fatal(get_type_name(), $psprintf("error in seqr cast")); |
|
//-- cast AXI4 to HMC pkt monitors |
if ( !$cast(axi4_hmc_req_mon, hmc_module.axi4_req_mon)) |
`uvm_fatal(get_type_name(), $psprintf("error in axi4_req_mon cast")); |
if ( !$cast(axi4_hmc_rsp_mon, hmc_module.axi4_rsp_mon)) |
`uvm_fatal(get_type_name(), $psprintf("error in axi4_rsp_mon cast")); |
|
axi4_req.master.sequencer = axi4_req_seqr; |
|
//-- connect the AXI4 UVC UVM analysis ports to the corresponding Module UVC monitors |
axi4_req.monitor.item_collected_port.connect(axi4_hmc_req_mon.axi4_port); |
axi4_rsp.monitor.item_collected_port.connect(axi4_hmc_rsp_mon.axi4_port); |
|
//-- connect the AXi4 to HMC pkt response monitor to the tag handler |
axi4_hmc_rsp_mon.item_collected_port.connect(axi4_req_seqr.handler.hmc_rsp_port); |
|
//-- virtual sequencer |
v_seqr.axi4_req_seqr = axi4_req_seqr; |
v_seqr.rf_seqr_hmc = rfs_hmc_I.sequencer; |
|
//--hmc monitor to scb |
hmc.req_transaction_mon.transaction_finished_port.connect(hmc_module.scb.hmc_req_port); //--direkt |
hmc.rsp_transaction_mon.transaction_finished_port.connect(hmc_module.scb.hmc_rsp_port); |
|
|
v_seqr.scb = hmc_module.scb; |
|
endfunction : connect_phase |
|
function void extract_phase(uvm_phase phase); |
link_cfg.responder.config_cg.sample(); |
endfunction : extract_phase |
|
endclass : hmc_tb |
|
`endif // hmc_TB_SV |
/trunk/openHMC/sim/tb/uvc/src/targets/dut_openhmc_behavioral_uvc.sv
0,0 → 1,244
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`default_nettype none |
`timescale 100ps/1ps |
|
module dut #( |
//*************************Don't touch! Control the design with arguments when executing run.sh |
parameter LOG_NUM_LANES = `LOG_NUM_LANES, |
parameter NUM_LANES = 2**LOG_NUM_LANES, |
parameter LOG_FPW = `LOG_FPW, |
parameter FPW = `FPW, |
parameter DWIDTH = 128*FPW, |
parameter NUM_DATA_BYTES = 16*FPW, |
parameter LANE_WIDTH = DWIDTH / NUM_LANES |
//************************* |
) |
( |
//AXI4 user clock |
input wire clk_user, |
//125MHz reference clock |
input wire clk_hmc_refclk, |
//Global reset |
input wire res_n, |
|
//HMC Link interface |
hmc_sr_if hmc, |
//AXI4 interface ports |
axi4_stream_if axi4_req, |
axi4_stream_if axi4_rsp, |
|
//Register File interface |
cag_rgm_rfs_if rfs_hmc |
); |
|
//----------------------------- Wiring openHMC controller |
wire [DWIDTH-1:0] to_serializers; |
wire [DWIDTH-1:0] from_deserializers; |
wire [NUM_LANES-1:0] bit_slip; |
wire [NUM_LANES-1:0] phy_lane_polarity; |
bit phy_rx_ready; |
bit P_RST_N; |
//If transceiver models are used, clk_hmc should be sourced from the transceiver outclock and res_n hmc can be set independently |
wire clk_hmc = clk_user; |
wire res_n_hmc = res_n; |
|
// Wire the HMC BFM model |
wire LxRXPS; // HMC input |
wire LxTXPS; // HMC output |
wire FERR_N; // HMC output |
wire LxTXPS_pullup; |
assign LxTXPS_pullup = (LxTXPS === 1'bz) ? 1'b1 : LxTXPS; |
wire FERR_N_pullup; |
assign FERR_N_pullup = (FERR_N === 1'bz) ? 1'b1 : FERR_N; |
|
//----------------------------- Signal Routing from SerDes to HMC |
wire [NUM_LANES-1:0] serial_Rx; |
wire [NUM_LANES-1:0] serial_Txp; |
|
//----------------------------- Attach the Register File System interface |
assign rfs_hmc_if.clk = clk_hmc; |
assign rfs_hmc_if.res_n = res_n; |
|
//Assign the AXI4 IF |
assign axi4_req.ACLK = (`OPENHMC_ASYNC_FIFOS==0) ? clk_hmc : clk_user; |
assign axi4_rsp.ACLK = (`OPENHMC_ASYNC_FIFOS==0) ? clk_hmc : clk_user; |
assign axi4_req.ARESET_N = (`OPENHMC_ASYNC_FIFOS==0) ? res_n_hmc : res_n; |
assign axi4_rsp.ARESET_N = (`OPENHMC_ASYNC_FIFOS==0) ? res_n_hmc : res_n; |
|
//------------------------------ Attach the HMC Link interface |
assign hmc.REFCLKP = clk_hmc_refclk; |
assign hmc.REFCLKN = ~clk_hmc_refclk; |
assign FERR_N = hmc.FERR_N; |
assign hmc.REFCLK_BOOT = 2'b00; // 00 -> 125 MHz, 01 -> 156.25 MHz, 10 -> 166.67 MHz |
assign hmc.P_RST_N = P_RST_N; |
assign LxTXPS = hmc.TXPS; |
assign hmc.RXPS = LxRXPS; |
|
assign hmc.RXP = NUM_LANES==8 ? {8'h0, serial_Txp[NUM_LANES-1:0]} : serial_Txp; // Controller Tx is Cube Rx |
assign hmc.RXN = ~hmc.RXP;//NUM_LANES==8 ? {8'h0, ~serial_Txp[NUM_LANES-1:0]} : ~serial_Txp; // Controller Tx is Cube Rx |
assign serial_Rx = hmc.TXP; // Controller Rx is Cube Tx |
|
//----------------------------- Generate Clocks |
bit clk_10G; |
generate |
begin : clocking_gen |
initial clk_10G = 1'b1; |
always #0.05ns clk_10G = ~clk_10G; |
end |
endgenerate |
|
//----------------------------- Behavioral SerDes |
bit LxTXPS_synced; |
bit res_n_synced; |
genvar lane; |
generate |
begin : serializers_gen |
|
for (lane=0; lane<NUM_LANES; lane++) begin : behavioral_gen |
serializer #( |
.DWIDTH(LANE_WIDTH) |
) serializer_I ( |
.clk(clk_hmc), |
.res_n(res_n), |
.fast_clk(clk_10G), |
.data_in(to_serializers[lane*LANE_WIDTH+LANE_WIDTH-1:lane*LANE_WIDTH]), |
.data_out(serial_Txp[lane]) |
); |
deserializer #( |
.DWIDTH(LANE_WIDTH) |
) deserializer_I ( |
.clk(clk_hmc), |
.res_n(LxTXPS_synced && res_n), |
.fast_clk(clk_10G), |
.bit_slip(bit_slip[lane]), |
.lane_polarity(phy_lane_polarity[lane]), |
.data_in(serial_Rx[lane]), |
.data_out(from_deserializers[lane*LANE_WIDTH+LANE_WIDTH-1:lane*LANE_WIDTH]) |
); |
end |
end |
endgenerate |
|
always @(LxTXPS) phy_rx_ready <= #500ns LxTXPS; |
always @(posedge clk_hmc) LxTXPS_synced <= LxTXPS; |
|
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
//---------INSTANTIATIONS HERE------------------------------------------------------------------------- |
//----------------------------------------------------------------------------------------------------- |
//===================================================================================================== |
openhmc_top #( |
.LOG_FPW(LOG_FPW), |
.FPW(FPW), |
.LOG_NUM_LANES(LOG_NUM_LANES), |
//Configure the Functionality |
.LOG_MAX_RX_TOKENS(10), //That is max 1023 Tokens |
.LOG_MAX_HMC_TOKENS(10), //That is max 1023 Tokens |
.HMC_RX_AC_COUPLED(1), |
.CTRL_LANE_POLARITY(1), |
.CTRL_LANE_REVERSAL(1), |
.BITSLIP_SHIFT_RIGHT(1), |
.OPEN_RSP_MODE(`OPEN_RSP_MODE), |
.SYNC_AXI4_IF(`OPENHMC_ASYNC_FIFOS==0), |
// Debug Logic |
.DBG_RX_TOKEN_MON(1) //Required by the test check sequence |
) |
openhmc_instance |
( |
|
//---------------------------------- |
//----SYSTEM INTERFACES |
//---------------------------------- |
.clk_user(clk_user), |
.clk_hmc(clk_hmc), |
.res_n_user(res_n), |
.res_n_hmc(res_n), |
|
//---------------------------------- |
//----Connect HMC Controller |
//---------------------------------- |
//to TX |
.s_axis_tx_TVALID(axi4_req.TVALID), |
.s_axis_tx_TREADY(axi4_req.TREADY), |
.s_axis_tx_TDATA(axi4_req.TDATA), |
.s_axis_tx_TUSER(axi4_req.TUSER), |
//from RX |
.m_axis_rx_TVALID(axi4_rsp.TVALID), |
.m_axis_rx_TREADY(axi4_rsp.TREADY), |
.m_axis_rx_TDATA(axi4_rsp.TDATA), |
.m_axis_rx_TUSER(axi4_rsp.TUSER), |
|
//---------------------------------- |
//----Connect Physical Link |
//---------------------------------- |
.phy_data_tx_link2phy(to_serializers), |
.phy_data_rx_phy2link(from_deserializers), |
.phy_bit_slip(bit_slip), |
.phy_tx_ready(res_n), |
.phy_rx_ready(phy_rx_ready && LxTXPS), |
.phy_lane_polarity(phy_lane_polarity), |
.phy_init_cont_set(), |
|
//---------------------------------- |
//----Connect HMC |
//---------------------------------- |
.P_RST_N(P_RST_N), |
.LXRXPS(LxRXPS), |
.LXTXPS(LxTXPS_pullup), |
.FERR_N(FERR_N_pullup), |
|
//---------------------------------- |
//----Connect RF |
//---------------------------------- |
.rf_address(rfs_hmc.address), |
.rf_read_data(rfs_hmc.read_data), |
.rf_invalid_address(rfs_hmc.invalid_address), |
.rf_access_complete(rfs_hmc.access_done), |
.rf_read_en(rfs_hmc.ren), |
.rf_write_en(rfs_hmc.wen), |
.rf_write_data(rfs_hmc.write_data) |
|
); |
|
endmodule : dut |
|
`default_nettype wire |
|
/trunk/openHMC/sim/tb/uvc/src/hmc_vseqr.sv
0,0 → 1,70
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef VIRTUAL_SEQUENCER_SV |
`define VIRTUAL_SEQUENCER_SV |
|
class vseqr extends uvm_sequencer; |
|
hmc_link_config link_cfg; |
|
//-- references to testbench sequencers |
cag_rgm_sequencer rf_seqr_hmc; |
|
hmc_module_scb scb; |
|
hmc_2_axi4_sequencer #(.DATA_BYTES(`AXI4BYTES),.TUSER_WIDTH(`AXI4BYTES)) axi4_req_seqr; |
|
`uvm_component_utils_begin(vseqr) |
`uvm_component_utils_end |
|
function new (string name = "hmc_virtual_sequencer", uvm_component parent); |
super.new(name, parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
if (!uvm_config_db#(hmc_link_config)::get(this, "", "link_cfg", link_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("hmc_link_uvc_config not set via config_db")); |
end |
endfunction : build_phase |
|
endclass : vseqr |
|
`endif // VIRTUAL_SEQUENCER_SV |
/trunk/openHMC/sim/tb/uvc/src/tb_top.sv
0,0 → 1,175
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`include "axi4_stream_pkg.sv" |
`include "hmc_pkg.sv" |
`include "hmc_module_pkg.sv" |
`include "cag_rgm_rfs_if.sv" |
|
|
|
`timescale 100ps/1ps |
|
module tb_top (); |
|
import uvm_pkg::*; |
|
//-- include the UVCs |
import axi4_stream_pkg::*; |
import hmc_pkg::*; |
import hmc_module_pkg::*; |
import hmc_base_types_pkg::*; |
|
`include "cag_rgm.svh" |
|
`ifdef X16 |
`include "register_file_model_16x.sv" |
`else |
`include "register_file_model_8x.sv" |
`endif |
|
`include "hmc_packet.sv" |
`include "hmc_req_packet.sv" |
`include "hmc_2_axi4_sequencer.sv" |
`include "hmc_2_axi4_sequence.sv" |
`include "tag_handler.sv" |
|
`include "hmc_vseqr.sv" |
|
`include "axi4_stream_hmc_monitor.sv" |
|
`include "hmc_tb.sv" |
|
`include "test_lib.sv" |
|
logic res_n, clk_user, clk_hmc_refclk; |
|
//-- instantiate the interfaces |
axi4_stream_if #( |
.DATA_BYTES(`AXI4BYTES), |
.TUSER_WIDTH(`AXI4BYTES) |
) axi4_hmc_req_if(); |
|
axi4_stream_if #( |
.DATA_BYTES(`AXI4BYTES), |
.TUSER_WIDTH(`AXI4BYTES) |
) axi4_hmc_rsp_if(); |
|
cag_rgm_rfs_if #( |
.ADDR_WIDTH(`RFS_OPENHMC_RF_AWIDTH), |
.READ_DATA_WIDTH(`RFS_OPENHMC_RF_RWIDTH), |
.WRITE_DATA_WIDTH(`RFS_OPENHMC_RF_WWIDTH) |
) rfs_hmc_if(); |
|
hmc_sr_if#(.NUM_LANES(2**`LOG_NUM_LANES)) hmc_if(); |
hmc_sr_if#(.NUM_LANES(2**`LOG_NUM_LANES)) hmc_int_if(); |
dut dut_I ( |
.clk_user(clk_user), |
.clk_hmc_refclk(clk_hmc_refclk), |
.res_n(res_n), |
.hmc(hmc_if), |
.axi4_req(axi4_hmc_req_if), |
.axi4_rsp(axi4_hmc_rsp_if), |
|
.rfs_hmc(rfs_hmc_if) |
); |
|
assign hmc_int_if.REFCLK_BOOT = hmc_if.REFCLK_BOOT; |
assign hmc_int_if.REFCLKN = hmc_if.REFCLKN; |
assign hmc_int_if.REFCLKP = hmc_if.REFCLKP; |
assign hmc_int_if.P_RST_N = hmc_if.P_RST_N; |
assign hmc_int_if.RXPS = hmc_if.RXPS; |
|
assign hmc_if.TXPS = hmc_int_if.TXPS; |
assign hmc_if.FERR_N = hmc_int_if.FERR_N; |
initial begin |
|
uvm_config_db#(virtual axi4_stream_if #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)))::set(null, "uvm_test_top.hmc_tb0.axi4_req", "vif", axi4_hmc_req_if); |
uvm_config_db#(virtual axi4_stream_if #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)))::set(null, "uvm_test_top.hmc_tb0.axi4_rsp", "vif", axi4_hmc_rsp_if); |
|
//hmc_link interfaces |
uvm_config_db#(virtual hmc_sr_if#(.NUM_LANES(2**`LOG_NUM_LANES)))::set(null, "uvm_test_top.hmc_tb0.hmc", "vif", hmc_if); |
uvm_config_db#(virtual hmc_sr_if#(.NUM_LANES(2**`LOG_NUM_LANES)))::set(null, "uvm_test_top.hmc_tb0.hmc", "int_vif", hmc_int_if); |
|
run_test(); |
end |
|
initial begin |
clk_user <= 1'b1; |
clk_hmc_refclk <= 1'b1; |
res_n <= 1'b0; |
#500ns; |
@(posedge clk_user) res_n <= 1'b1; |
end |
|
//-- Generate the user clock |
always begin |
case(`FPW) |
2: begin |
if(`LOG_NUM_LANES==3) //8lanes |
#1.6ns clk_user = !clk_user; |
else begin |
#0.8ns clk_user = !clk_user; |
end |
end |
4: begin |
if(`LOG_NUM_LANES==3) //8lanes |
#3.2ns clk_user = !clk_user; |
else |
#1.6ns clk_user = !clk_user; |
end |
6: begin |
if(`LOG_NUM_LANES==3) //8lanes |
#4.8ns clk_user = !clk_user; |
else |
#2.4ns clk_user = !clk_user; |
end |
8: begin |
if(`LOG_NUM_LANES==3) //8lanes |
#6.4ns clk_user = !clk_user; |
else |
#3.2ns clk_user = !clk_user; |
end |
endcase |
end |
|
//-- 125 MHz HMC/Transceiver refclock |
always #4ns clk_hmc_refclk <= ~clk_hmc_refclk; |
|
endmodule : tb_top |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_slave_agent.sv
64,7 → 64,10
end |
if (!uvm_config_db#(axi4_stream_config)::get(this, "", "axi4_stream_cfg", axi4_stream_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_stream_cfg not set via config_db")); |
end else begin |
uvm_config_db#(axi4_stream_config)::set(this, "driver" , "axi4_stream_cfg", axi4_stream_cfg); //distributing axi4_stream_cfg to master driver |
end |
|
if(axi4_stream_cfg.slave_active == UVM_ACTIVE)begin |
uvm_config_db#(axi4_stream_config)::set(this, "driver", "axi4_stream_cfg", axi4_stream_cfg); // distribute axi4_stream_cfg to driver |
driver = axi4_stream_slave_driver#(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("driver", this); |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_master_agent.sv
69,6 → 69,8
|
if (!uvm_config_db#(axi4_stream_config)::get(this, "", "axi4_stream_cfg", axi4_stream_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_stream_cfg not set via config_db")); |
end else begin |
uvm_config_db#(axi4_stream_config)::set(this, "driver" , "axi4_stream_cfg", axi4_stream_cfg); //distributing axi4_stream_cfg to master driver |
end |
|
if(axi4_stream_cfg.master_active == UVM_ACTIVE)begin //-- distribute axi4_stream_cfg to driver |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_hmc_monitor.sv
154,11 → 154,11
end |
|
end |
if(|vc.tuser) |
`uvm_info(get_type_name(),$psprintf("%d header and %d tails available", headers_seen, tails_seen) ,UVM_HIGH) |
|
`uvm_info(get_type_name(),$psprintf("%d header and %d tails available", headers_seen, tails_seen) ,UVM_HIGH) |
|
|
|
endfunction : collect_flits |
|
//-- Use FLITs to form packets |
174,6 → 174,8
current_flit = flit_queue.pop_front(); |
no_length_mismatches_allowed : assert (current_flit[14:11] == current_flit[10:7]); //--check internal hmc_packet length |
current_packet_length = current_flit[10:7]; |
`uvm_info(get_type_name(),$psprintf("packet length %0d ", current_packet_length), UVM_HIGH) |
`uvm_info(get_type_name(),$psprintf("queue size %0d ", flit_queue.size()), UVM_HIGH) |
flit_queue_underflow2 : assert (flit_queue.size() >= current_packet_length - 1); //--check check hmc_packet complete received |
|
|
227,15 → 229,10
|
hmc_packet packet; |
|
|
`uvm_info(get_type_name(),$psprintf("got valid cycle"), UVM_HIGH) |
|
collect_flits(vc); |
|
//`uvm_info(get_type_name(),$psprintf("got %0d tails and %0d flits",tails_seen, flit_queue.size() ), UVM_HIGH) |
|
`uvm_info(get_type_name(),$psprintf("got %0d tails and %0d flits",tails_seen, flit_queue.size() ), UVM_HIGH) |
|
|
//-- Convert flit_queue to hmc_packets |
while (tails_seen >0) begin |
collect_packet(); |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_if.sv
46,15 → 46,15
`ifndef AXI4_STREAM_IF_SV |
`define AXI4_STREAM_IF_SV |
|
interface axi4_stream_if #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) ( |
input logic ACLK, //-- Clock (All signals sampled on the rising edge) |
input logic ARESET_N //-- Global Reset |
); |
interface axi4_stream_if #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) (); |
|
//-- |
//-- Interface signals |
//-- |
|
logic ACLK; //-- Clock (All signals sampled on the rising edge) |
logic ARESET_N; //-- Global Reset |
|
logic TVALID; // Master valid |
logic TREADY; // Slave ready |
logic [8*DATA_BYTES-1:0] TDATA; //-- Master data |
69,12 → 69,12
logic [DATA_BYTES/16-1:0] DEBUG_HEADERS; //-- contains the HMC-HEADER Flags |
logic [DATA_BYTES/16-1:0] DEBUG_TAILS; //-- contains the HMC-TAIL Flags |
|
|
//-- assigning the debug signals to TUSER |
assign DEBUG_VALIDS = TUSER[1*(DATA_BYTES /16)-1: (0* DATA_BYTES /16)]; |
assign DEBUG_HEADERS = TUSER[2*(DATA_BYTES /16)-1: (1* DATA_BYTES /16)]; |
assign DEBUG_TAILS = TUSER[3*(DATA_BYTES /16)-1: (2* DATA_BYTES /16)]; |
|
|
//-- |
//-- Interface Coverage |
//-- |
166,11 → 166,11
// |
//endproperty |
|
chk_reset_tvalid : assert property ( |
//-- TVALID must be inactive during Reset |
@(posedge ACLK) |
!ARESET_N |-> TVALID == 1'b0 |
); |
// chk_reset_tvalid : assert property ( |
// //-- TVALID must be inactive during Reset |
// @(posedge ACLK) |
// !ARESET_N |-> TVALID == 1'b0 |
// ); |
|
|
chk_valid_hold : assert property ( |
205,9 → 205,24
|=> (TVALID == 1) throughout ( $countones(DEBUG_HEADERS) < $countones(DEBUG_TAILS) )[->1] |
); |
|
time clk_rise; |
time reset_rise; |
|
always @(posedge ACLK) begin |
if(ARESET_N == 0) |
clk_rise <= $time(); |
end |
|
always @(posedge ARESET_N) begin |
reset_rise <= $time(); |
end |
|
//TODO TODO ADD |
// check_sync_reset : assert property ( |
// @(posedge ACLK) |
// $rose(ARESET_N) |=> (reset_rise == clk_rise) |
// ); |
|
|
property data_hold_p; |
//-- if TVALID is set TDATA must not be changed until TREADY |
logic [8*DATA_BYTES-1:0] m_data; |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_valid_cycle.sv
47,7 → 47,7
class axi4_stream_valid_cycle #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_sequence_item; |
|
rand bit [DATA_BYTES*8-1:0] tdata; |
rand bit [TUSER_WIDTH-1:0] tuser; |
rand bit [TUSER_WIDTH-1:0] tuser; |
rand int unsigned delay = 0; |
|
constraint c_packet_delay { |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_config.sv
44,10 → 44,12
|
uvm_active_passive_enum master_active = UVM_PASSIVE; |
uvm_active_passive_enum slave_active = UVM_PASSIVE; |
uvm_active_passive_enum open_rsp_mode = UVM_PASSIVE; |
|
`uvm_object_utils_begin(axi4_stream_config) |
`uvm_field_enum(uvm_active_passive_enum, master_active, UVM_DEFAULT) |
`uvm_field_enum(uvm_active_passive_enum, slave_active, UVM_DEFAULT) |
`uvm_field_enum(uvm_active_passive_enum, open_rsp_mode, UVM_DEFAULT) |
`uvm_object_utils_end |
|
function new(string name = "axi4_stream_config"); |
/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_slave_driver.sv
44,6 → 44,12
class axi4_stream_slave_driver #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_driver #(hmc_packet); |
|
axi4_stream_config axi4_stream_cfg; |
rand int block_cycles; |
|
|
constraint c_block_cycles { |
soft block_cycles dist{0:/30,[1:5]:/41, [6:15]:/25, [16:10000]:/4}; |
} |
|
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
66,13 → 72,15
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
|
if (!uvm_config_db#(axi4_stream_config)::get(this, "", "axi4_stream_cfg", axi4_stream_cfg)) begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_stream_cfg not set via config_db")); |
end |
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
bit ready_asserted = 0; |
bit last_valid = 0; |
int set_probability; |
|
|
super.run_phase(phase); |
|
forever begin |
84,23 → 92,34
fork |
forever begin |
//-- Accept packets |
@(negedge vif.ACLK); |
@(posedge vif.ACLK); |
|
set_probability_randomization : assert (std::randomize(set_probability) with {set_probability >= 0 && set_probability < 10;}); |
|
//-- Higher probability to be ready when the master has something to send |
if (ready_asserted == 0 && vif.TVALID == 1 && set_probability > 3) begin |
ready_asserted = 1; |
//-- Can be ready when the master has nothing to send |
end else if (ready_asserted == 0 && vif.TVALID == 0 && set_probability > 8) begin |
ready_asserted = 1; |
//-- Only become not ready after accepting something |
end else if (ready_asserted == 1 && vif.TVALID == 1 && set_probability > 3) begin |
ready_asserted = 0; |
if(axi4_stream_cfg.open_rsp_mode==UVM_ACTIVE) begin |
vif.TREADY <= 1'b1; |
end else begin |
|
if (vif.TVALID) |
randcase |
3 : vif.TREADY <= 1; |
1 : vif.TREADY <= 0; |
endcase |
else |
randcase |
1 : vif.TREADY <= 1; |
1 : vif.TREADY <= 0; |
1 : begin //-- hold tready at least until tvalid is set |
vif.TREADY <= 0; |
void'(this.randomize()); |
while (vif.TVALID == 0) |
@(posedge vif.ACLK); |
|
repeat(block_cycles) @(posedge vif.ACLK); //-- wait 2 additional cycles |
|
end |
endcase |
|
|
end |
|
vif.TREADY <= ready_asserted; |
last_valid = vif.TVALID == 1'b1; |
end |
begin //-- Asynchronous reset |
@(negedge vif.ARESET_N); |
/trunk/openHMC/sim/UVC/hmc_base_types/sv/hmc_packet.sv
50,7 → 50,7
|
// request header fields |
rand bit [2:0] cube_ID; // CUB |
rand bit [33:0] address; // ADRS |
rand bit [33:0] address; // ADRS |
rand bit [8:0] tag; // TAG |
rand bit [3:0] packet_length; // LNG 128-bit (16-byte) flits |
rand bit [3:0] duplicate_length; // DLN |
64,7 → 64,7
rand bit [2:0] sequence_number; // SEQ |
rand bit [7:0] forward_retry_pointer; // FRP |
rand bit [7:0] return_retry_pointer; // RRP |
rand bit [31:0] packet_crc; // CRC |
rand bit [31:0] packet_crc; // CRC |
|
// response header fields not used before |
rand bit [8:0] return_tag; // TGA (Optional) |
83,6 → 83,8
|
// helper fields |
rand int flit_delay; |
|
int timestamp; |
|
`uvm_object_utils_begin(hmc_packet) |
`uvm_field_int(flit_delay, UVM_ALL_ON | UVM_NOPACK | UVM_DEC | UVM_NOCOMPARE | UVM_DEC) |
106,10 → 108,14
`uvm_field_int(crc_error, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_object_utils_end |
|
//constraint c_payload_size { packet_length == 1 || payload.size() == packet_length - 1; } |
constraint c_poisoned { poisoned == 0; } |
constraint c_cube_id {cube_ID ==0;} |
constraint c_address {address ==0;} |
constraint c_address { |
soft address < 80000000; |
((command & `HMC_TYPE_MASK) == HMC_FLOW_TYPE) -> address == 0; |
soft address[3:0]==4'h0; |
} |
constraint c_source_link_ID {source_link_ID ==0;} |
constraint c_crc_error { crc_error == 0; } |
constraint c_matching_length { packet_length == duplicate_length; } |
constraint c_return_tag { return_tag == 0; } |
143,7 → 149,31
constraint c_flit_delay { |
soft flit_delay dist{0:/90, [1:8]:/8, [8:200]:/2 }; |
} |
constraint c_error_status { |
soft error_status == 0; |
} |
|
constraint c_data_invalid { |
soft data_invalid == 0; |
} |
|
|
constraint c_pret { |
(command == HMC_PRET)-> forward_retry_pointer ==0; |
(command == HMC_PRET)-> sequence_number ==0; |
} |
constraint c_irtry{ |
(command == HMC_IRTRY) -> start_retry != clear_error_abort; |
((command == HMC_IRTRY)&&(start_retry)) ->forward_retry_pointer == 1; |
((command == HMC_IRTRY)&&(clear_error_abort)) ->forward_retry_pointer == 2; |
(command == HMC_IRTRY) -> sequence_number == 0; |
} |
|
constraint c_flow { |
((command & `HMC_TYPE_MASK) == HMC_FLOW_TYPE) -> tag == 0; |
((command & `HMC_TYPE_MASK) == HMC_FLOW_TYPE) -> cube_ID == 0; |
} |
|
function new (string name = "hmc_packet"); |
super.new(name); |
endfunction : new |
158,7 → 188,6
|
`uvm_info("AXI Packet queued",$psprintf("%0s packet_length = %0d",command.name(), packet_length), UVM_HIGH) |
|
|
if (packet_length < 2) |
return; |
|
175,8 → 204,6
if ((command == HMC_MODE_WRITE)|| (command == HMC_MODE_READ)) begin |
payload[0][127:32] = 96'b0; |
end |
|
|
endfunction |
|
function hmc_command_type get_command_type(); |
216,25 → 243,16
*/ |
|
function bit [31:0] calculate_crc(); |
bit bitstream[]; |
packer_succeeded : assert (pack(bitstream) > 0); |
return calc_crc(bitstream); |
endfunction : calculate_crc |
|
function bit [31:0] calc_crc(bit bitstream[]); |
bit [32:0] polynomial = 33'h1741B8CD7; // Normal |
|
bit [32:0] remainder = 33'h0; |
bit bitstream[]; |
int bits_packed=0; |
|
bits_packed = pack(bitstream); |
packer_succeeded : assert (bits_packed > 0); |
|
/* |
if (bits_packed > 128) begin //DEBUG |
bit [127:0] flits[9]; |
for( int i=0; i < bits_packed; i++) |
flits[i/128][i%128] = bitstream[i]; |
for( int i=0; i < bits_packed/128; i++) |
`uvm_info(get_type_name(),$psprintf("calculate_crc flits[%0x] %0x",i,flits[i]), UVM_HIGH) |
end |
*/ |
|
for( int i=0; i < bits_packed-32; i++ ) begin // without the CRC |
for( int i=0; i < bitstream.size()-32; i++ ) begin // without the CRC |
remainder = {remainder[31:0], bitstream[i]}; |
if( remainder[32] ) begin |
remainder = remainder ^ polynomial; |
249,9 → 267,8
end |
|
return remainder[31:0]; |
endfunction : calc_crc |
|
endfunction : calculate_crc |
|
virtual function void do_pack(uvm_packer packer); |
|
super.do_pack(packer); |
267,12 → 284,12
HMC_IRTRY: packer.pack_field ( {3'h0, 3'h0, 34'h0, 9'h0, duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
default: uvm_report_fatal(get_type_name(), $psprintf("pack function called for a hmc_packet with an illegal FLOW type='h%0h!", command)); |
endcase |
HMC_READ_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, 34'h0, tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_MODE_READ_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_READ_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_MODE_READ_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, 34'h0, tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_POSTED_WRITE_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_WRITE_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_POSTED_MISC_WRITE_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_MISC_WRITE_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, 34'h0, tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_MISC_WRITE_TYPE: packer.pack_field ( {cube_ID[2:0], 3'h0, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
HMC_RESPONSE_TYPE: packer.pack_field ( {22'h0, source_link_ID[2:0], 6'h0, return_tag[8:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], 1'b0, command[5:0]}, 64); |
default: uvm_report_fatal(get_type_name(), $psprintf("pack function called for a hmc_packet with an illegal command type='h%0h!", command)); |
endcase |
308,6 → 325,7
|
virtual function void do_unpack(uvm_packer packer); |
bit [63:0] header; |
bit [63:0] tail; |
bit [31:0] calculated_crc; |
bit [21:0] rsvd22; |
bit [5:0] rsvd6; |
315,18 → 333,26
bit [2:0] rsvd3; |
bit rsvd1; |
|
bit bitstream[]; |
|
super.do_unpack(packer); |
packer.big_endian = 0; |
|
packer.get_bits(bitstream); |
|
for (int i = 0; i <32; i++)begin |
packet_crc[i] = bitstream[bitstream.size()-32 +i]; |
end |
|
calculated_crc = calc_crc(bitstream); |
// header |
header = packer.unpack_field(64); |
command[5:0] = header[5:0]; |
command[5:0] = header[5:0];//-- doppelt? |
|
if (get_command_type != HMC_RESPONSE_TYPE) |
{cube_ID[2:0], rsvd3, address[33:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], rsvd1, command[5:0]} = header; |
else |
{rsvd22[21:0], source_link_ID[2:0], rsvd6[5:0], return_tag[8:0], tag[8:0], duplicate_length[3:0], packet_length[3:0], rsvd1, command[5:0]} = header; |
|
// Unpack should not be called with length errors |
if (duplicate_length != packet_length || packet_length == 0) |
`uvm_fatal(get_type_name(), $psprintf("do_unpack: length mismatch dln=%0d len=%0d cmd=%0d!", duplicate_length, packet_length, command)); |
336,20 → 362,22
payload.push_back(packer.unpack_field(128)); |
|
// tail |
if (get_command_type != HMC_RESPONSE_TYPE) |
{packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], rsvd5, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]} = packer.unpack_field(64); |
tail = packer.unpack_field(64); |
if (get_command_type != HMC_RESPONSE_TYPE) |
{packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], rsvd5, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]} = tail; |
else |
{packet_crc[31:0], return_token_count[4:0], error_status[6:0], data_invalid, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]} = packer.unpack_field(64); |
{packet_crc[31:0], return_token_count[4:0], error_status[6:0], data_invalid, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]} = tail; |
|
start_retry = (command == HMC_IRTRY ? forward_retry_pointer[0] : 1'b0); |
clear_error_abort = (command == HMC_IRTRY ? forward_retry_pointer[1] : 1'b0); |
|
calculated_crc = calculate_crc(); |
crc_error = 0; |
|
// Inverted CRC means poisoned |
poisoned = (packet_crc == ~calculated_crc) ? 1'b1 : 1'b0; |
|
crc_error = (packet_crc != calculated_crc && !poisoned) ? 1'b1 : 1'b0; |
if (packet_crc != calculated_crc && !poisoned ) |
begin |
crc_error = 1; |
end |
endfunction : do_unpack |
|
|
/trunk/openHMC/sim/UVC/hmc_base_types/sv/hmc_types.svh
102,6 → 102,7
|
typedef enum { |
RESET, |
POWER_DOWN, |
INIT, |
PRBS, |
NULL_FLITS, |
112,7 → 113,6
START_RETRY_INIT, |
CLEAR_RETRY, |
SEND_RETRY_PACKETS |
|
} init_state_t; |
|
`endif // HMC_TYPES_SVH |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_sr_if.sv
0,0 → 1,247
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// |
// Short Range Hybrid Memory Cube Interface |
// |
// |
|
`ifndef HMC_SR_IF_SV |
`define HMC_SR_IF_SV |
|
interface hmc_sr_if #(parameter NUM_LANES = 16) (); |
|
//-- |
//-- interface signals |
//-- |
|
logic REFCLKP; // Link Reference clock |
logic REFCLKN; |
|
logic [1:0] REFCLK_BOOT; // 00 -> 125 MHz, 01 -> 156.25 MHz, 10 -> 166.67 MHz |
|
logic P_RST_N; |
|
//-- Differential pairs |
logic [NUM_LANES - 1 : 0] RXP; |
logic [NUM_LANES - 1 : 0] RXN; |
|
logic [NUM_LANES - 1 : 0] TXP; |
logic [NUM_LANES - 1 : 0] TXN; |
|
logic RXPS; // Power-reduction input |
logic TXPS; // Power-reduction output |
|
logic FERR_N; // Fatal error indicator |
|
//-- |
//-- Checking & Coverage |
//-- |
|
time t_IS = 10ns; //-- see the Spec |
time t_RST = 20ns; //-- minimum reset time |
|
time t_PST = 80ns; |
time t_SS = 525ns; //-- since revision E |
time t_SME = 600ns; |
time t_SREF = 1us;//-- should be 1ms in the real system |
|
time reset_fall = 0; |
time RXPS_rise; |
time TXPS_rise; |
time reset_rise; |
|
time RXPS_fall; |
time TXPS_fall = 0; |
|
|
bit txp_z = 0; |
event wakeup; |
event sleep; |
|
covergroup rst_times_cg @ (posedge P_RST_N); |
option.per_instance = 1; |
RXPS_rise_BEFORE_P_RST_N : coverpoint $time() - RXPS_rise { |
bins small_time[100] = {[1*t_IS+1:100*t_IS-1]}; |
bins huge_time = {[100*t_IS:$]}; |
illegal_bins illegal = {[0:t_IS]}; |
} |
P_RST_N_length : coverpoint $time() - reset_fall { |
bins small_time[100] = {[1*t_RST+1:100*t_RST-1]}; |
bins huge_time = {[100*t_RST:$]}; |
illegal_bins illegal = {[0:t_RST]}; |
} |
endgroup |
|
|
|
covergroup sleep_times_cg @ (posedge RXPS); |
option.per_instance = 1; |
SLEEP_TIME : coverpoint $time - RXPS_fall { |
bins short_sleep[20] = {[2*t_SREF:20*t_SREF]}; |
bins long_sleep = {[21*t_SREF:$]}; |
illegal_bins illegal = {[0:t_SREF-1]}; |
} |
endgroup |
|
|
covergroup prepare_sleep_cg @ (sleep); |
option.per_instance = 1; |
PREPARE_SLEEP_TIME : coverpoint TXPS_fall - RXPS_fall { |
bins short_sleep = {[0 :t_PST]}; |
bins waiting_t_sme[3] = {[t_PST :3*t_SS]}; |
illegal_bins illegal = {[t_PST+ 3*t_SS+1:$]}; |
} |
SWITCH_TO_Z : coverpoint $time - TXPS_fall { |
bins short = {[0:t_SME/2]}; |
bins long = {[t_SME/2 + 1: t_SME]}; |
illegal_bins illegal = {[t_SME+1:$]}; |
} |
endgroup |
|
|
covergroup prepare_wakeup_cg @ (wakeup); |
option.per_instance = 1; |
PREPARE_WAKEUP_TIME : coverpoint TXPS_rise - RXPS_rise { |
bins short_sleep = {[0 :t_PST]}; |
bins waiting_t_sme[3] = {[t_PST :3*t_SS]}; |
illegal_bins illegal = {[t_PST+ 3*t_SS+1:$]}; |
} |
SWITCH_FROM_Z : coverpoint $time - TXPS_rise { |
bins short = {[0:t_SME/2]}; |
bins long = {[t_SME/2 + 1: t_SME]}; |
illegal_bins illegal = {[t_SME+1:$]}; |
} |
|
endgroup |
|
|
rst_times_cg rst_times = new(); |
sleep_times_cg sleep_times = new(); |
prepare_sleep_cg prepare_sleep = new(); |
prepare_wakeup_cg prepare_wakeup = new(); |
|
//always @(posedge RXPS) begin |
// if(P_RST_N == 0) |
// RXPS_rise <= $time(); |
//end |
|
always @(posedge P_RST_N) begin |
reset_rise <= $time(); |
end |
|
always @(negedge P_RST_N) begin |
reset_fall <= $time(); |
end |
|
always @(negedge RXPS) begin |
RXPS_fall <= $time(); |
end |
always @(negedge TXPS) begin |
TXPS_fall = $time(); |
//->sleep; |
end |
|
always @(TXP) begin |
if (TXP === {NUM_LANES{1'bz}})begin |
->sleep; |
txp_z = 1; |
end |
else begin |
if (RXPS_rise >0) begin |
if (txp_z == 1)begin |
->wakeup; |
end |
txp_z = 0; |
end |
end |
end |
|
always @(posedge RXPS) begin |
RXPS_rise <= $time(); |
end |
always @(posedge TXPS) begin |
TXPS_rise = $time(); |
end |
|
//-- reset checks |
chk_RXPS_before_P_RST_N : assert property ( |
@(posedge REFCLKP) |
$rose(P_RST_N) |=> (reset_rise >= RXPS_rise + t_IS) |
); |
|
chk_P_RST_N_length : assert property ( |
@(posedge REFCLKP) |
$rose(P_RST_N) |=> (t_RST <= reset_rise - reset_fall) |
); |
|
|
chk_Lanes_HIGH_Z_during_P_RST_N_P : assert property ( |
@(posedge REFCLKP) |
!P_RST_N |-> (TXP === { NUM_LANES{1'bZ}}) |
); |
chk_Lanes_HIGH_Z_during_P_RST_N_N : assert property ( |
@(posedge REFCLKP) |
!P_RST_N |-> (TXN === { NUM_LANES{1'bZ}}) |
); |
|
|
|
//-- sleep mode checks --// |
|
//-- txps falling edge within t_PST + 3* t_SME after rxps falling edge |
chk_TXPS_fall_after_RXPS : assert property ( |
@(posedge REFCLKP) |
$fell(TXPS) |->(t_PST+ 3* t_SME >= TXPS_fall - RXPS_fall) |
); |
|
chk_TXPS_rise_after_RXPS : assert property ( |
@(posedge REFCLKP) |
$rose(TXPS) |->((t_PST+ 3* t_SME >= TXPS_rise - RXPS_rise)|| RXPS_rise <= reset_rise) |
); |
|
chk_sleep_mode_min_duration : assert property ( |
@(posedge REFCLKP) disable iff (!P_RST_N) |
$rose(RXPS) |->(t_SREF <= RXPS_rise - RXPS_fall) |
); |
|
endinterface : hmc_sr_if |
|
`endif // HMC_SR_IF_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_config.sv
0,0 → 1,376
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef hmc_config_SV |
`define hmc_config_SV |
|
|
|
|
class hmc_local_link_config extends uvm_object; |
// Configure the driver |
rand bit [15:0] reverse_polarity; |
rand bit reverse_lanes; |
rand int TS1_Messages; |
|
rand int irtry_flit_count_to_send; |
rand int irtry_flit_count_received_threshold; |
|
int random_retry_probability; |
rand int max_retry_attempts; |
|
rand int lane_delays[16]; |
rand bit lane_delays_enabled=1; |
|
bit errors_enabled = 0; |
bit lane_errors_enabled = 0; |
rand int poisoned_probability; |
rand int lng_error_probability; |
rand int seq_error_probability; |
rand int crc_error_probability; |
rand int bitflip_error_probability; |
|
rand int poisoned_packets_minimum_length; |
uvm_active_passive_enum active = UVM_PASSIVE; |
int width; |
|
rand int send_tret_time; |
rand int send_pret_time; |
|
bit requester = 1'b1; |
int run_length_limit = 85; |
|
covergroup config_cg; |
option.per_instance = 1; |
lane0_delay : coverpoint lane_delays[0] |
{bins delay[] = {[0:7]};} |
lane1_delay : coverpoint lane_delays[1] |
{bins delay[] = {[0:7]};} |
lane2_delay : coverpoint lane_delays[2] |
{bins delay[] = {[0:7]};} |
lane3_delay : coverpoint lane_delays[3] |
{bins delay[] = {[0:7]};} |
lane4_delay : coverpoint lane_delays[4] |
{bins delay[] = {[0:7]};} |
lane5_delay : coverpoint lane_delays[5] |
{bins delay[] = {[0:7]};} |
lane6_delay : coverpoint lane_delays[6] |
{bins delay[] = {[0:7]};} |
lane7_delay : coverpoint lane_delays[7] |
{bins delay[] = {[0:7]};} |
lane8_delay : coverpoint lane_delays[8] |
{bins delay[] = {[0:7]};} |
lane9_delay : coverpoint lane_delays[9] |
{bins delay[] = {[0:7]};} |
lane10_delay : coverpoint lane_delays[10] |
{bins delay[] = {[0:7]};} |
lane11_delay : coverpoint lane_delays[11] |
{bins delay[] = {[0:7]};} |
lane12_delay : coverpoint lane_delays[12] |
{bins delay[] = {[0:7]};} |
lane13_delay : coverpoint lane_delays[13] |
{bins delay[] = {[0:7]};} |
lane14_delay : coverpoint lane_delays[14] |
{bins delay[] = {[0:7]};} |
lane15_delay : coverpoint lane_delays[15] |
{bins delay[] = {[0:7]};} |
|
lane0_polarity : coverpoint reverse_polarity[0] |
{bins polarity = {1};} |
lane1_polarity : coverpoint reverse_polarity[1] |
{bins polarity = {1};} |
lane2_polarity : coverpoint reverse_polarity[2] |
{bins polarity = {1};} |
lane3_polarity : coverpoint reverse_polarity[3] |
{bins polarity = {1};} |
lane4_polarity : coverpoint reverse_polarity[4] |
{bins polarity = {1};} |
lane5_polarity : coverpoint reverse_polarity[5] |
{bins polarity = {1};} |
lane6_polarity : coverpoint reverse_polarity[6] |
{bins polarity = {1};} |
lane7_polarity : coverpoint reverse_polarity[7] |
{bins polarity = {1};} |
lane8_polarity : coverpoint reverse_polarity[8] |
{bins polarity = {1};} |
lane9_polarity : coverpoint reverse_polarity[9] |
{bins polarity = {1};} |
lane10_polarity : coverpoint reverse_polarity[10] |
{bins polarity = {1};} |
lane11_polarity : coverpoint reverse_polarity[11] |
{bins polarity = {1};} |
lane12_polarity : coverpoint reverse_polarity[12] |
{bins polarity = {1};} |
lane13_polarity : coverpoint reverse_polarity[13] |
{bins polarity = {1};} |
lane14_polarity : coverpoint reverse_polarity[14] |
{bins polarity = {1};} |
lane15_polarity : coverpoint reverse_polarity[15] |
{bins polarity = {1};} |
|
endgroup |
|
`uvm_object_utils_begin(hmc_local_link_config) |
`uvm_field_int(reverse_polarity, UVM_DEFAULT | UVM_BIN) |
`uvm_field_int(reverse_lanes, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(lane_delays_enabled, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(irtry_flit_count_to_send, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(irtry_flit_count_received_threshold, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(random_retry_probability, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(max_retry_attempts, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(poisoned_packets_minimum_length, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(poisoned_probability, UVM_DEFAULT| UVM_DEC) |
`uvm_field_int(lng_error_probability, UVM_DEFAULT| UVM_DEC) |
`uvm_field_int(seq_error_probability, UVM_DEFAULT| UVM_DEC) |
`uvm_field_int(crc_error_probability, UVM_DEFAULT| UVM_DEC) |
`uvm_field_int(bitflip_error_probability, UVM_DEFAULT| UVM_DEC) |
`uvm_field_int(width, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(send_pret_time, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(send_tret_time, UVM_DEFAULT | UVM_DEC) |
`uvm_field_enum(uvm_active_passive_enum, active, UVM_DEFAULT) |
`uvm_field_int(run_length_limit, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(requester, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(errors_enabled, UVM_DEFAULT) |
`uvm_field_int(lane_errors_enabled, UVM_DEFAULT) |
|
`uvm_object_utils_end |
|
// constraint c_token_count { |
// token_count > 27 && token_count < 1024; //token count min=27, for compliance with tx_link. Could be refined if necessary |
// } |
|
constraint c_max_retry_attempts { |
max_retry_attempts == 10; |
} |
|
constraint c_TS1_Messages { |
soft TS1_Messages == 6; |
} |
|
constraint c_active_settings { |
active==UVM_ACTIVE || |
random_retry_probability == 0 && send_pret_time == 0 && |
send_tret_time == 0;// && bit_errors_allowed == 0;// && |
// poisoned_packets_allowed == 0; |
} |
|
constraint c_lane_delays { |
foreach (lane_delays[i]) { |
if(lane_delays_enabled) lane_delays[i] inside {[0:7]}; |
else lane_delays[i]==0; |
} |
} |
|
constraint c_lane_polarity { |
foreach (reverse_polarity[i]) { |
if ((width == 8) && (i >=8)) reverse_polarity[i] == 0; |
} |
} |
|
constraint c_send_pret_time { |
send_pret_time == 0; |
} |
|
constraint c_send_tret_time { |
send_tret_time == 0; |
} |
|
constraint c_irtry_flit_count_received_threshold { |
irtry_flit_count_received_threshold == 16; |
} |
constraint c_irtry_flit_count_to_send { |
//irtry_flit_count_to_send > 16 && irtry_flit_count_to_send < 30; |
irtry_flit_count_to_send == 16; |
} |
|
constraint c_poisoned_packets_propability { |
poisoned_probability <=10; |
poisoned_probability >=0; |
|
soft poisoned_probability == 0; |
if (errors_enabled) (poisoned_probability == 6); |
} |
|
constraint c_lng_error_probability { |
lng_error_probability <=10; |
lng_error_probability >=0; |
|
soft lng_error_probability == 0; |
if (errors_enabled) (lng_error_probability == 6); |
} |
|
constraint c_seq_error_probability { |
seq_error_probability <=10; |
seq_error_probability >=0; |
|
soft seq_error_probability == 0; |
if (errors_enabled) (seq_error_probability == 6); |
} |
|
constraint c_crc_error_probability { |
crc_error_probability <=10; |
crc_error_probability >=0; |
|
soft crc_error_probability == 0; |
if (errors_enabled)(crc_error_probability == 6); |
} |
|
constraint c_bitflip_error_probability { |
soft bitflip_error_probability == 0; |
if (lane_errors_enabled)(bitflip_error_probability == 2); |
} |
|
constraint c_poisoned_packets_minimum_length { |
poisoned_packets_minimum_length > 4 && |
poisoned_packets_minimum_length < 9; |
} |
|
function new(string name="hmc_local_link_config"); |
super.new(name); |
config_cg = new(); |
endfunction : new |
|
function void post_randomize(); |
endfunction : post_randomize |
|
virtual function void do_print (uvm_printer printer); |
super.do_print(printer); |
endfunction : do_print |
|
endclass : hmc_local_link_config |
|
class hmc_link_config extends uvm_object; |
|
// Global Configuration (Requester, Responder, and Monitor) |
rand bit [2:0] cube_id; |
rand bit scramblers_enabled; |
// Timing parameters |
int tINIT = 1us; // 20ms in the spec, but that would take too long in simulation |
int tRESP1 = 1us; // 1us or 1.2ms with DFE |
int tRESP2 = 1us; // 1us |
|
int fpw; //-- used for coverage |
|
time t_PST = 80ns; |
time t_SS = 500ns; |
time t_SME = 600ns; |
|
int retry_timeout_period = 614.4ns; // 10Gbps |
// 491.52ns // 12.5Gbps |
// 409.35ns // 15Gbps |
|
rand int bit_rate; |
rand int bit_time; |
|
rand int hmc_tokens; |
rand int rx_tokens; |
|
|
uvm_active_passive_enum cfg_rsp_open_loop = UVM_PASSIVE; |
uvm_active_passive_enum enable_tag_checking = UVM_ACTIVE; |
|
// Configure the Requester |
hmc_local_link_config requester; |
hmc_local_link_config responder; |
|
`uvm_object_utils_begin(hmc_link_config) |
`uvm_field_int(tINIT, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(tRESP1, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(tRESP2, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(retry_timeout_period, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(scramblers_enabled, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(bit_rate, UVM_DEFAULT | UVM_DEC) |
`uvm_field_int(bit_time, UVM_DEFAULT | UVM_DEC) |
`uvm_field_object(requester, UVM_DEFAULT) |
`uvm_field_object(responder, UVM_DEFAULT) |
`uvm_field_int(hmc_tokens, UVM_DEC) |
`uvm_field_int(rx_tokens, UVM_DEC) |
`uvm_field_enum(uvm_active_passive_enum, cfg_rsp_open_loop, UVM_DEFAULT) |
`uvm_field_enum(uvm_active_passive_enum, enable_tag_checking, UVM_DEFAULT) |
|
`uvm_object_utils_end |
|
//-- Constraints |
|
constraint cube_id_c { |
cube_id >= 0; |
soft cube_id == 0; |
} |
|
constraint c_bit_rate { |
// Eventually allow 10, 12.5, and 15 Gb/s |
bit_rate == 10_000; //10Gbit/s = 10_000 Mbit/s |
} |
|
constraint c_bit_time { |
//bit_time > 0 && bit_time == 1us/bit_rate; |
bit_time == 100ps; // 10Gbit |
//bit_time == 80ps; // 12.5Gbit |
//bit_time == 66ps; // 15Gbit TODO: Rounding problems?!? |
} |
|
constraint hmc_tokens_c { |
hmc_tokens >= 25; |
soft hmc_tokens dist{[25:30]:/5, [31:219]:/95}; |
} |
|
constraint rx_tokens_c { |
rx_tokens >=30; |
soft rx_tokens dist{[9:30]:/5, [31:255]:/95}; |
} |
|
function new(string name="hmc_link_config"); |
super.new(name); |
requester = new; |
responder = new; |
endfunction : new |
|
function void post_randomize(); |
assert (requester.randomize()); |
assert (responder.randomize()); |
endfunction : post_randomize |
|
virtual function void do_print (uvm_printer printer); |
super.do_print(printer); |
requester.do_print(printer); |
responder.do_print(printer); |
endfunction : do_print |
|
endclass : hmc_link_config |
|
`endif // hmc_config_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_requester_sequence.sv
0,0 → 1,208
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_REQUESTER_SEQUENCE_SV |
`define HMC_REQUESTER_SEQUENCE_SV |
|
/* sequence is incomplete and not tested */ |
/* Use at your own risk */ |
|
class hmc_requester_sequence extends uvm_sequence; |
|
rand int delay; |
rand hmc_packet response; |
rand bit error_response; |
event item_available; |
|
hmc_packet response_queue[$]; |
|
constraint delay_c { |
delay dist {0:=4, [0:9]:=8, [10:30]:=2, [31:100]:=1}; |
} |
|
`uvm_object_utils(hmc_requester_sequence) |
|
`uvm_declare_p_sequencer(hmc_requester_sequencer) |
|
function new(string name="hmc_requester_sequence"); |
super.new(name); |
endfunction : new |
|
task create_response_packet(hmc_packet request); |
int response_length = 1; |
int new_timestamp; |
bit [127:0] rand_flit; |
bit [127:0] payload_flits [$]; |
|
`uvm_info(get_type_name(),$psprintf("Generating response for a %s @%0x",request.command.name(), request.address),UVM_HIGH) |
|
`uvm_create(response); |
|
void'(this.randomize(error_response)); |
void'(this.randomize(delay)); |
|
new_timestamp = delay * 500ps + $time; |
|
if (request.get_command_type() == HMC_READ_TYPE) begin : read |
|
case (request.command) |
HMC_READ_16 : response_length = 2; |
HMC_READ_32 : response_length = 3; |
HMC_READ_48 : response_length = 4; |
HMC_READ_64 : response_length = 5; |
HMC_READ_80 : response_length = 6; |
HMC_READ_96 : response_length = 7; |
HMC_READ_112 : response_length = 8; |
HMC_READ_128 : response_length = 9; |
endcase |
|
// Randomize the packet |
void'(response.randomize() with { |
command == HMC_READ_RESPONSE; |
address == request.address; // for debugging |
packet_length == response_length; |
duplicate_length == response_length; |
tag == request.tag; |
error_status == 0 || error_response; |
}); |
|
for (int i=0; i<response_length-1; i++) begin |
randomize_flit_successful : assert (std::randomize(rand_flit)) |
payload_flits.push_front(rand_flit); |
end |
|
response.payload = payload_flits; |
response.timestamp = new_timestamp; |
enqueue_response_packet(response); |
|
end : read |
else if (request.get_command_type() == HMC_WRITE_TYPE) begin : write |
|
response_length = 1; |
|
void'(response.randomize() with { |
command == HMC_WRITE_RESPONSE; |
address == request.address; // for debugging |
packet_length == response_length; |
duplicate_length == response_length; |
tag == request.tag; |
error_status == 0 || error_response; |
}); |
|
response.timestamp = new_timestamp; |
enqueue_response_packet(response); |
|
end : write |
// Posted Writes are allowed, but get no response |
else if ( request.get_command_type() != HMC_POSTED_WRITE_TYPE || |
request.get_command_type() != HMC_POSTED_MISC_WRITE_TYPE |
) begin : error |
uvm_report_fatal(get_type_name(), $psprintf("Unsupported command type %s", request.command.name())); |
end : error |
|
endtask : create_response_packet |
|
task enqueue_response_packet(hmc_packet response); |
// Insert at the end when the queue is empty or |
if (response_queue.size() == 0 || |
// when the timestamp is larger than the tail of the queue |
response.timestamp >= response_queue[response_queue.size()-1].timestamp) begin |
response_queue.push_back(response); |
// Insert at the beginning of the queue when the timestamp is small |
end else if (response.timestamp <= response_queue[0].timestamp) begin |
response_queue.push_front(response); |
end else begin |
for (int position=1;position < response_queue.size(); position++) begin |
if (response.timestamp < response_queue[position].timestamp) begin |
response_queue = {response_queue[0:position-1], response, response_queue[position:$]}; |
position = response_queue.size(); // Break |
end |
end |
end |
|
// Signal via event that a response has been added |
-> item_available; |
|
endtask : enqueue_response_packet |
|
task body(); |
|
void'(this.randomize()); |
|
fork |
// Convert requests to responses |
forever begin : tranlsate_loop |
hmc_packet packet; |
p_sequencer.req_mailbox.get(packet); |
create_response_packet(packet); |
end : tranlsate_loop |
|
// |
begin |
hmc_packet packet; |
|
forever begin : send_loop |
|
if (response_queue.size() > 0) begin |
int time_to_wait; |
|
time_to_wait = response_queue[0].timestamp - $time; |
if (time_to_wait <= 0) begin |
packet = response_queue.pop_front(); |
uvm_report_info(get_type_name(), $psprintf("Sending response packet: %s", packet.command.name()), UVM_HIGH); |
`uvm_send(packet) |
end else begin |
#time_to_wait; |
end |
end |
else begin |
// Wait for items to get added to the queue |
if (response_queue.size() == 0) |
@(item_available); |
end |
|
end : send_loop |
end |
join |
|
endtask : body |
|
endclass : hmc_requester_sequence |
|
`endif // HMC_REQUESTER_SEQUENCE_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_cdr.sv
0,0 → 1,132
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef hmc_cdr_SV |
`define hmc_cdr_SV |
class hmc_cdr #(parameter NUM_LANES = 16) extends uvm_component; |
|
event int_clk; |
|
virtual hmc_sr_if#(.NUM_LANES(NUM_LANES)) vif; |
hmc_link_config link_config; |
|
link_type_t link_type = REQUESTER; |
|
`uvm_component_param_utils_begin(hmc_cdr#(.NUM_LANES(NUM_LANES))) |
`uvm_field_enum(link_type_t, link_type, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new ( string name="hmc_cdr", uvm_component parent ); |
super.new(name, parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
if(uvm_config_db#(hmc_link_config )::get(this, "", "link_config",link_config) ) begin |
this.link_config = link_config; |
end else begin |
`uvm_fatal(get_type_name(),"link_config is not set") |
end |
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",vif) ) begin |
this.vif = vif; |
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
endfunction : build_phase |
|
|
task run_phase(uvm_phase phase); |
bit timeout = 0; |
|
time timeout_length; |
time wait_time; |
|
super.run_phase(phase); |
|
forever begin |
|
@(posedge vif.P_RST_N); //-- wait for leaving reset state |
fork |
begin |
@(negedge vif.P_RST_N); //-- entering reset state |
end |
begin |
|
timeout_length = link_config.bit_time; |
|
forever begin |
fork |
begin |
if(link_type == REQUESTER) |
@(vif.RXP); |
else |
@(vif.TXP); |
end |
begin |
#(timeout_length + 1ps); |
timeout = 1; |
end |
join_any |
disable fork; |
|
case (link_config.bit_time) |
100ps : wait_time = 50ps; |
80ps : wait_time = 40ps; |
66ps : wait_time = 30ps; |
endcase |
|
timeout_length = wait_time; |
|
if(timeout == 1) |
wait_time -= 1ps; |
|
#(wait_time); |
|
-> int_clk; |
|
timeout = 0; |
end |
end |
join_any; |
disable fork; |
end |
endtask : run_phase |
|
endclass :hmc_cdr |
|
`endif //hmc_cdr_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_responder_sequencer.sv
0,0 → 1,86
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_RESPONDER_SEQUENCER_SV |
`define HMC_RESPONDER_SEQUENCER_SV |
|
typedef class hmc_responder_sequence; |
|
class hmc_responder_sequencer extends uvm_sequencer #(hmc_packet); |
|
`uvm_analysis_imp_decl(_hmc_req) |
uvm_analysis_imp_hmc_req #(hmc_packet, hmc_responder_sequencer) hmc_req_port; |
mailbox #(hmc_packet) req_mailbox; |
|
`uvm_component_utils(hmc_responder_sequencer) |
|
hmc_responder_sequence resp_seq; |
|
function new(string name="hmc_responder_sequencer", uvm_component parent); |
super.new(name,parent); |
hmc_req_port = new("hmc_req_port", this); |
req_mailbox = new(); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
endfunction : connect_phase |
|
task run(); |
resp_seq = hmc_responder_sequence::type_id::create("resp_seq", this); |
resp_seq.start(this); |
endtask : run |
|
virtual function void write_hmc_req(input hmc_packet request); |
|
`uvm_info(get_type_name(),$psprintf("Request: %s",request.command.name()),UVM_HIGH) |
|
req_mailbox_not_full : assert (req_mailbox.try_put(request)); |
|
endfunction : write_hmc_req |
|
endclass : hmc_responder_sequencer |
|
`endif // HMC_RESPONDER_SEQUENCER_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_responder_driver.sv
0,0 → 1,316
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_RESPONDER_DRIVER_SV |
`define HMC_RESPONDER_DRIVER_SV |
|
class hmc_responder_driver#(parameter NUM_LANES=16) extends hmc_driver_base#(NUM_LANES); |
bit clear_error = 0; |
|
`uvm_component_param_utils(hmc_responder_driver#(.NUM_LANES(NUM_LANES))) |
|
function new(string name="hmc_responder_driver", uvm_component parent); |
super.new(name,parent); |
hmc_frp_port = new("hmc_frp_port", this); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
start_clear_retry_event = new("start_retry_event"); |
local_config = link_config.responder; |
|
if (!local_config.requester) begin |
tokens_to_send = link_config.hmc_tokens; |
|
`uvm_info(get_type_name(),$psprintf("initial_trets token_count = %0d", link_config.hmc_tokens), UVM_NONE) |
end else begin |
tokens_to_send = link_config.rx_tokens; |
|
`uvm_info(get_type_name(),$psprintf("initial_trets token_count = %0d", link_config.rx_tokens), UVM_NONE) |
end |
token_count_not_zero : assert (tokens_to_send > 0); |
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
super.run_phase(phase); |
|
forever begin |
if(vif.P_RST_N !== 1) begin |
next_state = RESET; |
end |
|
fork |
forever begin |
if (next_state != state) begin |
`uvm_info(get_type_name(),$psprintf("in state %s", next_state.name()), UVM_HIGH) |
end |
|
|
last_state = state; |
state = next_state; |
|
case (state) |
RESET: reset(); |
POWER_DOWN: power_down(); |
INIT: init(); |
PRBS: prbs(); |
NULL_FLITS: null_flits(); |
TS1: ts1(); |
NULL_FLITS_2: null_flits_2(); |
INITIAL_TRETS: initial_trets(); |
LINK_UP: link_up(); |
START_RETRY_INIT: start_retry_init(); |
CLEAR_RETRY: clear_retry(); |
SEND_RETRY_PACKETS: send_retry_packets(); |
endcase |
clear_error = 0; |
end |
begin |
@(negedge vif.P_RST_N); |
end |
forever begin |
start_clear_retry_event.wait_ptrigger(); |
start_clear_retry_event.reset(0); |
next_state = CLEAR_RETRY; |
`uvm_info(get_type_name(), "start retry event was triggered", UVM_HIGH) |
clear_error = 1; |
end |
begin |
time wait_time; |
@(negedge vif.RXPS); |
power_down_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_PST + 3*link_config.t_SS;}); |
#wait_time; |
vif.TXPS = 0; |
link_down_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_SME;}); |
#wait_time; |
next_state = POWER_DOWN; |
end |
clk_gen(); |
join_any; |
disable fork; |
end |
|
endtask : run_phase |
|
task reset(); |
|
vif.TXP = {NUM_LANES {1'bz}}; |
vif.TXN = {NUM_LANES {1'bz}}; |
vif.TXPS = 1'bz; |
vif.FERR_N = 1'bz; |
|
seq_num = 1; |
last_rrp = 0; |
init_continue = 0; |
can_continue = 0; |
retry_buffer.reset(); |
|
//wait for reset signal |
@(posedge vif.P_RST_N); |
reset_timestamp = $time; |
|
next_state = INIT; |
endtask : reset |
|
task power_down(); |
time wait_time; |
|
clear_lanes(); |
vif.TXP = {NUM_LANES {1'bz}}; |
vif.TXN = {NUM_LANES {1'bz}}; |
|
recover_from_power_down = 1; |
|
@(posedge vif.RXPS) |
//-- wait some time < t_pst |
power_up_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_PST + 3*link_config.t_SS;}); |
#wait_time; |
vif.TXPS = 1; |
//-- wait some time < t_sme |
link_up_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_SME;}); |
#wait_time; |
next_state = PRBS; |
|
endtask : power_down |
|
task init(); |
|
//wait for tINIT to pass |
while ($time < reset_timestamp + link_config.tINIT) |
@(posedge vif.REFCLKP); |
|
can_continue = 1; |
|
// TODO: Think of the "right" place to do this. |
// The problem is that it should happen in the sideband. |
// In our case, the sideband is software-controlled, not part of the controller. |
set_init_continue(); |
`uvm_info(get_type_name(),$psprintf("active = %0d retry prob = %0d", local_config.active, local_config.random_retry_probability), UVM_HIGH) |
|
//wait for init_continue to be set |
while (!init_continue) |
@(posedge vif.REFCLKP); |
|
//Set TXPS high |
vif.TXPS = 1'b1; |
|
//@(posedge vif.REFCLKP); |
|
next_state = PRBS; |
endtask : init |
|
task prbs(); |
int prbs_time; |
|
prbs_timestamp = $time; |
|
// send PRBS at least until Requester locks |
while (!(remote_status.current_state > PRBS)) |
for (int i=0; i < 4; i++) |
drive_fit({NUM_LANES/2 {i[1:0]}}); |
|
// Randomize PRBS length |
prbs_time_randomization_succeeds : assert (std::randomize(prbs_time) with {prbs_time > 0ns && prbs_time < link_config.tRESP1;}); |
`uvm_info(get_type_name(),$psprintf("prbs_time = %0d (between %0d and %0d)", prbs_time, 0ns, link_config.tRESP1), UVM_HIGH) |
|
for (int i=0; i < prbs_time/link_config.bit_time; i++) begin |
drive_fit({NUM_LANES/2 {i[1:0]}}); |
end |
|
next_state = NULL_FLITS; |
endtask : prbs |
|
task null_flits(); |
int null_time; |
|
null_timestamp = $time; |
|
reset_lfsr(); |
|
//wait for Requester to send TS1 |
while (!(remote_status.current_state >NULL_FLITS)) |
drive_fit({NUM_LANES {1'b0}}); |
|
req_ts1_timestamp = $time; |
|
//wait at most tRESP2 |
null_time_randomization_succeeds : assert (std::randomize(null_time) with {null_time > 0ns && null_time < link_config.tRESP2;}); |
`uvm_info(get_type_name(),$psprintf("null time = %0d ", null_time), UVM_HIGH) |
for (int i=0; i<null_time/link_config.bit_time-1; i++) begin |
drive_fit({NUM_LANES {1'b0}}); |
end |
|
next_state = TS1; |
endtask : null_flits |
|
task ts1(); |
int ts1_fits = 0; |
|
// Save the timestamp |
ts1_timestamp = $time; |
`uvm_info(get_type_name(), $psprintf("Sending TS1 Sequences"),UVM_MEDIUM) |
//wait for Requester to send NULL FLITs |
while (!(remote_status.current_state>TS1)) |
send_ts1(256); // 16 fits per sequence number, 16 sequence numbers |
|
next_state = NULL_FLITS_2; |
endtask : ts1 |
|
task null_flits_2(); |
int null_flit_count; |
|
null_flit_count_randomization_succeeds : assert (std::randomize(null_flit_count) with {null_flit_count >= 32 && null_flit_count < 512;}); |
|
//send NULL FLITs |
for (int i=0; i < null_flit_count; i++) |
drive_flit(128'h0); |
|
next_state = INITIAL_TRETS; |
endtask : null_flits_2 |
|
function void drive_lanes(input bit[NUM_LANES-1:0] new_value); |
int i; |
|
bit[NUM_LANES-1:0] lanes_reordered; |
|
if (local_config.reverse_lanes) begin |
for (i = 0; i < local_config.width; i= i+1) begin |
lanes_reordered[i] = new_value[local_config.width-i-1]; |
end |
end else begin |
lanes_reordered = new_value; |
end |
|
for (i = 0; i < local_config.width; i= i+1) begin |
bit set; |
lane_queues[i].push_back(lanes_reordered[i] ^ local_config.reverse_polarity[i]); |
|
if (local_config.lane_delays[i] <= lane_queues[i].size()) begin |
set = lane_queues[i].pop_front(); |
vif.TXP[i] = set; |
vif.TXN[i] = ~set; |
end |
end |
endfunction : drive_lanes |
|
task clear_lanes(); |
//-- while lane_queues.size >0 |
int i; |
bit empty = 1; |
while(empty) begin |
empty =0; |
@driver_clk; |
for (i = 0; i < local_config.width; i= i+1) begin |
logic set; |
if (lane_queues[i].size>0) begin |
empty = 1; |
set = lane_queues[i].pop_front(); |
vif.TXP[i] = set; |
vif.TXN[i] = ~set; |
end else begin |
vif.TXP[i] = 1'bz; |
vif.TXN[i] = 1'bz; |
end |
end |
end |
endtask : clear_lanes |
|
endclass : hmc_responder_driver |
|
`endif // HMC_RESPONDER_DRIVER_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_token_handler.sv
0,0 → 1,80
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_TOKEN_HANDLER_SV |
`define HMC_TOKEN_HANDLER_SV |
|
class hmc_token_handler extends uvm_component; |
|
`uvm_analysis_imp_decl(_tokens) |
uvm_analysis_imp_tokens#(hmc_packet, hmc_token_handler) token_imp; |
|
|
`uvm_component_utils(hmc_token_handler) |
|
int available_tokens; |
|
function new(string name="hmc_token_handler", uvm_component parent); |
super.new(name,parent); |
|
token_imp = new ("token_imp",this); |
available_tokens = 0; |
endfunction : new |
|
function void reset(); |
available_tokens = 0; |
endfunction : reset |
|
function void write_tokens(input hmc_packet packet); |
//`uvm_info(get_type_name(), $psprintf("write_tokens received %0d available_tokens = %0d", packet.return_token_count, available_tokens), UVM_HIGH) |
available_tokens = available_tokens + packet.return_token_count; |
endfunction : write_tokens |
|
function bit tokens_available(input int request); |
//`uvm_info(get_type_name(), $psprintf("tokens_available called for %0d available_tokens = %0d", request, available_tokens), UVM_HIGH) |
tokens_available = 0; |
if (available_tokens >= request) begin |
available_tokens = available_tokens - request; |
tokens_available = 1; |
end |
endfunction : tokens_available |
|
|
endclass : hmc_token_handler |
|
`endif // HMC_TOKEN_HANDLER_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_responder_agent.sv
0,0 → 1,111
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_RESPONDER_AGENT_SV |
`define HMC_RESPONDER_AGENT_SV |
|
class hmc_responder_agent #(parameter NUM_LANES = 16)extends uvm_agent; |
|
uvm_active_passive_enum active_passive = UVM_PASSIVE; |
|
hmc_monitor#(.NUM_LANES(NUM_LANES)) monitor; |
hmc_status h_status; |
|
hmc_responder_driver #(.NUM_LANES(NUM_LANES)) driver; |
hmc_responder_sequencer sequencer; |
hmc_token_handler token_handler; |
hmc_retry_buffer retry_buffer; |
|
hmc_transaction_mon req_transaction_mon; |
|
virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)) vif; |
|
`uvm_component_param_utils_begin(hmc_responder_agent#(.NUM_LANES(NUM_LANES))) |
`uvm_field_enum(uvm_active_passive_enum, active_passive, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="hmc_responder_agent", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(active_passive == UVM_ACTIVE) begin |
driver = hmc_responder_driver#(.NUM_LANES(NUM_LANES))::type_id::create("driver", this); |
sequencer = hmc_responder_sequencer::type_id::create("sequencer",this); |
token_handler = hmc_token_handler::type_id::create("token_handler",this); |
retry_buffer = hmc_retry_buffer::type_id::create("retry_buffer",this); |
end |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",vif) ) begin |
this.vif = vif; |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "driver","vif",vif); |
end |
|
if(!uvm_config_db#(hmc_status)::get(this, "", "h_status",h_status) ) begin |
`uvm_fatal(get_type_name(),"hmc_status is not set") |
end |
|
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
if(active_passive == UVM_ACTIVE) begin |
driver.seq_item_port.connect(sequencer.seq_item_export); |
|
driver.token_handler = token_handler; |
driver.retry_buffer = retry_buffer; |
|
driver.remote_status = h_status.Requester_link_status; |
|
monitor.frp_port.connect(driver.hmc_frp_port); |
req_transaction_mon.transaction_finished_port.connect(sequencer.hmc_req_port); |
monitor.return_token_port.connect(token_handler.token_imp); |
monitor.rrp_port.connect(retry_buffer.return_pointer_imp); |
driver.start_clear_retry_event = monitor.start_clear_retry_event; |
end |
|
endfunction : connect_phase |
|
endclass : hmc_responder_agent |
|
`endif // HMC_RESPONDER_AGENT_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_pkg.sv
0,0 → 1,87
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`include "hmc_sr_if.sv" |
//`include "hmc_base_types_pkg.sv" |
|
`timescale 1ps/1ps |
|
package hmc_pkg; |
|
`include "uvm_macros.svh" |
import uvm_pkg::*; |
import hmc_base_types_pkg::*; |
|
typedef enum { |
REQUESTER, |
RESPONDER |
} link_type_t; |
|
`include "hmc_config.sv" |
`include "hmc_tag_mon.sv" |
`include "hmc_transaction_mon.sv" |
|
`include "hmc_link_status.sv" |
|
|
`include "hmc_status.sv" |
`include "hmc_cdr.sv" |
|
`include "hmc_monitor.sv" |
`include "hmc_error_injector.sv" |
|
`include "hmc_token_handler.sv" |
`include "hmc_retry_buffer.sv" |
|
`include "hmc_driver_base.sv" |
|
`include "hmc_requester_driver.sv" |
`include "hmc_requester_sequencer.sv" |
`include "hmc_requester_sequence.sv" |
`include "hmc_requester_agent.sv" |
|
`include "hmc_responder_driver.sv" |
`include "hmc_responder_sequencer.sv" |
`include "hmc_responder_sequence.sv" |
`include "hmc_responder_agent.sv" |
|
|
`include "hmc_env.sv" |
|
endpackage : hmc_pkg |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_status.sv
0,0 → 1,65
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_STATUS_SV |
`define HMC_STATUS_SV |
|
class hmc_status extends uvm_component; |
|
hmc_link_status Requester_link_status; |
hmc_link_status Responder_link_status; |
|
function new ( string name="hmc_status", uvm_component parent ); |
|
super.new(name, parent); |
|
Requester_link_status = hmc_link_status::type_id::create("Requester_link_status", this); |
Responder_link_status = hmc_link_status::type_id::create("Responder_link_status", this); |
|
// Requester_link_status.set_Requester(1'b1); |
// Requester_link_status.set_remote(Responder_link_status); |
// |
// Responder_link_status.set_Requester(1'b0); |
// Responder_link_status.set_remote(Requester_link_status); |
|
endfunction : new |
|
|
endclass : hmc_status |
|
`endif // HMC_STATUS_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_tag_mon.sv
0,0 → 1,133
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// |
// hmc link tag checker |
// |
// |
|
`ifndef hmc_tag_mon_SV |
`define hmc_tag_mon_SV |
|
class hmc_tag_mon extends uvm_component; |
|
|
int tags_in_use[int]; |
int current_tag; |
int transaction_count; |
int max_tags_in_use; |
|
int max_tags_available = 512; |
|
|
covergroup tags_cg; |
option.per_instance = 1; |
TAGS_IN_USE : coverpoint tags_in_use.size(){ |
bins low_usage[] = {[1:20]}; |
bins medium_usage[] = {[21:250]}; |
bins high_usage[] = {[251:511]}; |
bins no_tags_available = {512}; |
} |
|
USED_TAGS : coverpoint current_tag{ |
bins TAGS[] = {[1:511]}; |
} |
endgroup |
|
`uvm_component_utils_begin(hmc_tag_mon) |
`uvm_field_int(max_tags_available, UVM_DEFAULT) |
`uvm_component_utils_end |
|
|
function new ( string name="hmc_tag_mon", uvm_component parent ); |
super.new(name, parent); |
tags_in_use.delete(); |
max_tags_in_use = 0; |
transaction_count = 0; |
tags_cg = new(); |
endfunction : new |
|
function void reset(); |
tags_in_use.delete(); |
endfunction : reset |
|
function void use_tag(input bit [8:0] tag); |
int tmp[]; |
|
if (tag > max_tags_available-1) |
`uvm_fatal(get_type_name(), $psprintf("use_tag: tag (%0d) out of range!", tag)) |
|
if(!tags_in_use.exists(tag) ) begin |
tags_in_use[tag] = tag; |
current_tag = tag; |
tags_cg.sample(); |
end |
|
endfunction : use_tag |
|
function void release_tag(input bit [8:0] tag); |
if (tags_in_use.exists(tag)) |
tags_in_use.delete(tag); |
else |
`uvm_fatal(get_type_name(), $psprintf("release_tag: tag (%0d) not in use!", tag)) |
|
transaction_count++; |
endfunction : release_tag |
|
function bit idle_check(); |
idle_check = 1; |
if (tags_in_use.size() > 0) begin |
foreach (tags_in_use[i]) |
`uvm_info(get_type_name(), $psprintf("%0d tags still in use, Tag %0d is in use!", tags_in_use.size(), i),UVM_LOW) |
idle_check = 0; |
end |
endfunction : idle_check |
|
function void check_phase(uvm_phase phase); |
if (!idle_check()) |
`uvm_fatal(get_type_name(),$psprintf("Tags are still in use")) |
endfunction : check_phase |
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("max_tags_in_use %0d, transaction_count %0d", max_tags_in_use, transaction_count), UVM_LOW) |
endfunction : report_phase |
|
endclass : hmc_tag_mon |
|
`endif // hmc_tag_mon_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_driver_base.sv
0,0 → 1,628
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_DRIVER_BASE_SV |
`define HMC_DRIVER_BASE_SV |
|
class hmc_driver_base#(parameter NUM_LANES = 16) extends uvm_driver #(hmc_packet); |
|
|
`uvm_analysis_imp_decl(_hmc_frp) |
uvm_analysis_imp_hmc_frp #(hmc_packet, hmc_driver_base#(.NUM_LANES(NUM_LANES))) hmc_frp_port; |
|
init_state_t next_state = RESET; |
init_state_t state = RESET; |
init_state_t last_state = LINK_UP; |
|
virtual interface hmc_sr_if #(.NUM_LANES(NUM_LANES)) vif; |
|
hmc_token_handler token_handler; |
hmc_retry_buffer retry_buffer; |
hmc_link_status remote_status; |
|
//-- The parameters for this link |
hmc_link_config link_config; |
|
//-- The parameters for this driver |
hmc_local_link_config local_config; |
|
//-- Packets to send |
hmc_packet packet_queue[$]; |
|
typedef bit lane_queue [$]; |
lane_queue lane_queues [NUM_LANES]; |
|
event driver_clk; |
|
uvm_event start_clear_retry_event; |
|
// Timestamps for debugging |
int reset_timestamp = 0; |
int prbs_timestamp = 0; |
int null_timestamp = 0; |
int req_ts1_timestamp = 0; |
int ts1_timestamp = 0; |
|
// Timestamps for controlling packet flow |
int last_packet_timestamp = 0; |
int start_retry_timestamp = 0; |
//-- error propability |
int next_poisoned = 0; |
int lng_error_prob = 0; |
int seq_error_prob = 0; |
int crc_error_prob = 0; |
|
bit recover_from_power_down = 0; |
|
// Count retry attempts signalled by the responder (from here) |
int retry_attempts = 0; |
|
// Count retry attempts from the requester |
int remote_retries_signalled = 0; |
int remote_retries_cleared = 0; |
int local_retries_signalled = 0; |
int local_retries_cleared = 0; |
|
// Internal state for scramblers |
bit [14:0] lfsr[NUM_LANES-1:0]; |
|
// Internal state for packets |
bit [2:0] seq_num = 1; |
|
// State for tokens and frp |
bit [7:0] frp_queue [$]; |
bit [7:0] last_frp = 0; |
bit [7:0] last_rrp; |
|
int tokens_to_send = 0; |
|
int used_tokens = 0; |
int sent_tokens = 0; |
|
bit [14:0] lfsr_seed[0:15] = { |
15'h4D56, |
15'h47FF, |
15'h75B8, |
15'h1E18, |
15'h2E10, |
15'h3EB2, |
15'h4302, |
15'h1380, |
15'h3EB3, |
15'h2769, |
15'h4580, |
15'h5665, |
15'h6318, |
15'h6014, |
15'h077B, |
15'h261F |
}; |
|
bit [15:8] ts1_high = 8'hF0; |
bit [7:4] ts1_top_lane = 4'hC; |
bit [7:4] ts1_bottom_lane = 4'h3; |
bit [7:4] ts1_middle_lane = 4'h5; |
|
// Configuration parameters |
bit init_continue; |
bit can_continue; |
|
`uvm_component_param_utils(hmc_driver_base #(.NUM_LANES(NUM_LANES))) |
|
function new(string name="hmc_driver_base", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
vif_found : assert (uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",this.vif)); |
config_found : assert (uvm_config_db#(hmc_link_config)::get(this, "", "link_config",link_config)); |
endfunction : build_phase |
|
virtual task run_phase(uvm_phase phase); |
super.run_phase(phase); |
endtask : run_phase |
|
task reset(); |
|
vif.TXP = {$size(vif.TXP) {1'bz}}; |
vif.TXN = {$size(vif.TXN) {1'bz}}; |
vif.TXPS = 1'bz; |
|
seq_num = 1; |
last_rrp = 0; |
init_continue = 0; |
can_continue = 0; |
retry_buffer.reset(); |
|
//-- wait for reset signal |
@(posedge vif.P_RST_N); |
reset_timestamp = $time; |
|
next_state = INIT; |
endtask : reset |
|
task clk_gen(); |
@(posedge vif.REFCLKP); |
forever begin |
#link_config.bit_time -> driver_clk; |
end |
endtask : clk_gen |
|
task send_ts1(int ts1_fits); |
bit [4:0] ts1_seq_num; |
bit [NUM_LANES-1:0] fit_val; |
bit [15:0] ts1_values [NUM_LANES-1:0]; |
|
ts1_values[0] = {ts1_high, ts1_bottom_lane, 4'h0}; |
for (int lane=1; lane < local_config.width-1; lane++) |
ts1_values[lane] = {ts1_high, ts1_middle_lane, 4'h0}; |
ts1_values[local_config.width-1] = {ts1_high, ts1_top_lane, 4'h0}; |
|
//Send some (possibly incomplete) TS1 flits |
while (ts1_fits > 0) begin |
// Cycle through all the sequence numbers |
for (ts1_seq_num=0; ts1_seq_num < 16 && ts1_fits > 0; ts1_seq_num++) begin |
// Add the sequence number to the ts1_values |
for (int i=0; i < local_config.width; i++) begin |
ts1_values[i][3:0] = ts1_seq_num; |
end |
// Send the fits of the ts1 values |
for (int fit=0; fit < 16; fit++) begin |
for (int lane=0; lane < local_config.width; lane++) begin |
fit_val[lane] = ts1_values[lane][fit]; |
end |
if (ts1_fits > 0) begin |
drive_fit(fit_val); |
end else begin |
drive_fit({NUM_LANES{1'b0}}); |
end |
ts1_fits = ts1_fits - 1; |
end |
end |
end |
endtask : send_ts1 |
|
task initial_trets(); |
hmc_packet tret = new(); |
//send TRET FLITs |
while (tokens_to_send > 0) begin |
init_tret_randomization : assert (tret.randomize() with { |
command == HMC_TRET; |
poisoned == 0; |
crc_error == 0; |
packet_length == 1; |
duplicate_length == 1; |
return_token_count <= tokens_to_send && return_token_count > 0; |
}); |
send_packet(tret); |
tokens_to_send = tokens_to_send - tret.return_token_count; |
end |
next_state = LINK_UP; |
endtask : initial_trets |
|
task link_up(); |
hmc_packet packet; |
|
get_packets(); |
|
if (packet_queue.size() > 0 && token_handler.tokens_available(packet_queue[0].packet_length) && (250- retry_buffer.get_buffer_used()) > packet_queue[0].packet_length ) begin |
packet = packet_queue.pop_front(); //-- send the first packet in the queue |
if ((next_poisoned < local_config.poisoned_probability)) |
send_poisoned(packet); |
else |
send_packet(packet); |
|
poisoned_propability_randomisation : assert (std::randomize(next_poisoned) with {next_poisoned > 0 && next_poisoned < 1000;}); |
|
end else if ($time-last_packet_timestamp > local_config.send_pret_time && frp_queue.size() > 0) begin |
`uvm_info(get_type_name(),$psprintf("sending pret, frp_queue size = %0d", frp_queue.size()), UVM_HIGH) |
send_pret(); |
end else if ($time-last_packet_timestamp > local_config.send_tret_time && (used_tokens - sent_tokens) > 0 &&(250- retry_buffer.get_buffer_used()) >1) begin |
`uvm_info(get_type_name(),$psprintf("sending tret, (<%0d)", used_tokens-sent_tokens), UVM_HIGH) |
send_tret(); |
end else begin |
drive_flit(128'h0); |
end |
|
// From here on, there are no packets being driven. This is just logic to decide the next state. |
|
//-- Handle error_abort_mode on remote link |
if (remote_status.get_error_abort_mode() && $time() - start_retry_timestamp > link_config.retry_timeout_period ) begin |
next_state = START_RETRY_INIT; |
end |
endtask : link_up |
|
task start_retry_init(); //-- send start retry IRTRYs |
|
start_retry_timestamp = $time; |
local_retries_signalled = local_retries_signalled + 1; |
`uvm_info(get_type_name(),$psprintf("sending start retry packets"), UVM_MEDIUM) |
|
//send IRTRY FLITs |
for (int i=0; i < local_config.irtry_flit_count_to_send; i++) |
send_irtry_start(); |
|
next_state = LINK_UP; |
endtask : start_retry_init |
|
task clear_retry(); //-- send clear error abort mode IRTRYs |
|
local_retries_cleared = local_retries_cleared + 1; |
//send IRTRY FLITs |
for (int i=0; i < local_config.irtry_flit_count_to_send; i++) |
send_irtry_clear(); |
next_state = SEND_RETRY_PACKETS; |
endtask : clear_retry |
|
task send_retry_packets(); |
hmc_packet packet; |
int spacer_flits; |
|
packet = retry_buffer.get_retry_packet(); |
while (packet != null) begin |
spacer_flits_randomization_succeeds : assert (std::randomize(spacer_flits) with {spacer_flits >= 0 && spacer_flits < 10;}); |
for (int i=0; i<spacer_flits; i++) begin |
drive_flit(128'h0); |
end |
retry_send_packet(packet); |
packet = retry_buffer.get_retry_packet(); |
end |
next_state = LINK_UP; |
endtask : send_retry_packets |
|
task get_packets(); |
hmc_packet packet; |
|
if( seq_item_port.has_do_available() ) begin |
if( packet_queue.size() == 0) begin |
seq_item_port.get_next_item(packet); |
packet_queue.push_back(packet); |
seq_item_port.item_done(); |
end |
end |
endtask : get_packets |
|
task send_irtry_start(); |
send_irtry(1,0); |
endtask : send_irtry_start |
|
task send_irtry_clear(); |
send_irtry(0,1); |
endtask : send_irtry_clear |
|
task send_irtry(input bit start, input bit clear); |
hmc_packet irtry = new(); |
|
irtry_randomization: assert (irtry.randomize() with { |
command == HMC_IRTRY; |
packet_length == 1; |
duplicate_length == 1; |
start_retry == start; |
clear_error_abort == clear; |
}); |
|
send_packet(irtry); |
endtask : send_irtry |
|
task send_tret(); |
|
hmc_packet tret = new(); |
|
tret_randomization: assert (tret.randomize() with { |
command == HMC_TRET; |
packet_length == 1; |
duplicate_length == 1; |
}); |
|
send_packet(tret); |
|
endtask : send_tret |
|
task send_pret(); |
|
hmc_packet pret = new(); |
|
pret_randomization: assert (pret.randomize() with { |
command == HMC_PRET; |
packet_length == 1; |
duplicate_length == 1; |
}); |
|
send_packet(pret); |
|
endtask : send_pret |
|
task send_poisoned(input hmc_packet pkt); |
hmc_packet poisoned = new pkt; //-- copy the pkt into a new one |
|
`uvm_info(get_type_name(),$psprintf("Poisoning Packet with command %s and tag %d", poisoned.command.name(), poisoned.tag),UVM_NONE) |
|
poisoned.poisoned = 1; |
send_packet(poisoned); |
|
packet_queue.push_back(pkt);//-- resent the packet later |
|
endtask : send_poisoned |
|
task send_packet(input hmc_packet pkt); |
int packet_frp; |
bit [31:0] crc; |
int bit_pos; |
int tok_cnt; |
// Save packet in Retry buffer if not IRTRY, NULL, or PRET |
// Tokens and Sequence numbers are saved in the retry buffer. |
|
if (pkt.command == HMC_IRTRY || |
pkt.command == HMC_NULL || |
pkt.command == HMC_PRET) begin |
packet_frp = 0; |
pkt.sequence_number = 0; |
retry_send_packet(pkt); |
end else begin |
pkt.sequence_number = seq_num; |
if (state != INITIAL_TRETS) begin |
if (used_tokens - sent_tokens > 0) begin |
// Always send tokens with TRETs |
if (pkt.command == HMC_TRET) |
tok_cnd_tret_randomization : assert (std::randomize(tok_cnt) with {(pkt.command == HMC_TRET && tok_cnt > 0) && tok_cnt < 32 && tok_cnt <= (used_tokens - sent_tokens);}); |
else |
tok_cnt_randomization_succeeds : assert (std::randomize(tok_cnt) with {(tok_cnt >= 0) && tok_cnt < 32 && tok_cnt <= (used_tokens - sent_tokens);}); |
pkt.return_token_count = tok_cnt; |
end else begin |
pkt.return_token_count = 0; |
end |
end |
packet_frp = retry_buffer.add_packet(pkt); |
if(packet_frp != -1)begin |
seq_num++; |
if (state != INITIAL_TRETS) begin |
sent_tokens += pkt.return_token_count; |
end |
// From now on, it's equivalent to retry |
`uvm_info(get_type_name(), $psprintf("Sending CDM %s with TRETS %d", pkt.command.name(), pkt.return_token_count), UVM_HIGH) |
retry_send_packet(pkt); |
end |
end |
endtask : send_packet |
|
task retry_send_packet(input hmc_packet pkt); |
bit [31:0] crc; |
int bit_pos; |
int bit_error; |
int error_type; |
int rrp_to_send; |
|
|
int pkt_lng; |
bit [2:0]seq_number; |
|
|
// Don't change the stored packet (except to clear the CRC error flag) |
hmc_packet copy = new pkt; |
|
// Return retry pointers are not saved. |
// Skip some retry pointers |
rrp_to_send_randomization_succeeds : assert (std::randomize(rrp_to_send) with {rrp_to_send >= 0 && rrp_to_send <= frp_queue.size();}); |
if (rrp_to_send == 0) begin |
copy.return_retry_pointer = last_rrp; |
end else begin |
for (int i=0;i<rrp_to_send;i++) begin |
copy.return_retry_pointer = frp_queue.pop_front(); |
`uvm_info(get_type_name(),$psprintf("popped %0d for frp in %s", copy.return_retry_pointer, copy.command.name()),UVM_HIGH) |
end |
end |
last_rrp = copy.return_retry_pointer; |
|
//-- ERROR INJECTION |
|
//-- adding sequence error |
error_type_seq_error_randomization : assert (std::randomize(seq_error_prob) with {seq_error_prob > 0 && seq_error_prob < 1000;}); |
if (seq_error_prob < local_config.seq_error_probability) begin |
randcase |
1: copy.sequence_number = copy.sequence_number + 1; |
1: copy.sequence_number = copy.sequence_number - 1; |
1: begin |
random_SEQ_succeeds : assert( |
std::randomize(seq_number) with { seq_number !=copy.sequence_number;}); |
copy.sequence_number = seq_number; |
end |
endcase |
`uvm_info(get_type_name(),$psprintf("injecting SEQ error in CMD %s and FRP %d",copy.command.name(), copy.forward_retry_pointer), UVM_NONE) |
end |
|
|
//-- inserting Length Error |
error_type_lng_error_randomization : assert (std::randomize(lng_error_prob) with {lng_error_prob > 0 && lng_error_prob < 1000;}); |
if (lng_error_prob < local_config.lng_error_probability) begin |
randcase |
1: copy.packet_length = copy.packet_length + 1; |
1: copy.packet_length = copy.packet_length - 1; |
1: copy.duplicate_length = copy.duplicate_length + 1; |
1: copy.duplicate_length = copy.duplicate_length - 1; |
1: begin random_LNG_succeeds : assert( |
std::randomize(pkt_lng) with {pkt_lng >= 0 && pkt_lng < 16 && pkt_lng !=copy.packet_length;}); |
copy.packet_length = pkt_lng; |
end |
1: begin random_DLN_succeeds : assert( |
std::randomize(pkt_lng) with {pkt_lng >= 0 && pkt_lng < 16 && pkt_lng !=copy.duplicate_length;}); |
copy.duplicate_length = pkt_lng; |
end |
endcase |
end |
|
crc = copy.calculate_crc(); //-- calculate crc for packet with valid tail |
|
|
//-- poisoning packets |
if (copy.poisoned) begin |
`uvm_info(get_type_name(),$psprintf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX poisoning packet with CRC %0x and CMD %s and TAG %d", ~crc, copy.command.name(), copy.tag),UVM_LOW) |
crc = ~crc; |
end |
|
|
//-- inserting CRC error |
error_type_crc_error_randomization : assert (std::randomize(crc_error_prob) with {crc_error_prob > 0 && crc_error_prob < 1000;}); |
if (crc_error_prob < local_config.crc_error_probability * copy.packet_length) begin //-- increase the crc error probability for longer packets |
int clear_crc_error; |
crc_bit_error_randomization_succeeds : assert (std::randomize(bit_pos) with {bit_pos >= 0 && bit_pos < 32;}); |
`uvm_info(get_type_name(),$psprintf("inserting crc error at %0x", bit_pos),UVM_LOW) |
crc[bit_pos] = !crc[bit_pos]; |
clear_crc_error_randomization_succeeds : assert (std::randomize(clear_crc_error) with {clear_crc_error >= 0 && clear_crc_error < 3;}); |
if (clear_crc_error == 1) |
pkt.crc_error = 0; |
end |
copy.packet_crc = crc; |
drive_tx_packet(copy); |
|
endtask : retry_send_packet |
|
task drive_fit(input bit[NUM_LANES-1:0] new_value); |
if (link_config.scramblers_enabled) begin |
drive_lanes(get_scrambler_value()^new_value); |
end else begin |
drive_lanes(new_value); |
end |
@driver_clk; |
step_scramblers(); |
endtask : drive_fit |
|
task drive_flit(input bit [127:0] flit); |
int i; |
bit [15:0] fits [16]; |
|
for (int i=0; i<128; i++) |
fits[i/local_config.width][i%local_config.width] = flit[i]; |
|
for (int i=0; i<128/local_config.width;i++) begin |
drive_fit(fits[i]); |
end |
|
endtask : drive_flit |
|
task drive_tx_packet(input hmc_packet pkt); |
bit bitstream[]; |
bit [127:0] flits [9]; // Max packet size is 9 flits |
bit [127:0] curr_flit; |
int i; |
int bitcount; |
bitcount = pkt.pack(bitstream); |
|
for (int i=0; i<bitcount; i++) |
flits[i/128][i%128] = bitstream[i]; |
for (int i=0; i<bitcount/128; i++) begin |
drive_flit(flits[i]); |
end |
|
last_packet_timestamp = $time; |
|
endtask : drive_tx_packet |
|
virtual function void drive_lanes(input bit[NUM_LANES-1:0] new_value); |
`uvm_info(get_type_name(),$psprintf("called virtual function drive_lanes!"), UVM_HIGH) |
endfunction : drive_lanes |
|
function void reset_lfsr(); |
int i; |
|
for (i = 0; i < NUM_LANES; i= i+1) begin |
if (local_config.reverse_lanes == 1) |
lfsr[i] = lfsr_seed[NUM_LANES-1-i]; |
else |
lfsr[i] = lfsr_seed[i]; |
end |
endfunction : reset_lfsr |
|
function void step_scramblers(); |
int i; |
|
if (link_config.scramblers_enabled) begin |
for (i = 0; i < NUM_LANES; i= i+1) begin |
lfsr[i] = {lfsr[i][1]^lfsr[i][0], lfsr[i][14:1]}; |
end |
end |
endfunction : step_scramblers |
|
function bit[NUM_LANES-1:0] get_scrambler_value(); |
int i; |
|
if (link_config.scramblers_enabled) begin |
for (i = 0; i < NUM_LANES; i= i+1) begin |
get_scrambler_value[i] = lfsr[i][0]; |
end |
end else begin |
for (i = 0; i < NUM_LANES; i= i+1) begin |
get_scrambler_value = {NUM_LANES {1'b0}}; |
end |
end |
endfunction : get_scrambler_value |
|
// I2C or JTAG would configure the HMC during reset |
function void set_init_continue(); |
tb_respects_tINIT : assert (can_continue); |
init_continue = 1; |
endfunction : set_init_continue |
|
virtual function void write_hmc_frp(input hmc_packet pkt); |
|
bit [7:0] frp; |
int random_wait; |
|
`uvm_info(get_type_name(),$psprintf("hmc_frp: %s with FRP %0d & size %0d",pkt.command.name(), pkt.forward_retry_pointer, pkt.packet_length),UVM_HIGH) |
|
// IRTRY and PRET do not have valid frp fields |
if (pkt.command != HMC_IRTRY && pkt.command != HMC_PRET) begin |
frp = pkt.forward_retry_pointer; |
if (frp != last_frp) begin |
frp_queue.push_back(frp); |
last_frp = frp; |
end |
end |
|
if (pkt.get_command_type != HMC_FLOW_TYPE && !pkt.poisoned ) begin |
used_tokens_does_not_overflow : assert ( used_tokens < used_tokens + pkt.packet_length); |
used_tokens = used_tokens + pkt.packet_length; |
end |
|
endfunction : write_hmc_frp |
|
endclass : hmc_driver_base |
|
`endif // HMC_DRIVER_BASE_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_error_injector.sv
0,0 → 1,178
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
`ifndef HMC_ERROR_INJECTOR |
`define HMC_ERROR_INJECTOR |
|
class hmc_error_injector #(parameter NUM_LANES = 16) extends uvm_component; |
|
virtual hmc_sr_if#(.NUM_LANES(NUM_LANES)) ext_vif; |
virtual hmc_sr_if#(.NUM_LANES(NUM_LANES)) int_vif; |
hmc_cdr #(.NUM_LANES(NUM_LANES)) cdr; |
|
|
hmc_link_config link_config; |
hmc_local_link_config local_config; |
hmc_link_status link_status; |
|
logic [NUM_LANES - 1 : 0] current_value; |
int num_bitflips; |
int inserted_bitflips[]; |
|
`uvm_component_param_utils_begin(hmc_error_injector#(.NUM_LANES(NUM_LANES))) |
`uvm_component_utils_end |
|
function new ( string name="hmc_error_injector", uvm_component parent ); |
super.new(name, parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(uvm_config_db#(hmc_link_config)::get(this, "", "link_config",link_config) ) begin |
uvm_config_db#(hmc_link_config)::set(this, "cdr","link_config",link_config); |
end else begin |
`uvm_fatal(get_type_name(),"link_config is not set") |
end |
|
if(!uvm_config_db#(hmc_local_link_config)::get(this, "", "local_config",local_config) ) begin |
`uvm_fatal(get_type_name(),"local_config is not set") |
end |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "ext_vif",ext_vif) ) begin |
this.ext_vif = ext_vif; |
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "int_vif",int_vif) ) begin |
this.int_vif = int_vif; |
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
|
if(!uvm_config_db#(hmc_link_status)::get(this, "", "link_status",link_status) ) begin |
`uvm_fatal(get_type_name(),"link_status is not set") |
end |
|
if (local_config.requester) begin |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "cdr","vif",ext_vif); |
end else begin |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "cdr","vif",int_vif); |
end |
|
set_config_int("cdr", "link_type", local_config.requester?REQUESTER:RESPONDER); |
|
cdr = hmc_cdr#(.NUM_LANES(NUM_LANES))::type_id::create("cdr", this); |
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
endfunction : connect_phase |
|
|
task run_phase(uvm_phase phase); |
#1ps; |
read(); |
write(); |
forever begin |
@(cdr.int_clk) |
read(); |
if (local_config.lane_errors_enabled && link_status.current_state >= LINK_UP) |
inject_error(); |
write(); |
end |
endtask : run_phase |
|
function void read(); |
if (local_config.requester) begin |
current_value = ext_vif.RXP; |
end else begin |
current_value = int_vif.TXP; |
end |
endfunction |
|
function void write(); |
logic [NUM_LANES - 1 : 0] inv_value; |
|
foreach(current_value[i]) begin |
if (!(current_value[i] === 1'bz)) |
inv_value[i] = ~current_value[i]; |
else begin |
inv_value[i] = 1'bz; |
end |
end |
|
if (local_config.requester) begin |
int_vif.RXP = current_value; |
int_vif.RXN = inv_value; |
end else begin |
ext_vif.TXP = current_value; |
ext_vif.TXN = inv_value; |
end |
endfunction : write |
|
function void inject_error(); |
int error_probability; |
error_prob_rand_succeeds : assert (std::randomize(error_probability) |
with {error_probability >= 0 && error_probability < 10000;}); |
if (error_probability < local_config.bitflip_error_probability) begin |
num_error_rand_succeeds : assert(std::randomize(num_bitflips) |
with {num_bitflips>0 && num_bitflips<NUM_LANES;}); |
`uvm_info(get_type_name(), $psprintf("Inserting %0d Bitflips in %s Link",num_bitflips, local_config.requester?"requester":"responder"), UVM_HIGH) |
bitflip(num_bitflips); |
end |
endfunction : inject_error |
|
function void bitflip(int bits); |
int pos = -1; |
int last_pos[int]; |
for (int i= 0; i < bits; i++) begin |
while (last_pos[pos] == 1 || pos == -1)begin //-- inject bitflip only once per lane |
pos_randomization_succeeds : assert (std::randomize(pos) with {pos >= 0 && pos < NUM_LANES;}); |
end |
last_pos[pos] = 1; |
current_value[pos] = ~current_value[pos]; |
`uvm_info(get_type_name(), $psprintf("Inserting Bitflip at %d in %s Link", pos, local_config.requester?"requester":"responder"), UVM_HIGH) |
end |
endfunction : bitflip |
|
endclass : hmc_error_injector |
|
|
`endif |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_monitor.sv
0,0 → 1,1062
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// |
// hmc_packet monitor |
// |
// |
|
`ifndef HMC_MONITOR_SV |
`define HMC_MONITOR_SV |
|
class hmc_monitor#(parameter NUM_LANES = 16) extends uvm_monitor; |
|
virtual hmc_sr_if#(.NUM_LANES(NUM_LANES)) vif; |
|
hmc_link_config link_config; |
hmc_local_link_config local_config; |
hmc_status status; |
hmc_link_status link_status; |
hmc_link_status remote_link_status; |
hmc_transaction_mon transaction_mon; |
hmc_cdr #(.NUM_LANES(NUM_LANES)) cdr; |
|
uvm_analysis_port #(hmc_packet) item_collected_port; |
uvm_analysis_port #(hmc_packet) return_token_port; |
uvm_analysis_port #(hmc_packet) frp_port; |
uvm_analysis_port #(int) rrp_port; |
|
uvm_event start_clear_retry_event; |
event lane_queue_event; //-- triggers after write to any lane queue |
event flit_queue_event; //-- triggers after write to the collected_flits queue |
|
// Partial flits from each lane |
typedef bit [14:0] lsfr_t; |
typedef bit [15:0] partial_flit_t; |
typedef bit [127:0] flit_t; |
// Queue of unassembled flits (per lane) |
typedef partial_flit_t partial_flit_queue_t[$]; |
partial_flit_queue_t lane_queues[]; |
|
|
|
bit [2:0] next_sequence_num; |
bit lane_reversal_set = 0;//-- TODO move to link_status |
|
bit bitstream[$]; |
bit [127:0] collected_flits[$]; |
|
|
hmc_packet collected_packet; |
|
//-- reporting counter |
int lng_error = 0; |
int crc_error = 0; |
int seq_error = 0; |
int poisoned_pkt =0; |
|
|
typedef enum { |
LENGTH_ERROR, |
CRC_ERROR, |
SEQ_ERROR, |
POISON, |
INVALID_TS1 |
}error_class_e; |
|
//-- coverage --// |
int packets_after_Link_up = 0; |
int start_retry_count = 0; |
int clear_error_abort_count = 0; |
error_class_e current_error; |
|
int null_flits_after_TS1 = 0; |
int null_flits_between_pkts = 0; |
|
|
covergroup hmc_pkt_error_cg; |
option.per_instance = 1; |
ERROR_TYPE: coverpoint current_error; |
|
HMC_COMMAND: coverpoint collected_packet.command { |
bins flow_types[] = { |
HMC_TRET, |
HMC_PRET, |
HMC_NULL, |
HMC_IRTRY |
}; |
bins requests[] = { |
HMC_WRITE_16, |
HMC_WRITE_32, |
HMC_WRITE_48, |
HMC_WRITE_64, |
HMC_WRITE_80, |
HMC_WRITE_96, |
HMC_WRITE_112, |
HMC_WRITE_128, |
|
HMC_MODE_WRITE, |
HMC_BIT_WRITE, |
HMC_DUAL_8B_ADDI, |
HMC_SINGLE_16B_ADDI, |
|
HMC_POSTED_WRITE_16, |
HMC_POSTED_WRITE_32, |
HMC_POSTED_WRITE_48, |
HMC_POSTED_WRITE_64, |
HMC_POSTED_WRITE_80, |
HMC_POSTED_WRITE_96, |
HMC_POSTED_WRITE_112, |
HMC_POSTED_WRITE_128, |
HMC_POSTED_BIT_WRIT, |
|
HMC_POSTED_BIT_WRIT, |
HMC_POSTED_DUAL_8B_ADDI, |
HMC_POSTED_SINGLE_16B_ADDI, |
|
HMC_MODE_READ, |
HMC_READ_16, |
HMC_READ_32, |
HMC_READ_48, |
HMC_READ_64, |
HMC_READ_80, |
HMC_READ_96, |
HMC_READ_112, |
HMC_READ_128}; |
|
bins response[] = { |
HMC_READ_RESPONSE, |
HMC_WRITE_RESPONSE, |
HMC_MODE_READ_RESPONSE, |
HMC_MODE_WRITE_RESPONSE, |
HMC_ERROR_RESPONSE |
}; |
illegal_bins n_used = default; |
} |
CROSS_ERROR_TYPPE_COMMAND : cross ERROR_TYPE, HMC_COMMAND { |
ignore_bins SEQ_IGNORE = binsof(ERROR_TYPE) intersect {SEQ_ERROR} && binsof(HMC_COMMAND) intersect {HMC_NULL, HMC_PRET, HMC_IRTRY}; |
ignore_bins POISON_IGNORE = binsof(ERROR_TYPE) intersect {POISON} && binsof(HMC_COMMAND) intersect {HMC_NULL}; |
} |
endgroup |
|
|
covergroup null2_cg; |
option.per_instance = 1; |
NULL2_count : coverpoint null_flits_after_TS1+ null_flits_between_pkts{ //-- Link_up is reached after 32 consecutive flits |
illegal_bins ib = {[0:31]}; |
bins minimum_amount = {32}; |
bins low_amount[] = {[33:50]}; |
bins medium_amount[] = {[51:100]}; |
bins high_amount = {[101:$]}; |
} |
endgroup |
|
|
covergroup hmc_packets_cg; |
option.per_instance = 1; |
|
NULLS_BETWEEN_PACKETS : coverpoint null_flits_between_pkts{ |
bins low_amount[] = {[0:20]}; |
bins medium_amount[] = {[21:199]}; |
bins high_amount ={[200:$]}; |
} |
COMMAND : coverpoint collected_packet.command; |
PAYLOAD_LENGTH : coverpoint collected_packet.duplicate_length -1{ |
bins no_payload = {0}; |
bins payload[] = {[1:8]}; |
} |
CROSS_COMMAND_NULLS : cross COMMAND,NULLS_BETWEEN_PACKETS; |
endgroup |
|
|
covergroup hmc_link_cg; |
option.per_instance = 1; |
LINK_REVERSAL : coverpoint link_status.lane_reversed; |
Link_WIDTH : coverpoint NUM_LANES{ |
bins half_width = {8}; |
bins full_width = {16}; |
} |
CROSS_LANE_LINK_REVERSAL_WIDTH : cross Link_WIDTH, LINK_REVERSAL; |
endgroup |
|
|
covergroup tokens_cg; |
option.per_instance = 1; |
TOKEN_AVAILABLE : coverpoint link_status.token_count{ |
bins no_token_available = {0}; |
bins very_low_amount_available[] = {[1:9]}; |
bins low_amount_available[] = {[10:30]}; |
bins medium_amount_available[] = {[31:100]}; |
bins high_amount_available = {[101:$]}; |
} |
FPW : coverpoint link_config.fpw { |
bins legal_fpw[] = {2,4,6,8}; |
} |
CROSS_FPW_TOKENS : cross FPW, TOKEN_AVAILABLE; |
endgroup |
|
`uvm_component_param_utils(hmc_monitor#(.NUM_LANES(NUM_LANES))) |
|
|
function new ( string name="hmc_monitor", uvm_component parent ); |
|
super.new(name, parent); |
|
lane_queues = new[NUM_LANES] (lane_queues); |
|
hmc_pkt_error_cg = new(); |
hmc_packets_cg = new(); |
hmc_link_cg = new(); |
tokens_cg = new(); |
null2_cg = new(); |
|
item_collected_port = new("item_collected_port", this); |
return_token_port = new("return_token_port", this); |
frp_port = new("frp_port", this); |
rrp_port = new("rrp_port", this); |
next_sequence_num = 3'b1; |
|
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",vif) ) begin |
this.vif = vif; |
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
if(!uvm_config_db#(hmc_link_config)::get(this, "", "link_config",link_config) ) begin |
`uvm_fatal(get_type_name(),"link_config is not set") |
end |
|
if(!uvm_config_db#(hmc_local_link_config)::get(this, "", "local_config",local_config) ) begin |
`uvm_fatal(get_type_name(),"local_config is not set") |
end |
|
|
if(!uvm_config_db#(hmc_status)::get(this, "", "status",status) ) begin |
`uvm_fatal(get_type_name(),"Responder_link_status is not set") |
end |
|
if (item_collected_port == null) |
`uvm_fatal(get_type_name(), "uvm_analysis_port not ready") |
|
|
start_clear_retry_event = new ("start_retry_event"); |
link_status = local_config.requester?status.Requester_link_status:status.Responder_link_status; |
remote_link_status = (!local_config.requester)?status.Requester_link_status:status.Responder_link_status; |
|
set_config_int("cdr", "link_type", local_config.requester?REQUESTER:RESPONDER); |
|
cdr = hmc_cdr#(.NUM_LANES(NUM_LANES))::type_id::create("cdr", this); |
|
// This should be a better check for the BFM. |
if (!link_config.responder.active) begin |
status.Responder_link_status.set_relaxed_token_handling(1); |
end |
|
|
endfunction : build_phase |
|
function logic get_bit(input bit Requester, input int lane); |
if (Requester) |
get_bit = vif.RXP[lane]; |
else |
get_bit = vif.TXP[lane]; |
endfunction : get_bit |
|
function bit check_lane_queues_not_empty(); |
bit full = 1; |
foreach (lane_queues[i]) begin |
if (lane_queues[i].size()==0) |
full = 0; |
end |
return full; |
endfunction |
|
task check_clock(); |
int i; |
int start_time = 0; |
int clock_period = 0; |
int expected_period = 0; |
|
`uvm_info(get_type_name(),$psprintf("started clock check %0d", $time), UVM_HIGH) |
forever begin |
|
if (vif.P_RST_N !== 1) // Reset |
begin |
@(posedge vif.P_RST_N); |
|
// Sample REFCLK_BOOT pins |
case (vif.REFCLK_BOOT) |
2'b00: expected_period = 8ns; // 125 MHz |
2'b01: expected_period = 6.4ns; // 156.25 MHz |
2'b10: expected_period = 6ns; // 166.66 MHz |
2'b11: `uvm_fatal(get_type_name(),$psprintf("REFCLK_BOOT setting %0d invalid!", vif.REFCLK_BOOT)) |
endcase |
|
// Sample REFCLKP |
@(posedge vif.REFCLKP); |
start_time = $time; |
|
for (i=0;i<100;i++) |
@(posedge vif.REFCLKP); |
clock_period = ($time-start_time)/100; |
|
`uvm_info(get_type_name(),$psprintf("clock_period = %0d expected = %0d", clock_period, expected_period), UVM_HIGH) |
|
if (clock_period != expected_period) |
`uvm_fatal(get_type_name(),$psprintf("clock_period %0d (p) != expected %0d!", clock_period, expected_period)); |
|
// Sample REFCLKN |
@(posedge vif.REFCLKN); |
start_time = $time; |
|
for (i=0;i<100;i++) |
@(posedge vif.REFCLKN); |
clock_period = ($time-start_time)/100; |
|
if (clock_period != expected_period) |
`uvm_fatal(get_type_name(),$psprintf("clock_period (n) %0d != expected %0d!", clock_period, expected_period)); |
|
end |
@(negedge vif.P_RST_N); |
end |
endtask : check_clock |
|
task monitor_power_pins(); |
if (local_config.requester) begin |
link_status.signal_power_state(vif.RXPS); |
forever begin |
@(vif.RXPS) |
if (vif.RXPS == 1'b0) |
CHK_IDLE_BEFORE_REQUESTER_POWERDOWN: assert (idle_check()) //-- check if Link is IDLE |
else begin |
`uvm_fatal(get_type_name(),$psprintf("link is not IDLE")) |
end |
link_status.signal_power_state(vif.RXPS); |
end |
end else begin |
link_status.signal_power_state(vif.TXPS); |
forever begin |
@(vif.TXPS) |
if (vif.TXPS == 1'b0) |
CHK_IDLE_BEFORE_RESPONDER_POWERDOWN: assert (idle_check()) //-- check if Link is IDLE |
else begin |
`uvm_fatal(get_type_name(),$psprintf("link is not IDLE")) |
end |
link_status.signal_power_state(vif.TXPS); |
end |
end |
endtask : monitor_power_pins |
|
task descramble(input int lane); |
partial_flit_t partial_flit; |
lsfr_t lfsr; |
lsfr_t calculated_lfsr; |
bit last_bit; |
bit alligned = 0; |
int run_length_count = 0; |
|
`uvm_info(get_type_name(),$psprintf("%s lane %0d descrambler started", local_config.requester?"Requester":"Responder", lane), UVM_HIGH) |
forever begin |
if (link_status.current_state == RESET || link_status.current_state == POWER_DOWN) /*RESET*/ |
begin |
logic test; |
@(link_status.current_state); |
`uvm_info(get_type_name(), "Waiting for valid bit", UVM_HIGH) |
test = local_config.requester?vif.RXP[lane]:vif.TXP[lane]; |
while (test === 1'bz)begin |
@(cdr.int_clk) |
test = local_config.requester?vif.RXP[lane]:vif.TXP[lane]; |
end |
end |
|
else if (!link_status.get_locked(lane)) /*LOCK SCRAMBLER*/ |
begin |
|
lfsr = calculated_lfsr; |
//-- Guess that the top bit is 0 to lock when scrambling is turned off |
calculated_lfsr[14] = (link_config.scramblers_enabled? 1'b1 : 1'b0); |
for (int i=0; i<14; i++) |
begin |
calculated_lfsr[i] = get_bit(local_config.requester,lane) ^ last_bit; |
last_bit = get_bit(local_config.requester,lane); |
|
@(cdr.int_clk); |
lfsr = {lfsr[1]^lfsr[0], lfsr[14:1]}; // step the LFSR |
end |
if (lane == 0) |
`uvm_info(get_type_name(),$psprintf("%s lane 0 calculated_lfsr=%0x lfsr=%0x", local_config.requester?"Requester":"Responder", calculated_lfsr, lfsr), UVM_HIGH) |
if (lfsr == calculated_lfsr) begin |
/*Inversion check*/ |
if (get_bit(local_config.requester,lane) ^ lfsr[0]) begin |
link_status.set_inverted(lane); |
`uvm_info(get_type_name(),$psprintf("%s lane %0d is inverted", local_config.requester?"Requester":"Responder", lane),UVM_LOW) |
end |
Requester_locks_before_Responder : assert (local_config.requester || status.Requester_link_status.get_all_lanes_locked()); |
link_status.set_locked(lane); |
end |
end |
else if (!link_status.get_nonzero(lane)) /*WAIT FOR POSSIBLE TS1 (non-zero)*/ |
begin |
`uvm_info(get_type_name(),$psprintf("locked on %s lane %0d inverted = %0x lfsr=%0x", local_config.requester?"Requester":"Responder", lane,link_status.get_inverted(lane), lfsr), UVM_HIGH) |
while (get_bit(local_config.requester,lane) ^ lfsr[0] ^ link_status.get_inverted(lane) == 0) |
begin |
lfsr = {lfsr[1]^lfsr[0], lfsr[14:1]}; //-- Every clock after lock, step the LFSR |
@(cdr.int_clk); |
end |
link_status.set_nonzero(lane); |
end |
else if (!link_status.get_aligned(lane)) /*ALIGN WITH TS1*/ |
begin |
|
`uvm_info(get_type_name(),$psprintf("looking for TS1 on %s lane %0d", local_config.requester?"Requester":"Responder", lane), UVM_HIGH) |
partial_flit[7:0] = 8'hff; |
while (!link_status.get_aligned(lane)) begin |
//-- shift until a possible TS1 sequence is detected |
|
partial_flit = partial_flit >> 1; |
partial_flit[7] = get_bit(local_config.requester,lane) ^ lfsr[0] ^ link_status.get_inverted(lane); |
lfsr = {lfsr[1]^lfsr[0], lfsr[14:1]}; //-- Every clock after lock, step the LFSR |
@(cdr.int_clk); |
|
if (partial_flit[7:0] == 8'hf0) begin //-- found potential TS1 sequence |
//-- check next partial flits |
alligned = 1; |
for (int i = 0; i <local_config.TS1_Messages; i++) begin |
//-- read next partial flit |
for (int i=0; i<16; i++) begin |
partial_flit[i] = get_bit(local_config.requester,lane) ^ lfsr[0] ^ link_status.get_inverted(lane); |
lfsr = {lfsr[1]^lfsr[0], lfsr[14:1]}; // Every clock after lock, step the LFSR |
@(cdr.int_clk); |
end |
`uvm_info(get_type_name(),$psprintf("partial_flit=%0x", partial_flit), UVM_HIGH) |
if (partial_flit[15:8] != 8'hf0)begin |
`uvm_info(get_type_name(),$psprintf("Alignment Error, retry"), UVM_NONE) |
alligned = 0; |
continue;//-- retry |
end |
if (alligned) begin |
link_status.set_aligned(lane); |
|
`uvm_info(get_type_name(),$psprintf("%s lane %0x aligned", local_config.requester?"Requester":"Responder", lane), UVM_HIGH) |
end |
end |
end |
end |
run_length_count = 0; |
end |
else /*NORMAL OPERATION*/ |
begin |
for (int i=0; i<16; i++) |
begin |
// Check Run current_packet_length limit |
if (last_bit == get_bit(local_config.requester,lane)) |
begin |
run_length_count = run_length_count + 1; |
|
if ((run_length_count >= local_config.run_length_limit) && link_config.scramblers_enabled) |
`uvm_fatal(get_type_name(),$psprintf("last_bit=%0x repeated %0d times on %s lane %0d" |
, last_bit, run_length_count, local_config.requester?"Requester":"Responder", lane)); |
end else begin |
run_length_count = 0; |
last_bit = !last_bit; |
end |
partial_flit[i] = get_bit(local_config.requester,lane) ^ lfsr[0] ^ link_status.get_inverted(lane); |
lfsr = {lfsr[1]^lfsr[0], lfsr[14:1]}; // Every clock after lock, step the LFSR |
|
@(cdr.int_clk); |
end |
lane_queues[lane].push_back(partial_flit); |
//-- lane_queue_event only after all partial flits present |
if(check_lane_queues_not_empty()) |
-> lane_queue_event; |
end |
end |
endtask : descramble |
|
function void reset_link(); |
lane_reversal_set = 0; |
link_status.lane_reversed = 0; |
link_status.num_lanes = NUM_LANES; |
|
link_status.reset(); |
|
bitstream = {}; |
collected_flits = {}; |
for (int i=0; i < NUM_LANES; i++) begin |
lane_queues[i] = {}; |
end |
endfunction :reset_link |
|
task collect_flits(); |
|
flit_t current_flit; |
partial_flit_t lane_flit; |
|
`uvm_info(get_type_name(),$psprintf("starting collect_flits %s", local_config.requester? "Requester" : "Responder"), UVM_HIGH) |
forever begin |
if (link_status.current_state == RESET ) // Reset |
reset_link(); |
//-- check if partial flits available |
if (!flit_available())begin |
@(lane_queue_event);//-- wait for any change at the lane queues and recheck flit available before reading the lane queues |
end |
|
//-- check TS1 sequences |
if (link_status.current_state == TS1) begin |
foreach (lane_queues[i]) begin |
lane_flit = lane_queues[i].pop_front(); |
if (lane_flit != 16'b0) begin //-- while TS1 Sequence |
case (i) |
0: begin |
case (lane_flit[7:4]) |
4'h3 : link_status.lane_reversed = 0; |
4'hc : link_status.lane_reversed = 1; |
default : if (local_config.lane_errors_enabled) begin |
`uvm_info(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder"), UVM_HIGH) |
//-- cover invalid TS1 sequence error |
current_error = INVALID_TS1; |
collected_packet = new(); |
void'(collected_packet.randomize() with{command == HMC_NULL;}); |
hmc_pkt_error_cg.sample(); |
end else begin |
`uvm_fatal(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder")) |
end |
endcase |
if (!lane_reversal_set) begin |
`uvm_info(get_type_name(), $psprintf("%s Link is %s" |
, local_config.requester?"Requester":"Responder" |
, link_status.lane_reversed?"reversed":"not reversed" |
), UVM_NONE) |
end |
lane_reversal_set = 1; |
end |
NUM_LANES-1: begin |
case (lane_flit[7:4]) |
4'h3 : link_status.lane_reversed = 1; |
4'hc : link_status.lane_reversed = 0; |
default : if (local_config.lane_errors_enabled) begin |
`uvm_info(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder"), UVM_HIGH) |
end else begin |
`uvm_fatal(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder")) |
end |
endcase |
end |
default: begin |
if (local_config.lane_errors_enabled) begin |
if (lane_flit[7:4] != 4'h5) |
`uvm_info(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder"), UVM_HIGH) |
end else begin |
if (local_config.lane_errors_enabled) begin |
if (lane_flit[7:4] != 4'h5) |
`uvm_info(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder"), UVM_HIGH) |
end |
else begin |
CHK_TS1_ID: assert (lane_flit[7:4] == 4'h5); |
end |
end |
end |
endcase |
if (local_config.lane_errors_enabled) begin |
if (lane_flit[15:8] != 8'hf0) |
`uvm_info(get_type_name(), $psprintf("Detected invalid TS1 sequence on Lane %0d %s", i, local_config.requester?"requester":"responder"), UVM_HIGH) |
end |
else begin |
CHK_UPPER_TS1: assert (lane_flit[15:8] == 8'hf0); |
end |
end |
|
else begin |
hmc_link_cg.sample(); |
link_status.first_null_detected = 1; |
null_flits_after_TS1= NUM_LANES/8; //-- add 1 or 2 NULL2 Flits depending on NUM_LANES |
end |
end |
end |
else begin |
|
for (int j = 0; j < 16; j++) begin //for each bit position in partial flit |
for (int lane = 0; lane < NUM_LANES; lane++) begin //-- for each lane |
bitstream.push_back(lane_queues[link_status.lane_reversed?NUM_LANES-lane-1:lane][0][j]); |
end |
end |
for (int j = 0; j < 16; j++) begin |
void'(lane_queues[j].pop_front()); |
end |
|
while(bitstream.size()>=128) begin //-- at least 1 flit in bitstream |
for (int k = 0; k <128; k++) |
current_flit[k]= bitstream.pop_front(); |
|
if (link_status.current_state == NULL_FLITS_2) |
begin |
link_status.null_after_ts1_seen = 0; |
if (current_flit == 128'h0) |
begin |
null_flits_after_TS1++; |
if(null_flits_after_TS1 >= 32) begin |
link_status.set_null_after_ts1(); |
end |
`uvm_info(get_type_name(),$psprintf("null flit #%0d on %s Link",null_flits_after_TS1, local_config.requester?"Requester":"Responder"), UVM_HIGH) |
end |
else begin |
if(null_flits_after_TS1 != 0) |
if(local_config.lane_errors_enabled) begin |
`uvm_info(get_type_name(), $psprintf("received only %d consecutive NULL Flits after TS1 sequences, got %h",null_flits_after_TS1,current_flit ), UVM_NONE) |
null_flits_after_TS1++; |
end |
else begin |
`uvm_fatal(get_type_name(), $psprintf("received only %d consecutive NULL Flits after TS1 sequences, got %h",null_flits_after_TS1,current_flit )) |
end |
end |
end |
else if (link_status.current_state == LINK_UP) |
begin |
collected_flits.push_back(current_flit); |
-> flit_queue_event; |
end |
end |
end |
end |
endtask : collect_flits |
|
function bit check_seq_number(hmc_packet packet); |
check_seq_number = 0; |
if (packet.command != HMC_PRET && packet.command != HMC_IRTRY) // No sequence numbers to check in PRET |
begin |
if (packet.sequence_number != next_sequence_num) // Sequence error |
begin |
`uvm_info(get_type_name(), |
$psprintf("%s: expected sequence number %0d, got %0d! in packet with cmd %0s, frp %0d and rrp %0d", |
local_config.requester?"Requester":"Responder",next_sequence_num, packet.sequence_number, |
packet.command.name(),packet.forward_retry_pointer, packet.return_retry_pointer), |
UVM_LOW) |
seq_error++; |
current_error = SEQ_ERROR; |
hmc_pkt_error_cg.sample(); |
link_status.set_error_abort_mode(); |
link_status.clear_irtry_packet_counts(); |
check_seq_number = 1; |
end else begin |
`uvm_info(get_type_name(), $psprintf("CMD %s with current seq_nr: %d",packet.command.name(),packet.sequence_number), UVM_HIGH) |
next_sequence_num = packet.sequence_number + 1; |
end |
end |
else // PRET & IRTRY |
if (packet.sequence_number != 0) begin |
`uvm_info(get_type_name(),$psprintf("%s: expected sequence number 0, got %0d! in packet with cmd %0s, frp %0d and rrp %0d", |
local_config.requester?"Requester":"Responder",packet.sequence_number,packet.command.name(), |
packet.forward_retry_pointer, packet.return_retry_pointer), |
UVM_LOW) |
|
seq_error++; |
current_error = SEQ_ERROR; |
hmc_pkt_error_cg.sample(); |
link_status.set_error_abort_mode(); |
link_status.clear_irtry_packet_counts(); |
check_seq_number = 1; |
end |
|
endfunction : check_seq_number |
|
|
function void token_handling(hmc_packet packet); |
|
if (!remote_link_status.relaxed_token_handling) begin |
remote_link_status.token_count += packet.return_token_count; //-- add available token to the remote link |
return_token_port.write(collected_packet); |
if (local_config.requester && packet.return_token_count >0) |
`uvm_info(get_type_name(), $psprintf("Command %s adds %0d tokens to remote, new token count = %0d", |
packet.command.name(), packet.return_token_count,remote_link_status.token_count ), |
UVM_HIGH) |
|
end |
if (!link_status.relaxed_token_handling) begin |
if (packet.get_command_type() != HMC_FLOW_TYPE)// && !packet.poisoned) // Flow packets do not use tokens. |
begin |
if (!local_config.requester) |
`uvm_info(get_type_name(), $psprintf("Tokens available: %d, used tokens: %d, new token count: %d",link_status.token_count,packet.packet_length, link_status.token_count - packet.packet_length), UVM_HIGH) |
|
if (link_status.token_count < packet.packet_length) //--token underflow must not occur due to the token based flow control |
`uvm_fatal(get_type_name(), $psprintf("send_to_validate: no room to push %s token_count = %0d!", packet.command.name(), link_status.token_count)) |
|
`uvm_info(get_type_name(), $psprintf("send_to_validate: push %s (length %0d) frp %0d token_count %0d new token count %0d.", |
packet.command.name(), packet.packet_length, packet.forward_retry_pointer, link_status.token_count, |
link_status.token_count - packet.packet_length ), |
UVM_HIGH) |
|
link_status.token_count -= packet.packet_length; |
tokens_cg.sample(); |
end |
end |
endfunction : token_handling |
|
function void handle_start_retry(hmc_packet packet); |
if (packet.command == HMC_IRTRY && packet.start_retry) begin |
|
`uvm_info(get_type_name(),$psprintf("received %d start retry IRTRYs for FRP %d", |
link_status.get_StartRetry_packet_count(), packet.return_retry_pointer), UVM_HIGH) |
|
if(link_status.increment_StartRetry_packet_count() >= local_config.irtry_flit_count_received_threshold) begin |
UNEXPECTED_RETRY : assert (remote_link_status.error_abort_mode); |
|
`uvm_info(get_type_name(),$psprintf("Start Retry Threshold Reached for RRP %d", packet.return_retry_pointer),UVM_NONE) |
|
if (link_status.get_error_abort_mode() |
&& link_status.irtry_StartRetry_packet_count == local_config.irtry_flit_count_received_threshold) |
begin |
if(remote_link_status.last_successfull_frp != packet.return_retry_pointer)begin |
`uvm_fatal(get_type_name(), $psprintf("expecting RRP %0d, got %0d", |
remote_link_status.last_successfull_frp, packet.return_retry_pointer)) |
end |
rrp_port.write(packet.return_retry_pointer); |
end |
start_clear_retry_event.trigger(); |
end |
end |
else begin //-- clear start_retry counter |
if (link_status.irtry_StartRetry_packet_count >0) begin |
|
`uvm_info(get_type_name(),$psprintf("clearing Start Retry Counter due to a CMD %s after %0d consecutive StartRetry IRTRYs", |
packet.command.name(), link_status.get_StartRetry_packet_count()),UVM_HIGH) |
|
link_status.irtry_StartRetry_packet_count = 0; |
end |
end |
endfunction : handle_start_retry |
|
function void handle_error_abort_mode(hmc_packet packet); |
|
if ((packet.clear_error_abort)) begin |
`uvm_info(get_type_name(), $psprintf("Clear Error Abort Mode: %0d",link_status.irtry_ClearErrorAbort_packet_count ), UVM_HIGH) |
if (link_status.increment_ClearErrorAbort_packet_count() == local_config.irtry_flit_count_received_threshold) begin |
link_status.error_abort_mode = 0; |
|
`uvm_info(get_type_name(), $psprintf("Clearing Error Abort Mode" ), UVM_NONE) |
rrp_port.write(packet.return_retry_pointer); //--commit last valid RRP |
end |
|
end else begin |
if(!packet.start_retry) begin |
`uvm_info(get_type_name(),$psprintf("clearing Start Retry and Error Abort Counter due to a CMD %s", packet.command.name()),UVM_HIGH) |
link_status.clear_irtry_packet_counts(); //-- reset counter |
end |
end |
|
endfunction : handle_error_abort_mode |
|
|
task collect_packets(); |
bit bitstream[]; |
flit_t current_flit; |
flit_t header_flit; |
bit [31:0] packet_crc; |
bit [31:0] calculated_crc; |
int unsigned current_packet_length; |
int unsigned last_packet_length; |
|
|
`uvm_info(get_type_name(),$psprintf("starting collect_packets "), UVM_HIGH) |
forever begin |
if (link_status.current_state == RESET) //-- reset handling |
begin |
next_sequence_num = 3'b1; //-- reset sequence number |
packets_after_Link_up = 0;//-- reset packet counter |
@(link_status.current_state); |
end else |
begin |
if (collected_flits.size() == 0) begin //-- wait until at least one flit is available |
@(flit_queue_event); |
end |
current_flit = collected_flits.pop_front(); //-- header flit |
|
if (current_flit[5:0] == HMC_NULL) begin //-- do not forward null packets |
null_flits_between_pkts ++; |
if (link_status.irtry_StartRetry_packet_count >0) begin |
`uvm_info(get_type_name(),$psprintf("clearing Start Retry Counter due to a NULL Packet after %0d consecutive StartRetry IRTRYs", link_status.get_StartRetry_packet_count()),UVM_HIGH) |
link_status.irtry_StartRetry_packet_count = 0; |
end |
continue; |
end |
else begin |
//-- if first packet after NULL2 |
if (packets_after_Link_up ==0)begin |
null2_cg.sample(); |
end |
packets_after_Link_up++; |
end |
|
//-- check length miss-match |
//-- TODO: include CMD in length check |
if (current_flit[14:11] != current_flit[10:7] || current_flit[14:11] == 0) // Length mismatch or invalid current_packet_length |
begin |
|
`uvm_info(get_type_name(),$psprintf("%s: current_packet_length mismatch %0x len=%0d, dln = %0d", local_config.requester?"Requester":"Responder", current_flit, current_flit[10:7], current_flit[14:11]),UVM_NONE) |
lng_error ++; |
current_error = LENGTH_ERROR; |
|
collected_packet = new(); |
|
if (local_config.lane_errors_enabled)begin |
void'(collected_packet.randomize() with{ |
command == HMC_NULL; |
}); |
end else begin |
void'(collected_packet.randomize() with{ |
command == hmc_command_encoding'(current_flit[5:0]); |
}); |
end |
hmc_pkt_error_cg.sample(); |
|
link_status.set_error_abort_mode(); |
link_status.irtry_ClearErrorAbort_packet_count = 0; //-- reset clear error abort count |
//-- ignore packet fragments until first IRTRY |
while ( (hmc_command_encoding'(current_flit[5:0]) != HMC_IRTRY) |
|| (current_flit[10:7] != current_flit[14:11]) |
|| (current_flit[10:7] !=1) |
) begin |
if (collected_flits.size() ==0) |
@(flit_queue_event); |
current_flit = collected_flits.pop_front(); |
end |
end |
|
current_packet_length = current_flit[10:7]; |
|
`uvm_info(get_type_name(),$psprintf("%s: current_flit=%0x current_packet_length=%0d", local_config.requester?"Requester":"Responder", current_flit,current_packet_length), UVM_HIGH) |
|
bitstream = new[current_packet_length*128]; |
|
// pack first flit |
header_flit = current_flit; |
for (int i=0; i<128; i=i+1) |
bitstream[i] = current_flit[i]; |
|
// get and pack the remaining flits |
for (int j=1; j<current_packet_length; j=j+1) |
begin |
if (collected_flits.size() == 0) |
@(collected_flits.size()); |
|
current_flit = collected_flits.pop_front(); |
|
for (int i=0; i<128; i=i+1) |
bitstream[j*128+i] = current_flit[i]; |
end |
|
for (int i = 0; i <32; i++)begin |
packet_crc[i] = bitstream[bitstream.size()-32 +i]; |
end |
calculated_crc = collected_packet.calc_crc(bitstream); |
|
|
if ( calculated_crc!= packet_crc && !(packet_crc == ~calculated_crc)) begin //-- check CRC |
`uvm_info(get_type_name(), $psprintf("got a CRC error in hmc_packet %x", header_flit), UVM_NONE) |
crc_error ++; |
current_error = CRC_ERROR; |
collected_packet = hmc_packet::type_id::create("collected_packet", this); |
|
if (local_config.lane_errors_enabled)begin |
void'(collected_packet.randomize() with{ |
command == HMC_NULL; |
}); |
end else begin |
void'(collected_packet.unpack(bitstream)); |
end |
hmc_pkt_error_cg.sample(); |
|
link_status.set_error_abort_mode(); |
link_status.irtry_ClearErrorAbort_packet_count = 0; //-- reset clear error abort count |
continue; |
|
end |
|
|
collected_packet = hmc_packet::type_id::create("collected_packet", this); |
void'(collected_packet.unpack(bitstream)); |
if(collected_packet.command != HMC_IRTRY) |
`uvm_info(get_type_name(), $psprintf("collected_packet CMD: %s FRP: %d", |
collected_packet.command.name(), collected_packet.forward_retry_pointer), UVM_HIGH) |
handle_start_retry(collected_packet); |
|
if (link_status.get_error_abort_mode) begin |
if (collected_packet.command == HMC_IRTRY) |
void'(check_seq_number(collected_packet)); |
handle_error_abort_mode(collected_packet); |
|
end else begin |
|
//--check the sequence number |
if(check_seq_number(collected_packet)) |
continue; |
|
//-- at this point each packet should be clean |
|
token_handling(collected_packet); |
|
//-- commit the collected packet |
hmc_packets_cg.sample(); |
null_flits_between_pkts = 0; |
|
if (!link_status.get_error_abort_mode()) begin |
rrp_port.write(collected_packet.return_retry_pointer); |
|
end |
|
if (collected_packet.command != HMC_PRET) begin |
|
if (collected_packet.command != HMC_IRTRY) begin |
frp_port.write(collected_packet); |
link_status.last_successfull_frp = collected_packet.forward_retry_pointer; |
|
if (collected_packet.poisoned) begin |
|
`uvm_info(get_type_name(),$psprintf("received a poisoned %s", collected_packet.command.name()), UVM_NONE) |
poisoned_pkt++; |
current_error = POISON; |
hmc_pkt_error_cg.sample(); |
|
continue; |
end |
|
if (collected_packet.command != HMC_TRET |
&& !collected_packet.poisoned |
&& collected_packet.command != HMC_IRTRY |
) //-- send only Transaction packets |
item_collected_port.write(collected_packet); |
end |
end |
end |
end |
end |
endtask : collect_packets |
|
task link_states(); |
forever begin |
@({vif.P_RST_N |
,link_status.power_state |
,link_status.all_lanes_locked |
,link_status.all_lanes_alligned |
,link_status.first_null_detected |
,link_status.null_after_ts1_seen} |
); |
|
casex ({vif.P_RST_N |
,link_status.power_state |
,link_status.all_lanes_locked |
,link_status.all_lanes_alligned |
,link_status.first_null_detected |
,link_status.null_after_ts1_seen}) |
6'b0xxxxx : link_status.current_state = RESET; |
6'b10xxxx : link_status.current_state = POWER_DOWN; //-- sleep mode |
6'b110xxx : link_status.current_state = PRBS; //-- scrambler waits for null flits |
6'b1110xx : link_status.current_state = NULL_FLITS; //-- scrambler has detected a null flit |
6'b11110x : link_status.current_state = TS1; //-- scrambler has detected a TS1 sequence and is in flit sync |
6'b111110 : link_status.current_state = NULL_FLITS_2;//-- detected first NULL flits after TS1 |
6'b111111 : link_status.current_state = LINK_UP; //-- Link is UP |
endcase |
`uvm_info(get_type_name(),$psprintf("%s Link current State: %s \t vector: %b", |
local_config.requester?"Requester":"Responder", link_status.current_state.name(), |
{ vif.P_RST_N, |
link_status.power_state, |
link_status.all_lanes_locked, |
link_status.all_lanes_alligned, |
link_status.first_null_detected, |
link_status.null_after_ts1_seen |
}),UVM_LOW) |
if (link_status.current_state == POWER_DOWN || RESET) |
reset_link(); |
end |
endtask : link_states |
|
task run(); |
#1; |
for (int i=0; i<NUM_LANES; i++) |
begin |
automatic int lane = i; |
fork |
`uvm_info(get_type_name(),$psprintf("starting descrambler for Requester lane %0d", lane), UVM_HIGH) |
descramble(lane); |
join_none |
end |
fork |
check_clock(); |
monitor_power_pins(); |
collect_flits(); |
collect_packets(); |
link_states(); |
join_none |
|
wait fork; |
endtask : run |
|
|
function bit flit_available(); |
bit rval = 1'b1; |
// There is only a flit available if all lane_queues are ready |
|
for (int i=0; i < NUM_LANES; i++) |
rval = rval && lane_queues[i].size()>0; |
|
return rval; |
endfunction : flit_available |
|
function bit idle_check(); |
return transaction_mon.idle_check() |
&& (link_status.token_count == local_config.requester?link_config.rx_tokens:link_config.hmc_tokens); |
endfunction : idle_check |
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("LNG error count %0d", lng_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("CRC error count %0d", crc_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("SEQ error count %0d", seq_error), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("poisoned packets %0d", poisoned_pkt), UVM_NONE) |
endfunction : report_phase |
|
function void check_phase(uvm_phase phase); |
if (!idle_check())//-- TODO check that all transactions are closed |
`uvm_fatal(get_type_name(),$psprintf("Link is not IDLE")) |
endfunction : check_phase |
|
endclass : hmc_monitor |
|
`endif // HMC_MONITOR_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_env.sv
0,0 → 1,183
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_ENV_SV |
`define HMC_ENV_SV |
|
|
|
class hmc_env #(parameter NUM_LANES = 16) extends uvm_env; |
|
hmc_link_config link_config; |
|
virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)) vif; |
virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)) int_vif; |
|
hmc_error_injector #(.NUM_LANES(NUM_LANES)) req_inj; |
hmc_error_injector #(.NUM_LANES(NUM_LANES)) rsp_inj; |
|
|
hmc_status h_status; |
hmc_monitor #(.NUM_LANES(NUM_LANES)) req_mon; |
hmc_monitor #(.NUM_LANES(NUM_LANES)) rsp_mon; |
|
|
hmc_transaction_mon req_transaction_mon; |
hmc_transaction_mon rsp_transaction_mon; |
|
hmc_tag_mon tag_mon; |
|
hmc_requester_agent #(.NUM_LANES(NUM_LANES)) requester; |
hmc_responder_agent #(.NUM_LANES(NUM_LANES)) responder; |
|
`uvm_component_param_utils(hmc_env #(.NUM_LANES(NUM_LANES))) |
|
function new(string name="hmc_env", uvm_component parent); |
super.new(name,parent); |
h_status = new("h_status",this); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",vif) ) begin |
this.vif = vif; |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "req_inj","ext_vif",vif); |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "rsp_inj","ext_vif",vif); |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "rsp_mon","vif",vif); |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "rsp_mon.cdr","vif",vif); |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "requester","vif",vif); |
end else begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "int_vif",int_vif) ) begin |
this.int_vif = int_vif; |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "req_inj","int_vif",int_vif); |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "rsp_inj","int_vif",int_vif); |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "req_mon","vif",int_vif); |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "req_mon.cdr","vif",int_vif); |
|
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "responder","vif",int_vif); |
end |
|
req_inj = hmc_error_injector#(.NUM_LANES(NUM_LANES))::type_id::create("req_inj", this); |
req_inj = hmc_error_injector#(.NUM_LANES(NUM_LANES))::type_id::create("rsp_inj", this); |
|
req_mon = hmc_monitor#(.NUM_LANES(NUM_LANES))::type_id::create("req_mon", this); |
rsp_mon = hmc_monitor#(.NUM_LANES(NUM_LANES))::type_id::create("rsp_mon", this); |
|
uvm_config_db#(hmc_status)::set(this, "requester", "h_status", h_status); |
uvm_config_db#(hmc_status)::set(this, "responder", "h_status", h_status); |
|
uvm_config_db#(hmc_status)::set(this, "req_mon", "status", h_status); |
uvm_config_db#(hmc_status)::set(this, "rsp_mon", "status", h_status); |
|
uvm_config_db#(hmc_link_status)::set(this, "req_inj", "link_status", h_status.Requester_link_status); |
uvm_config_db#(hmc_link_status)::set(this, "rsp_inj", "link_status", h_status.Responder_link_status); |
|
if (uvm_config_db#(hmc_link_config)::get(this, "", "link_config", link_config)) begin |
if(link_config.enable_tag_checking) |
tag_mon = hmc_tag_mon::type_id::create("tag_mon", this); |
|
set_config_int("req_transaction_mon", "enable_tag_checking", link_config.enable_tag_checking); |
set_config_int("rsp_transaction_mon", "enable_tag_checking", link_config.enable_tag_checking); |
|
req_transaction_mon = hmc_transaction_mon::type_id::create("req_transaction_mon", this); |
rsp_transaction_mon = hmc_transaction_mon::type_id::create("rsp_transaction_mon", this); |
|
uvm_config_db#(hmc_link_config)::set(this, "rsp_mon.cdr","link_config",link_config); |
uvm_config_db#(hmc_link_config)::set(this, "req_mon.cdr","link_config",link_config); |
|
uvm_config_db#(hmc_link_config)::set(this, "req_mon", "link_config", link_config); |
uvm_config_db#(hmc_link_config)::set(this, "rsp_mon", "link_config", link_config); |
|
uvm_config_db#(hmc_local_link_config)::set(this, "req_mon", "local_config", link_config.requester); |
uvm_config_db#(hmc_local_link_config)::set(this, "rsp_mon", "local_config", link_config.responder); |
|
uvm_config_db#(hmc_link_config)::set(this, "req_inj", "link_config", link_config); |
uvm_config_db#(hmc_link_config)::set(this, "rsp_inj", "link_config", link_config); |
|
uvm_config_db#(hmc_local_link_config)::set(this, "req_inj", "local_config", link_config.requester); |
uvm_config_db#(hmc_local_link_config)::set(this, "rsp_inj", "local_config", link_config.responder); |
|
uvm_config_db#(hmc_link_config)::set(this, "requester.driver", "link_config", link_config); |
uvm_config_db#(hmc_link_config)::set(this, "responder.driver", "link_config", link_config); |
end |
else begin |
uvm_report_fatal(get_type_name(), $psprintf("link_config not set via config_db")); |
end |
|
set_config_int("requester", "active_passive", link_config.requester.active); |
set_config_int("responder", "active_passive", link_config.responder.active); |
|
requester = hmc_requester_agent#(.NUM_LANES(NUM_LANES))::type_id::create("requester",this); |
responder = hmc_responder_agent#(.NUM_LANES(NUM_LANES))::type_id::create("responder",this); |
|
requester.monitor = rsp_mon; |
responder.monitor = req_mon; |
|
responder.req_transaction_mon = req_transaction_mon; |
|
if(link_config.enable_tag_checking == UVM_ACTIVE) begin |
rsp_transaction_mon.tag_mon = tag_mon; |
req_transaction_mon.tag_mon = tag_mon; |
end |
|
req_mon.transaction_mon = rsp_transaction_mon; |
rsp_mon.transaction_mon = req_transaction_mon; |
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
req_mon.return_token_port.connect(req_transaction_mon.pkt_import); |
rsp_mon.return_token_port.connect(rsp_transaction_mon.pkt_import); |
|
req_mon.rrp_port.connect(rsp_transaction_mon.rrp_import); |
rsp_mon.rrp_port.connect(req_transaction_mon.rrp_import); |
endfunction : connect_phase |
|
endclass : hmc_env |
|
`endif // HMC_ENV_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_requester_sequencer.sv
0,0 → 1,90
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
|
/* sequencer is incomplete and not tested */ |
/* Use at your own risk */ |
|
`ifndef HMC_REQUESTER_SEQUENCER_SV |
`define HMC_REQUESTER_SEQUENCER_SV |
|
typedef class hmc_requester_sequence; |
|
class hmc_requester_sequencer extends uvm_sequencer #(hmc_packet); |
|
`uvm_analysis_imp_decl(_hmc_req) |
uvm_analysis_imp_hmc_req #(hmc_packet, hmc_requester_sequencer) hmc_req_port; |
mailbox #(hmc_packet) req_mailbox; |
|
`uvm_component_utils(hmc_requester_sequencer) |
|
// hmc_requester_sequence resp_seq; |
|
function new(string name="hmc_requester_sequencer", uvm_component parent); |
super.new(name,parent); |
hmc_req_port = new("hmc_req_port", this); |
req_mailbox = new(); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
endfunction : connect_phase |
|
task run(); |
// resp_seq = hmc_requester_sequence::type_id::create("resp_seq", this); |
// resp_seq.start(this); |
endtask : run |
|
virtual function void write_hmc_req(input hmc_packet request); |
|
`uvm_info(get_type_name(),$psprintf("Request: %s",request.command.name()),UVM_HIGH) |
|
// req_mailbox_not_full : assert (req_mailbox.try_put(request)); |
|
endfunction : write_hmc_req |
|
endclass : hmc_requester_sequencer |
|
`endif // HMC_REQUESTER_SEQUENCER_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_responder_sequence.sv
0,0 → 1,209
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_RESPONDER_SEQUENCE_SV |
`define HMC_RESPONDER_SEQUENCE_SV |
|
class hmc_responder_sequence extends uvm_sequence; |
|
rand int delay; |
rand hmc_packet response; |
rand bit error_response; |
event item_available; |
|
hmc_packet response_queue[$]; |
|
constraint delay_c { |
delay dist {0:=4, [0:9]:=8, [10:30]:=2, [31:100]:=1}; |
} |
|
`uvm_object_utils(hmc_responder_sequence) |
|
`uvm_declare_p_sequencer(hmc_responder_sequencer) |
|
function new(string name="hmc_responder_sequence"); |
super.new(name); |
endfunction : new |
|
task create_response_packet(hmc_packet request); |
int response_length = 1; |
int new_timestamp; |
bit [127:0] rand_flit; |
bit [127:0] payload_flits [$]; |
|
`uvm_info(get_type_name(),$psprintf("Generating response for a %s @%0x",request.command.name(), request.address),UVM_HIGH) |
|
`uvm_create(response); |
|
void'(this.randomize(error_response)); |
void'(this.randomize(delay)); |
|
new_timestamp = delay * 500ps + $time; |
|
if (request.get_command_type() == HMC_READ_TYPE || |
request.get_command_type() == HMC_MODE_READ_TYPE |
) begin : read |
|
case (request.command) |
HMC_READ_16 : response_length = 2; |
HMC_READ_32 : response_length = 3; |
HMC_READ_48 : response_length = 4; |
HMC_READ_64 : response_length = 5; |
HMC_READ_80 : response_length = 6; |
HMC_READ_96 : response_length = 7; |
HMC_READ_112 : response_length = 8; |
HMC_READ_128 : response_length = 9; |
HMC_MODE_READ_TYPE : response_length = 1; |
endcase |
|
// Randomize the packet |
void'(response.randomize() with { |
command == HMC_READ_RESPONSE; |
address == request.address; // for debugging |
packet_length == response_length; |
duplicate_length == response_length; |
tag == request.tag; |
error_status == 0 || error_response; |
}); |
|
for (int i=0; i<response_length-1; i++) begin |
randomize_flit_successful : assert (std::randomize(rand_flit)) |
payload_flits.push_front(rand_flit); |
end |
|
response.payload = payload_flits; |
response.timestamp = new_timestamp; |
enqueue_response_packet(response); |
|
end : read |
else if (request.get_command_type() == HMC_WRITE_TYPE || request.get_command_type() == HMC_MISC_WRITE_TYPE) begin : write |
|
response_length = 1; |
|
void'(response.randomize() with { |
command == HMC_WRITE_RESPONSE; |
address == request.address; // for debugging |
packet_length == response_length; |
duplicate_length == response_length; |
tag == request.tag; |
error_status == 0 || error_response; |
}); |
|
response.timestamp = new_timestamp; |
enqueue_response_packet(response); |
|
end : write |
// Posted Writes are allowed, but get no response |
else if ( request.get_command_type() != HMC_POSTED_WRITE_TYPE && |
request.get_command_type() != HMC_POSTED_MISC_WRITE_TYPE |
) begin : error |
uvm_report_fatal(get_type_name(), $psprintf("Unsupported command type %s", request.command.name())); |
end : error |
|
endtask : create_response_packet |
|
task enqueue_response_packet(hmc_packet response); |
// Insert at the end when the queue is empty or |
if (response_queue.size() == 0 || |
// when the timestamp is larger than the tail of the queue |
response.timestamp >= response_queue[response_queue.size()-1].timestamp) begin |
response_queue.push_back(response); |
// Insert at the beginning of the queue when the timestamp is small |
end else if (response.timestamp <= response_queue[0].timestamp) begin |
response_queue.push_front(response); |
end else begin |
for (int position=1;position < response_queue.size(); position++) begin |
if (response.timestamp < response_queue[position].timestamp) begin |
//response_queue = {response_queue[0:position-1], response, response_queue[position:$]}; |
response_queue.insert(position-1,response); |
position = response_queue.size(); // Break |
end |
end |
end |
|
// Signal via event that a response has been added |
-> item_available; |
|
endtask : enqueue_response_packet |
|
task body(); |
|
void'(this.randomize()); |
|
fork |
// Convert requests to responses |
forever begin : translate_loop |
hmc_packet packet; |
p_sequencer.req_mailbox.get(packet); |
create_response_packet(packet); |
end : translate_loop |
|
// |
begin |
hmc_packet packet; |
|
forever begin : send_loop |
|
if (response_queue.size() > 0) begin |
int time_to_wait; |
|
time_to_wait = response_queue[0].timestamp - $time; |
if (time_to_wait <= 0) begin |
packet = response_queue.pop_front(); |
uvm_report_info(get_type_name(), $psprintf("Sending response packet: %s", packet.command.name()), UVM_HIGH); |
`uvm_send(packet) |
end else begin |
#time_to_wait; |
end |
end |
else begin |
// Wait for items to get added to the queue |
if (response_queue.size() == 0) |
@(item_available); |
end |
|
end : send_loop |
end |
join |
|
endtask : body |
|
endclass : hmc_responder_sequence |
|
`endif // HMC_RESPONDER_SEQUENCE_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_requester_driver.sv
0,0 → 1,206
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_REQUESTER_DRIVER_SV |
`define HMC_REQUESTER_DRIVER_SV |
|
/* Driver is incomplete and not tested */ |
/* Use at your own risk */ |
|
|
class hmc_requester_driver #(parameter NUM_LANES=16) extends hmc_driver_base#(NUM_LANES); |
|
`uvm_component_param_utils(hmc_requester_driver#(.NUM_LANES(NUM_LANES))) |
|
function new(string name="hmc_requester_driver", uvm_component parent); |
super.new(name,parent); |
hmc_frp_port = new("hmc_frp_port", this); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
local_config = link_config.requester; |
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
super.run_phase(phase); |
|
forever begin |
if(vif.P_RST_N !== 1) begin |
next_state = RESET; |
end |
|
if (next_state != last_state) |
`uvm_info(get_type_name(),$psprintf("in state %s", next_state.name()), UVM_HIGH) |
|
last_state = next_state; |
|
fork |
begin |
case (next_state) |
RESET: reset(); |
NULL_FLITS: null_flits(); |
TS1: ts1(); |
NULL_FLITS_2: null_flits_2(); |
INITIAL_TRETS: initial_trets(); |
LINK_UP: link_up(); |
START_RETRY_INIT: start_retry_init(); |
CLEAR_RETRY: clear_retry(); |
SEND_RETRY_PACKETS: send_retry_packets(); |
|
endcase |
end |
begin |
@(negedge vif.P_RST_N); |
|
end |
begin |
// get_packets(); |
end |
join_any |
disable fork; |
end |
|
endtask : run_phase |
|
task reset(); |
|
vif.RXP = {NUM_LANES {1'bz}}; |
vif.RXN = {NUM_LANES {1'bz}}; |
vif.RXPS = 1'b1; |
|
|
seq_num = 1; |
last_rrp = 0; |
init_continue = 0; |
can_continue = 1; |
retry_buffer.reset(); |
|
//wait for reset signal |
@(posedge vif.P_RST_N); |
|
#link_config.tINIT; |
|
set_init_continue(); |
`uvm_info(get_type_name(),$psprintf("active = %0d retry prob = %0d", local_config.active, local_config.random_retry_probability), UVM_HIGH) |
|
vif.RXPS = 1'b1; |
|
#1us; |
reset_timestamp = $time; |
|
next_state = NULL_FLITS; |
endtask : reset |
|
task null_flits(); |
int null_time; |
|
reset_lfsr(); |
|
//wait for Responder to send NULLs |
while (!remote_status.get_all_lanes_locked()) |
drive_fit({NUM_LANES {1'b0}}); |
|
null_timestamp = $time; |
|
//wait at most tRESP2 |
null_time_randomization_succeeds : assert (std::randomize(null_time) with {null_time > 0ns && null_time < link_config.tRESP2;}); |
for (int i=0; i<null_time/link_config.bit_time; i++) begin |
drive_fit({NUM_LANES {1'b0}}); |
end |
|
next_state = TS1; |
endtask : null_flits |
|
task ts1(); |
int ts1_fits = 0; |
|
// Save the timestamp |
ts1_timestamp = $time; |
|
//wait for Responder to send TS1 |
while (!remote_status.get_all_lanes_aligned()) |
send_ts1(256); // 16 fits per sequence number, 16 sequence numbers |
|
//Send some (possibly incomplete) TS1 flits |
ts1_fits_randomization_succeeds : assert (std::randomize(ts1_fits) with {ts1_fits >= 0 && ts1_fits < 512;}); |
send_ts1(ts1_fits); |
|
next_state = NULL_FLITS_2; |
endtask : ts1 |
|
task null_flits_2(); |
int null_flit_count; |
|
while (!remote_status.get_first_tret_received()) |
drive_flit(128'h0); |
|
null_flit_count_randomization_succeeds : assert (std::randomize(null_flit_count) with {null_flit_count >= 1 && null_flit_count < 512;}); |
|
//send NULL FLITs |
for (int i=0; i < null_flit_count; i++) |
drive_flit(128'h0); |
|
next_state = INITIAL_TRETS; |
endtask : null_flits_2 |
|
function void drive_lanes(input bit[NUM_LANES-1:0] new_value); |
int i; |
|
bit[NUM_LANES-1:0] lanes_reordered; |
|
if (local_config.reverse_lanes) begin |
for (i = 0; i < NUM_LANES; i= i+1) begin |
lanes_reordered[i] = new_value[NUM_LANES-i-1]; |
end |
end else begin |
lanes_reordered = new_value; |
end |
|
// TODO: wire delays? |
for (i = 0; i < local_config.width; i= i+1) begin |
vif.RXP[i] = lanes_reordered[i] ^ local_config.reverse_polarity[i]; |
vif.RXN[i] = ~lanes_reordered[i] ^ local_config.reverse_polarity[i]; |
end |
endfunction : drive_lanes |
|
endclass : hmc_requester_driver |
|
`endif // HMC_REQUESTER_DRIVER_SV |
|
/trunk/openHMC/sim/UVC/hmc/sv/hmc_requester_agent.sv
0,0 → 1,101
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_REQUESTER_AGENT_SV |
`define HMC_REQUESTER_AGENT_SV |
|
/* Agent is incomplete and not tested in ACTIVE State */ |
/* Use at your own risk */ |
|
class hmc_requester_agent #(parameter NUM_LANES = 16) extends uvm_agent; |
|
uvm_active_passive_enum active_passive = UVM_PASSIVE; |
|
hmc_monitor#(.NUM_LANES(NUM_LANES)) monitor; |
|
hmc_requester_driver#(.NUM_LANES(NUM_LANES)) driver; |
hmc_requester_sequencer sequencer; |
hmc_token_handler token_handler; |
hmc_retry_buffer retry_buffer; |
virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)) vif; |
|
`uvm_component_param_utils_begin(hmc_requester_agent # (.NUM_LANES(NUM_LANES))) |
`uvm_field_enum(uvm_active_passive_enum, active_passive, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="hmc_requester_agent", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(active_passive == UVM_ACTIVE) begin |
driver = hmc_requester_driver#(.NUM_LANES(NUM_LANES))::type_id::create("driver", this); |
sequencer = hmc_requester_sequencer::type_id::create("sequencer",this); |
token_handler = hmc_token_handler::type_id::create("token_handler",this); |
retry_buffer = hmc_retry_buffer::type_id::create("retry_buffer",this); |
end |
|
if(uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::get(this, "", "vif",vif) ) begin |
this.vif = vif; |
uvm_config_db#(virtual interface hmc_sr_if#(.NUM_LANES(NUM_LANES)))::set(this, "driver","vif",vif); |
end |
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
if(active_passive == UVM_ACTIVE) begin |
driver.seq_item_port.connect(sequencer.seq_item_export); |
|
driver.token_handler = token_handler; |
driver.retry_buffer = retry_buffer; |
|
driver.remote_status = monitor.status.Responder_link_status; |
|
monitor.frp_port.connect(driver.hmc_frp_port); |
monitor.item_collected_port.connect(sequencer.hmc_req_port); |
monitor.return_token_port.connect(token_handler.token_imp); |
monitor.rrp_port.connect(retry_buffer.return_pointer_imp); |
end |
endfunction : connect_phase |
|
endclass : hmc_requester_agent |
|
`endif // HMC_REQUESTER_AGENT_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_retry_buffer.sv
0,0 → 1,171
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef HMC_RETRY_BUFFER_SV |
`define HMC_RETRY_BUFFER_SV |
|
class hmc_retry_buffer extends uvm_component; |
|
hmc_packet retry_buffer[$]; |
hmc_packet retry_packets[$]; |
|
int retry_pos = 0; |
|
bit [7:0] last_rrp = 8'h0; |
bit [7:0] retry_pointer_head = 8'h0; |
bit [7:0] retry_pointer_next = 8'h0; |
bit retry_in_progress = 0; |
int buffer_usage = 0; |
|
`uvm_analysis_imp_decl(_return_pointer) |
uvm_analysis_imp_return_pointer#(int, hmc_retry_buffer) return_pointer_imp; |
|
`uvm_component_utils(hmc_retry_buffer) |
|
function new(string name="hmc_retry_buffer", uvm_component parent); |
super.new(name,parent); |
|
return_pointer_imp = new ("return_pointer_imp",this); |
retry_pointer_head = 8'h0; |
retry_pointer_next = 8'h0; |
retry_in_progress = 0; |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
endfunction : build_phase |
|
function void reset(); |
retry_buffer = {}; |
retry_packets = {}; |
retry_pointer_head = 8'h0; |
retry_pointer_next = 8'h0; |
retry_in_progress = 0; |
endfunction : reset |
|
function void write_return_pointer(input int rrp); |
|
int index = -1; |
`uvm_info(get_type_name(),$psprintf("write_return_pointer: rrp %0d", rrp), UVM_HIGH) |
|
if(last_rrp == rrp) |
return; |
|
last_rrp = rrp; |
|
for (int i=0; i<retry_buffer.size(); i++) begin |
buffer_usage = buffer_usage - retry_buffer[i].packet_length; |
if (retry_buffer[i].forward_retry_pointer == rrp) begin |
index = i; |
break; |
end |
end |
|
valid_rrp_found_in_retry_buffer : assert (index!=-1 && index<retry_buffer.size()); |
|
// Delete everything up to the index |
if (retry_buffer.size()-1 == index) begin |
retry_buffer = {}; |
end else begin |
retry_buffer = retry_buffer[index+1:$]; |
end |
endfunction : write_return_pointer |
|
function int add_packet(input hmc_packet pkt); |
hmc_packet copy; |
|
|
bit [8:0] retry_pointer_next_sum = retry_pointer_next + pkt.packet_length; |
|
no_add_packet_when_retry_in_progress : assert (retry_in_progress == 0); |
|
if(retry_pointer_next_sum[7:0] >= last_rrp && retry_pointer_next_sum[8]) begin |
`uvm_info(get_type_name(),$psprintf("add_packet: Retry Buffer full 1 with last frp %0d", last_rrp), UVM_HIGH) |
return -1; |
end |
|
if(retry_pointer_next_sum >= last_rrp && retry_pointer_next < last_rrp) begin |
`uvm_info(get_type_name(),$psprintf("add_packet: Retry Buffer full 2 with last frp %0d", last_rrp), UVM_HIGH) |
return -1; |
end |
retry_pointer_next = retry_pointer_next_sum[7:0]; |
pkt.forward_retry_pointer = retry_pointer_next; |
buffer_usage += pkt.packet_length; |
|
`uvm_info(get_type_name(),$psprintf("add_packet: %s frp %0d", pkt.command.name(), pkt.forward_retry_pointer), UVM_HIGH) |
|
copy = new pkt; |
retry_buffer.push_back(copy); |
return retry_pointer_next; |
endfunction : add_packet |
|
function hmc_packet get_retry_packet(); |
if (retry_in_progress == 0 && retry_buffer.size() > 0) begin |
retry_in_progress = 1; |
retry_packets = retry_buffer; |
`uvm_info(get_type_name(),$psprintf("get_retry_packet: start retry with %0d packets", retry_buffer.size()), UVM_HIGH) |
retry_pos = 0; |
end |
|
if (retry_pos <retry_packets.size()) begin |
retry_pos ++; |
return retry_packets[retry_pos-1]; |
end else begin |
retry_in_progress = 0; |
return null; |
end |
endfunction : get_retry_packet |
|
function void check_phase(uvm_phase phase); |
no_retry_at_check : assert (retry_in_progress == 0); |
if (retry_buffer.size() > 0) begin |
for (int i=0;i<retry_buffer.size();i++) begin |
`uvm_info(get_type_name(),$psprintf("retry_buffer %0d: %s frp %0d", i, retry_buffer[i].command.name(), retry_buffer[i].forward_retry_pointer), UVM_LOW) |
end |
end |
retry_buffer_empty : assert (retry_buffer.size() == 0); |
endfunction : check_phase |
|
function int get_buffer_used(); |
return buffer_usage; |
endfunction : get_buffer_used |
|
endclass : hmc_retry_buffer |
|
`endif // HMC_RETRY_BUFFER_SV |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_transaction_mon.sv
0,0 → 1,177
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
`ifndef hmc_transaction_mon_sv |
`define hmc_transaction_mon_sv |
|
class hmc_transaction_mon extends uvm_monitor; |
|
hmc_packet hmc_buffer[$]; |
bit [7:0] last_rrp = 0; |
bit [2:0] next_sequence_num; |
hmc_tag_mon tag_mon; |
|
uvm_active_passive_enum enable_tag_checking = UVM_ACTIVE; |
|
`uvm_analysis_imp_decl(_hmc_pkt) |
uvm_analysis_imp_hmc_pkt #(hmc_packet, hmc_transaction_mon) pkt_import; |
`uvm_analysis_imp_decl(_hmc_rrp) |
uvm_analysis_imp_hmc_rrp #(int, hmc_transaction_mon) rrp_import; |
|
|
|
uvm_analysis_port #(hmc_packet) transaction_finished_port; |
|
`uvm_component_utils_begin(hmc_transaction_mon) |
`uvm_field_enum(uvm_active_passive_enum, enable_tag_checking, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new ( string name="hmc_transaction_mon", uvm_component parent ); |
super.new(name, parent); |
|
pkt_import = new("pkt_import",this); |
rrp_import = new("rrp_import",this); |
|
transaction_finished_port = new("transaction_finished_port", this); |
|
next_sequence_num = 3'b1; |
|
|
hmc_buffer = {}; |
|
|
endfunction : new |
|
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
endfunction : build_phase |
|
|
function void write_hmc_pkt(input hmc_packet collected_packet); |
|
if (collected_packet.command != HMC_NULL |
&& collected_packet.command != HMC_IRTRY |
&& collected_packet.command != HMC_PRET |
) |
begin |
`uvm_info(get_type_name(), $psprintf("got packet with command %s and frp %d", collected_packet.command.name(),collected_packet.forward_retry_pointer), UVM_HIGH) |
hmc_buffer.push_back(collected_packet); |
end |
|
|
|
endfunction : write_hmc_pkt |
|
function void tag_handling (hmc_packet packet ); |
if (packet.get_command_type() == HMC_WRITE_TYPE || |
packet.get_command_type() == HMC_MISC_WRITE_TYPE || |
packet.get_command_type() == HMC_MODE_READ_TYPE || |
packet.get_command_type() == HMC_READ_TYPE) |
begin |
tag_mon.use_tag(packet.tag); |
end |
|
if (packet.get_command_type() == HMC_RESPONSE_TYPE && |
packet.command != HMC_ERROR_RESPONSE && |
!packet.poisoned) |
begin |
tag_mon.release_tag(packet.tag); |
end |
|
endfunction : tag_handling |
|
|
function void write_hmc_rrp(int rrp); |
if (rrp != last_rrp) begin |
hmc_packet current_packet; |
`uvm_info(get_type_name(),$psprintf("searching packet with FRP %d", rrp),UVM_HIGH) |
if (hmc_buffer.size()>0) begin |
do begin |
if (hmc_buffer.size()>0) begin |
current_packet = hmc_buffer.pop_front(); |
|
if ((current_packet.command != HMC_TRET) ) begin |
`uvm_info(get_type_name(),$psprintf("send packet with command %s and frp %d", current_packet.command.name(),current_packet.forward_retry_pointer), UVM_HIGH) |
if (current_packet.poisoned) |
`uvm_info(get_type_name(), $psprintf("Packet was poisoned"), UVM_NONE) |
else begin |
if(enable_tag_checking == UVM_ACTIVE) |
tag_handling(current_packet); |
transaction_finished_port.write(current_packet); |
end |
end |
end |
else |
`uvm_fatal(get_type_name(),$psprintf("Cant find RRP %d in retry buffer", rrp)) |
end while (current_packet.forward_retry_pointer != rrp); |
end else |
`uvm_info(get_type_name(), $psprintf("retry buffer is empty, can not find matching rrp (%0d)", rrp), UVM_HIGH) |
last_rrp = rrp; |
end |
endfunction : write_hmc_rrp |
|
|
function bit idle_check(); |
if (enable_tag_checking == UVM_ACTIVE) |
return hmc_buffer.size()==0 && tag_mon.idle_check(); |
else |
return hmc_buffer.size()==0; |
endfunction : idle_check |
|
function void check_phase(uvm_phase phase); |
hmc_packet pkt; |
|
if (hmc_buffer.size() >0) begin |
`uvm_info(get_type_name(),$psprintf("retry buffer is not empty!"),UVM_NONE) |
while(hmc_buffer.size()>0) begin |
pkt = hmc_buffer.pop_front(); |
`uvm_info(get_type_name(),$psprintf("Open FRP: %d", pkt.forward_retry_pointer), UVM_NONE) |
end |
//-- print packet |
`uvm_fatal(get_type_name(),$psprintf("retry buffer is not empty!")) |
end |
|
endfunction : check_phase |
|
|
|
endclass : hmc_transaction_mon |
|
`endif // hmc_transaction_mon_sv |
/trunk/openHMC/sim/UVC/hmc/sv/hmc_link_status.sv
0,0 → 1,230
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* openHMC - An Open Source Hybrid Memory Cube Controller |
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg |
* www.ziti.uni-heidelberg.de |
* B6, 26 |
* 68159 Mannheim |
* Germany |
* |
* Contact: openhmc@ziti.uni-heidelberg.de |
* http://ra.ziti.uni-heidelberg.de/openhmc |
* |
* This source file is free software: you can redistribute it and/or modify |
* it under the terms of the GNU Lesser General Public License as published by |
* the Free Software Foundation, either version 3 of the License, or |
* (at your option) any later version. |
* |
* This source file is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this source file. If not, see <http://www.gnu.org/licenses/>. |
* |
* |
*/ |
// |
// |
// hmc link status |
// |
// |
|
`ifndef HMC_LINK_STATUS_SV |
`define HMC_LINK_STATUS_SV |
|
class hmc_link_status extends uvm_component; |
|
init_state_t current_state; |
|
int num_lanes = 8; |
|
// status bits |
bit first_null_detected = 0; //-- first NULL Flit detected after TS1 sequence |
bit null_after_ts1_seen = 0; //-- recceived the mimimum amount of NULL Flits to enter Link UP |
|
// Lane status signals |
bit lanes_locked [] ; |
bit lanes_aligned[]; |
bit [15:0]lanes_polarity; |
bit lanes_nonzero[]; |
bit lane_reversed; |
|
bit all_lanes_locked; |
bit all_lanes_alligned; |
|
int token_count; |
int num_lanes_locked; |
|
bit power_state; |
bit first_tret_received=1'b0; |
|
bit error_abort_mode=1'b0; |
int irtry_StartRetry_packet_count=0; |
int irtry_ClearErrorAbort_packet_count=0; |
|
|
int last_successfull_frp; |
int last_sequence_number; |
|
bit relaxed_token_handling=1'b0; |
|
`uvm_component_utils(hmc_link_status) |
|
function new ( string name="hmc_link_status", uvm_component parent ); |
super.new(name, parent); |
endfunction : new |
|
function void reset();//--TODO power down reset? |
lanes_locked = new[num_lanes]; |
lanes_aligned = new[num_lanes]; |
lanes_polarity = {16{1'b0}}; |
lanes_nonzero = new[num_lanes]; |
for (int i=0; i < num_lanes; i++) begin |
lanes_locked[i] = 0; |
lanes_aligned[i] = 0; |
lanes_polarity[i] = 0; |
lanes_nonzero[i] = 0; |
lane_reversed = 0; |
end |
|
num_lanes_locked = 0; |
|
first_null_detected = 0; |
null_after_ts1_seen = 0; |
error_abort_mode = 0; |
irtry_StartRetry_packet_count = 0; |
irtry_ClearErrorAbort_packet_count = 0; |
first_tret_received = 0; |
last_sequence_number= 0; |
|
void'(get_all_lanes_locked()); |
void'(get_all_lanes_aligned()); |
|
endfunction : reset |
|
function void set_relaxed_token_handling(input bit relaxed); |
relaxed_token_handling = relaxed; |
endfunction : set_relaxed_token_handling |
|
function void set_locked(input int lane); |
lanes_locked[lane] = 1'b1; |
num_lanes_locked = num_lanes_locked + 1; |
void'(get_all_lanes_locked()); |
endfunction : set_locked |
|
function bit get_locked(input int lane); |
return lanes_locked[lane]; |
endfunction : get_locked |
|
function int get_next_sequence_number(); |
return last_sequence_number + 1; |
endfunction : get_next_sequence_number |
|
function bit get_all_lanes_locked(); |
all_lanes_locked = num_lanes_locked == num_lanes; |
return num_lanes_locked == num_lanes; |
endfunction : get_all_lanes_locked |
|
function void set_aligned(input int lane); |
lanes_aligned[lane] = 1'b1; |
all_lanes_alligned = lanes_aligned == lanes_locked; |
endfunction : set_aligned |
|
function bit get_aligned(input int lane); |
return lanes_aligned[lane]; |
endfunction : get_aligned |
|
function bit get_all_lanes_aligned(); |
all_lanes_alligned = (lanes_aligned == lanes_locked) && (lanes_aligned == {16{1'b1}}); |
return all_lanes_alligned; |
endfunction : get_all_lanes_aligned |
|
function void set_inverted(input int lane); |
lanes_polarity[lane] = 1'b1; |
endfunction : set_inverted |
|
function bit get_inverted(input int lane); |
return lanes_polarity[lane]; |
endfunction : get_inverted |
|
function void set_nonzero(input int lane); |
lanes_nonzero[lane] = 1'b1; |
void'(get_all_nonzero()); |
endfunction : set_nonzero |
|
function bit get_nonzero(input int lane); |
return lanes_nonzero[lane]; |
endfunction : get_nonzero |
|
function bit get_all_nonzero(); |
return lanes_nonzero == lanes_locked; |
endfunction : get_all_nonzero |
|
function void set_null_after_ts1(); |
null_after_ts1_seen = 1; |
endfunction : set_null_after_ts1 |
|
function bit get_null_after_ts1(); |
return null_after_ts1_seen; |
endfunction : get_null_after_ts1 |
|
function bit get_first_tret_received(); |
return first_tret_received; |
endfunction : get_first_tret_received |
|
function void set_error_abort_mode(); |
error_abort_mode = 1; |
endfunction : set_error_abort_mode |
|
function bit get_error_abort_mode(); |
return error_abort_mode; |
endfunction : get_error_abort_mode |
|
function void clear_irtry_packet_counts(); |
`uvm_info(get_type_name(),$psprintf("clear IRTRY counter"), UVM_HIGH) |
irtry_StartRetry_packet_count = 0; |
irtry_ClearErrorAbort_packet_count = 0; |
endfunction : clear_irtry_packet_counts |
|
function int get_StartRetry_packet_count(); |
return irtry_StartRetry_packet_count; |
endfunction : get_StartRetry_packet_count |
|
function int get_ClearErrorAbort_packet_count(); |
return irtry_ClearErrorAbort_packet_count; |
endfunction : get_ClearErrorAbort_packet_count |
|
function int increment_StartRetry_packet_count(); |
irtry_StartRetry_packet_count = irtry_StartRetry_packet_count + 1; |
return irtry_StartRetry_packet_count; |
endfunction : increment_StartRetry_packet_count |
|
function int increment_ClearErrorAbort_packet_count(); |
irtry_ClearErrorAbort_packet_count = irtry_ClearErrorAbort_packet_count + 1; |
return irtry_ClearErrorAbort_packet_count; |
endfunction : increment_ClearErrorAbort_packet_count |
|
function void signal_power_state(input bit ps); |
power_state = ps; |
endfunction : signal_power_state |
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("Token_count %0d", token_count), UVM_LOW) |
endfunction : report_phase |
|
endclass : hmc_link_status |
|
`endif // HMC_LINK_STATUS_SV |
/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_pkg.sv
51,8 → 51,6
|
`include "hmc_module_scb.sv" |
`include "hmc_module_mon.sv" |
|
//`include "hmc_module_cfg.sv" |
`include "hmc_module_env.sv" |
|
endpackage : hmc_module_pkg |
/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_scb.sv
51,15 → 51,15
protected int axi4_error_response_count = 0; |
|
|
|
|
typedef hmc_packet hmc_request_queue[$]; |
typedef bit [127:0] flit_t; |
hmc_request_queue axi4_np_requests[*]; |
hmc_packet axi4_2_hmc[$]; |
hmc_packet hmc_2_axi4[$]; |
hmc_packet hmc_2_axi4_axi4_came_first[$]; |
hmc_packet hmc_response[$]; |
hmc_packet axi4_response[$]; |
|
|
int valid_cycle = 0; |
|
//--check tags |
67,8 → 67,6
bit [512:0]used_tags; |
|
|
|
|
//-- analysis imports |
//-- HMC Interface |
`uvm_analysis_imp_decl(_hmc_req) |
94,7 → 92,7
endfunction : new |
|
//-- compare the received response packets and check with the previous sent request packet |
function void hmc_2_axi4_compare(input hmc_packet expected, input hmc_packet packet); |
function void response_compare(input hmc_packet expected, input hmc_packet packet); |
int i; |
hmc_packet request; |
|
101,7 → 99,7
if (packet.command != HMC_ERROR_RESPONSE) begin //-- HMC_ERROR_RESPONSE has no label |
//-- Check the packet against the request stored in the axi4_np_requests map |
label : assert (axi4_np_requests.exists(packet.tag)) |
else `uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Unexpected Response with tag %0x \n%s", packet.tag, packet.sprint())); |
else `uvm_fatal(get_type_name(),$psprintf("response_compare: Unexpected Response with tag %0x \n%s", packet.tag, packet.sprint())); |
|
//-- delete the previous sent request packet |
request = axi4_np_requests[packet.tag].pop_front(); |
112,10 → 110,10
if (packet.command == HMC_WRITE_RESPONSE |
&& request.get_command_type() != HMC_WRITE_TYPE |
&& request.get_command_type() != HMC_MISC_WRITE_TYPE) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Write Response received with tag %0x for request %s\n%s", packet.tag, request.command.name(), packet.sprint())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Write Response received with tag %0x for request %s\n%s", packet.tag, request.command.name(), packet.sprint())) |
|
if (packet.command == HMC_READ_RESPONSE && request.get_command_type() != HMC_READ_TYPE && request.get_command_type() != HMC_MODE_READ_TYPE ) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Read Response received with tag %0x for request %s\n%s", packet.tag, request.command.name(), packet.sprint())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Read Response received with tag %0x for request %s\n%s", packet.tag, request.command.name(), packet.sprint())) |
|
if (packet.command == HMC_READ_RESPONSE) begin |
int expected_count; |
132,70 → 130,70
default: expected_count = 0; |
endcase |
if (expected_count != packet.payload.size()) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Read Response received with tag %0x and wrong size req=%0s rsp payload size=%0x\n", packet.tag, request.command.name(), packet.payload.size())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Read Response received with tag %0x and wrong size req=%0s rsp payload size=%0x\n", packet.tag, request.command.name(), packet.payload.size())) |
end |
|
//-- Check that the HMC command matches the HTOC item |
if (packet.get_command_type() != HMC_RESPONSE_TYPE) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Unexpected Packet \n%s", packet.sprint())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Unexpected Packet \n%s", packet.sprint())) |
|
if (expected.command != packet.command) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Expected %s, got %s", expected.command.name(), packet.command.name())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Expected %s, got %s", expected.command.name(), packet.command.name())) |
|
if (expected.tag != packet.tag) begin |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_NONE) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Packet tag mismatch %0d != %0d ", expected.tag, packet.tag)) |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_LOW) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Packet tag mismatch %0d != %0d ", expected.tag, packet.tag)) |
end |
|
if (expected.packet_length != packet.packet_length) begin |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_NONE) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Packet length mismatch %0d != %0d ", expected.packet_length, packet.packet_length)) |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_LOW) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Packet length mismatch %0d != %0d ", expected.packet_length, packet.packet_length)) |
end |
|
if (expected.payload.size() != packet.payload.size()) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Payload size mismatch %0d != %0d", expected.payload.size(), packet.payload.size())) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Payload size mismatch %0d != %0d", expected.payload.size(), packet.payload.size())) |
|
for (int i=0; i<packet.payload.size(); i++) begin |
if (packet.payload[i] != expected.payload[i]) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Payload mismatch at %0d %0x != %0x", i, packet.payload[i], expected.payload[i])) |
`uvm_fatal(get_type_name(),$psprintf("response_compare: Payload mismatch at %0d %0x != %0x", i, packet.payload[i], expected.payload[i])) |
end |
|
endfunction : hmc_2_axi4_compare |
endfunction : response_compare |
|
//-- compare and check 2 Request type packets |
function void axi4_2_hmc_compare(input hmc_packet expected, hmc_packet packet); |
function void request_compare(input hmc_packet expected, hmc_packet packet); |
|
hmc_command_type packet_type = packet.get_command_type(); |
if (packet_type == HMC_FLOW_TYPE || packet_type == HMC_RESPONSE_TYPE) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Unexpected Packet \n%s", packet.sprint())) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Unexpected Packet \n%s", packet.sprint())) |
|
if (expected.command != packet.command) begin |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_NONE) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Expected %s, got %s", expected.command.name(), packet.command.name())) |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_LOW) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Expected %s, got %s", expected.command.name(), packet.command.name())) |
end |
|
if (expected.cube_ID != packet.cube_ID) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: cube_ID mismatch %0d != %0d", expected.cube_ID, packet.cube_ID)) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: cube_ID mismatch %0d != %0d", expected.cube_ID, packet.cube_ID)) |
|
if (expected.address != packet.address) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Address mismatch %0d != %0d", expected.address, packet.address)) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Address mismatch %0d != %0d", expected.address, packet.address)) |
|
if (expected.packet_length != packet.packet_length) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Packet length mismatch %0d != %0d", expected.packet_length, packet.packet_length)) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Packet length mismatch %0d != %0d", expected.packet_length, packet.packet_length)) |
|
if (expected.tag != packet.tag) begin |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_NONE) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Packet tag mismatch %0d != %0d ", expected.tag, packet.tag)) |
`uvm_info(get_type_name(), $psprintf("Expected: %s. got: %s", expected.sprint(), packet.sprint() ), UVM_LOW) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Packet tag mismatch %0d != %0d ", expected.tag, packet.tag)) |
end |
|
if (expected.payload.size() != packet.payload.size()) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Payload size mismatch %0d != %0d", expected.payload.size(), packet.payload.size())) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Payload size mismatch %0d != %0d", expected.payload.size(), packet.payload.size())) |
|
for (int i=0;i<expected.payload.size();i = i+1) begin |
if (expected.payload[i] != packet.payload[i]) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Payload mismatch at %0d %0x != %0x", i, expected.payload[i], packet.payload[i])) |
`uvm_fatal(get_type_name(),$psprintf("request_compare: Payload mismatch at %0d %0x != %0x", i, expected.payload[i], packet.payload[i])) |
end |
endfunction : axi4_2_hmc_compare |
endfunction : request_compare |
|
function void write_hmc_rsp(input hmc_packet packet); |
hmc_packet expected; |
211,7 → 209,24
end |
|
//-- check this packet later |
hmc_2_axi4.push_back(packet); |
|
//-- the response packet might be delayed due to the packet mon |
//-- check if the response packet is already received on the axi link |
if (axi4_response.size() == 0) |
hmc_response.push_back(packet); |
else begin //-- check the packet |
expected = axi4_response.pop_front(); |
response_compare(expected, packet); //TODO |
|
if (packet.command != HMC_ERROR_RESPONSE) begin //TODO cover error response |
//-- check if open request with tag is available |
if (used_tags[packet.tag] == 1'b1) begin |
used_tags[packet.tag] = 1'b0; |
end else begin |
`uvm_fatal(get_type_name(),$psprintf("Packet with Tag %0d was not requested", packet.tag)) |
end |
end |
end |
endfunction : write_hmc_rsp |
|
function void write_hmc_req(input hmc_packet packet); |
233,7 → 248,7
expected = axi4_2_hmc.pop_front(); |
|
//-- compare and check 2 Request type packets |
axi4_2_hmc_compare(expected, packet); |
request_compare(expected, packet); |
|
`uvm_info(get_type_name(),$psprintf("hmc_req: checked packet #%0d %s@%0x", hmc_req_packet_count, packet.command.name(), packet.address), UVM_MEDIUM) |
endfunction : write_hmc_req |
245,26 → 260,37
if (packet == null) begin |
`uvm_fatal(get_type_name(), $psprintf("packet is null")) |
end |
|
//-- compare with previous on the HMC side received response packet |
expected = hmc_2_axi4.pop_front(); |
hmc_2_axi4_compare(expected, packet); |
if (packet.command != HMC_ERROR_RESPONSE) begin //TODO cover error response |
|
if (packet.command != HMC_ERROR_RESPONSE) begin //TODO cover error response |
axi4_rsp_packet_count++; |
|
`uvm_info(get_type_name(),$psprintf("axi4_rsp: received packet #%0d %s", axi4_rsp_packet_count, packet.command.name()), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("axi4_rsp: \n%s", packet.sprint()), UVM_HIGH) |
//-- check if open request with tag is available |
if (used_tags[packet.tag] == 1'b1) begin |
used_tags[packet.tag] = 1'b0; |
end else begin |
`uvm_fatal(get_type_name(),$psprintf("Packet with Tag %0d was not requested", packet.tag)) |
end |
end else begin |
axi4_error_response_count++; |
`uvm_info(get_type_name(),$psprintf("axi4_error_rsp: received error response #%0d %s", axi4_error_response_count, packet.command.name()), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("axi4_error_rsp: \n%s", packet.sprint()), UVM_HIGH) |
end |
|
//-- the response packet might be delayed due to the transmission mon. |
//-- due to this the compare must be executed later |
|
//-- compare with previous on the HMC side received response packet |
|
if (hmc_response.size()== 0) |
axi4_response.push_back(packet); |
else begin //-- check |
expected = hmc_response.pop_front(); |
response_compare(expected, packet); //TODO |
|
if (packet.command != HMC_ERROR_RESPONSE) begin //TODO cover error response |
//-- check if open request with tag is available |
if (used_tags[packet.tag] == 1'b1) begin |
used_tags[packet.tag] = 1'b0; |
end else begin |
`uvm_fatal(get_type_name(),$psprintf("Packet with Tag %0d was not requested", packet.tag)) |
end |
end |
end |
endfunction :write_axi4_hmc_rsp |
|
|
305,9 → 331,6
`uvm_info(get_type_name(),$psprintf("axi4_req: received packet #%0d %s@%0x", axi4_req_packet_count, packet.command.name(), packet.address), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("axi4_req: \n%s", packet.sprint()), UVM_HIGH) |
|
|
|
|
endfunction :write_axi4_hmc_req |
|
function void check_phase(uvm_phase phase); |
321,7 → 344,7
if (axi4_np_requests.size() > 0) begin |
for(int i=0;i<512;i++)begin |
if (axi4_np_requests.exists(i))begin |
`uvm_info(get_type_name(),$psprintf("Unanswered Requests: %0d with tag %0d", axi4_np_requests[i].size(), i), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("Unanswered Requests: %0d with tag %0d", axi4_np_requests[i].size(), i), UVM_LOW) |
end |
end |
`uvm_fatal(get_type_name(),$psprintf("axi4_np_requests.size() = %0d, not all requests have been answered!", axi4_np_requests.size())) |
331,7 → 354,7
if (used_tags >0) begin |
foreach(used_tags[i]) begin |
if (used_tags[i] == 1'b1) |
`uvm_info(get_type_name(),$psprintf("Tag %0d is in use", i), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("Tag %0d is in use", i), UVM_LOW) |
end |
`uvm_fatal(get_type_name(),$psprintf("Open Tags!")) |
end |
338,11 → 361,11
endfunction : check_phase |
|
function void report_phase(uvm_phase phase); |
`uvm_info(get_type_name(),$psprintf("axi4_req_count %0d", axi4_req_packet_count), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("axi4_rsp_count %0d", axi4_rsp_packet_count), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("hmc_req_count %0d", hmc_req_packet_count), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("hmc_rsp_count %0d", hmc_rsp_packet_count), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("Error response count %0d", axi4_error_response_count ), UVM_NONE) |
`uvm_info(get_type_name(),$psprintf("axi4_req_count %0d", axi4_req_packet_count), UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("axi4_rsp_count %0d", axi4_rsp_packet_count), UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("hmc_req_count %0d", hmc_req_packet_count), UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("hmc_rsp_count %0d", hmc_rsp_packet_count), UVM_LOW) |
`uvm_info(get_type_name(),$psprintf("Error response count %0d", axi4_error_response_count ), UVM_LOW) |
endfunction : report_phase |
|
endclass : hmc_module_scb |
/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_mon.sv
51,7 → 51,6
bins pkt_length[] = {[1:9]}; |
} |
HMC_COMMAND: coverpoint packet.command { |
//bins request_commands[] = |
bins requests[] = { |
HMC_WRITE_16, |
HMC_WRITE_32, |
121,8 → 120,8
super.new(name, parent); |
item_collected_port = new("item_collected_port", this); |
endfunction : new |
|
|
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
endfunction : build_phase |