OpenCores
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_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/init_test/init_test.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/sleep_mode/sleep_mode.sv File deleted \ No newline at end of file
/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/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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.