URL
https://opencores.org/ocsvn/openhmc/openhmc/trunk
Subversion Repositories openhmc
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/openhmc/trunk/openHMC/sim/tb/bfm/build/compile_ius_openhmc_behavioral_bfm.f
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/>. |
# |
# |
|
#Leave untouched |
+define+HMC_REQUESTER_IS_ACTIVE=0 |
+define+HMC_RESPONDER_IS_ACTIVE=0 |
+define+SIMULATION=1 |
|
###Include Sources |
#Behavioral serializer and routing models |
${OPENHMC_SIM}/tb/bfm/src/behavioral/deserializer.v |
${OPENHMC_SIM}/tb/bfm/src/behavioral/serializer.v |
${OPENHMC_SIM}/tb/bfm/src/behavioral/routing.v |
|
#openHMC controller |
-f ${OPENHMC_PATH}/rtl/hmc_controller/hmc_controller_top.f |
+incdir+${OPENHMC_PATH}/rtl/include/ |
|
#Micron BFM model |
-f ${OPENHMC_SIM}/bfm/hmc_bfm.f |
|
#Include Register File and controller header |
+incdir+${OPENHMC_SIM}/tb/bfm/src/rgm/openhmc/ |
+incdir+${OPENHMC_SIM}/tb/bfm/src/targets/ |
|
#Source top TB and DUT |
-f ${OPENHMC_SIM}/tb/bfm/build/compile_tb_openhmc.f |
${OPENHMC_SIM}/tb/bfm/src/tb_top_bfm.sv |
${OPENHMC_SIM}/tb/bfm/src/targets/dut_openhmc_behavioral_bfm.sv |
/openhmc/trunk/openHMC/sim/tb/bfm/build/compile_tb_openhmc.f
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/>. |
# |
# |
|
+define+RFS_DATA_WIDTH=64 |
+define+RFS_VC107_1HMC_8LANE_TOP_RF_AWIDTH=5 |
+define+RFS_VC107_1HMC_8LANE_TOP_RF_RWIDTH=64 |
+define+RFS_VC107_1HMC_8LANE_TOP_RF_WWIDTH=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 |
|
|
-64bit |
-access +rwc |
|
-linedebug |
|
-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 |
|
-timescale 100ps/10ps |
|
### DUT-specific files |
|
-top tb_top |
/openhmc/trunk/openHMC/sim/tb/bfm/build/ncsim.tcl
0,0 → 1,14
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.hmc_controller_instance.hmc_rx_link_I -all -database waves -memories |
probe -create tb_top.dut_I.hmc_controller_instance.hmc_tx_link_I -all -database waves -memories |
|
probe -create tb_top.axi4_hmc_req_if -all -database waves |
probe -create tb_top.axi4_hmc_rsp_if -all -database waves |
|
set assert_output_stop_level failed |
set assert_report_incompletes 0 |
|
run |
|
/openhmc/trunk/openHMC/sim/tb/bfm/testlib/hmc_check_seq.sv
0,0 → 1,121
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_CHECK_SEQ |
`define HMC_CHECK_SEQ |
|
`include "config.h" |
|
class hmc_check_seq extends hmc_base_seq; |
|
function new(string name="hmc_check_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(hmc_check_seq) |
`uvm_declare_p_sequencer(hmc_vseqr) |
|
int timer; |
|
task body(); |
reg_hmc_controller_rf_status_general_c status; |
reg_hmc_controller_rf_sent_np_c sent_np; |
reg_hmc_controller_rf_rcvd_rsp_c rcvd_rsp; |
|
`uvm_info(get_type_name(), "Running Check Sequence", UVM_NONE) |
|
timer = 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); |
|
#1us; |
|
while( ((sent_np.fields.cnt_ != rcvd_rsp.fields.cnt_) || |
(status.fields.hmc_tokens_remaining_ != `HMC_TOKENS) || |
(status.fields.rx_tokens_remaining_ != `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_, `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_, `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 |
#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); |
|
#1us; |
|
//-- ***REPORTS*** |
//-- Report Packet Counts |
if(sent_np.fields.cnt_ != rcvd_rsp.fields.cnt_) begin |
`uvm_info(get_type_name(),$psprintf("Counted: %0d NP Requests, %0d Responses", sent_np.fields.cnt_, rcvd_rsp.fields.cnt_), UVM_LOW) |
end |
|
if(status.fields.hmc_tokens_remaining_ != `HMC_TOKENS) begin |
`uvm_fatal(get_type_name(),$psprintf("Responder token count in TX_LINK = %0d, should be %0d", status.fields.hmc_tokens_remaining_, `HMC_TOKENS)) |
end |
|
//-- Report Tokens in RX Link |
if(status.fields.rx_tokens_remaining_ != `RX_TOKENS) begin |
`uvm_fatal(get_type_name(),$psprintf("Requester token count in TX_LINK = %0d, should be %0d", status.fields.rx_tokens_remaining_, `RX_TOKENS)) |
end |
|
endtask : body |
|
endclass : hmc_check_seq |
|
`endif // HMC_CHECK_SEQ |
/openhmc/trunk/openHMC/sim/tb/bfm/testlib/hmc_base_test.sv
0,0 → 1,126
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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; |
|
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; |
|
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; |
|
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); |
|
set_config_int("*", "recording_detail", UVM_FULL); |
|
//-- create the testbench |
hmc_tb0 = hmc_tb#()::type_id::create("hmc_tb0", this); |
|
printer = new(); |
printer.knobs.depth = 5; |
|
endfunction : build_phase |
|
function void end_of_elaboration_phase(uvm_phase phase); |
super.end_of_elaboration_phase(phase); |
|
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 |
|
//function void report_phase(uvm_phase phase); |
// report_summarize(); |
//endfunction : report_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(hmc_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 |
/openhmc/trunk/openHMC/sim/tb/bfm/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 |
/openhmc/trunk/openHMC/sim/tb/bfm/testlib/simple_test/simple_test_seq.sv
0,0 → 1,92
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 |
|
`include "config.h" |
|
class simple_test_seq extends hmc_base_seq; |
|
function new(string name="simple_test_seq"); |
super.new(name); |
endfunction : new |
|
hmc_init_seq init; |
hmc_check_seq check; |
|
`uvm_object_utils(simple_test_seq) |
`uvm_declare_p_sequencer(hmc_vseqr) |
|
hmc_2_axi4_sequence #(.DATA_BYTES(`AXI4BYTES), .TUSER_WIDTH(`AXI4BYTES)) requests; |
int np_tag; |
rand bit hmc_command_np; |
rand int flit_count; |
|
virtual task body(); |
|
`uvm_info(get_type_name(), "starting simple_test_seq", UVM_NONE) |
|
//-- write your test here |
|
#1us; |
`uvm_do(init) |
#1us; |
|
|
`uvm_create_on(requests, p_sequencer.axi4_req_seqr) //-- create a new sequence item 'requests' on sequencer |
requests.num_packets = `NUM_PACKETS; //-- HMC packets to send |
requests.max_pkts_per_cycle = `FPW; //-- Set the maximum number of complete packets per AXI4 cycle |
`uvm_rand_send(requests) //-- randomize and send the parametrize sequence item |
|
#1us; |
`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 |
/openhmc/trunk/openHMC/sim/tb/bfm/testlib/hmc_init_seq.sv
0,0 → 1,121
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 |
|
`include "config.h" |
|
class hmc_init_seq extends hmc_base_seq; |
|
// hmc_link_config link_config; |
|
function new(string name="hmc_init_seq"); |
super.new(name); |
endfunction : new |
|
`uvm_object_utils(hmc_init_seq) |
`uvm_declare_p_sequencer(hmc_vseqr) |
|
bit phy_ready = 1'b0; |
bit link_up = 1'b0; |
int timeout = 0; |
|
task body(); |
|
//-- configure the HMC controller |
reg_hmc_controller_rf_control_c control; |
reg_hmc_controller_rf_status_general_c status; |
|
`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.first_cube_ID_ = `HMC_CUBID; |
control.fields.rx_token_count_ = `RX_TOKENS; |
control.fields.scrambler_disable_ = 0; |
control.fields.bit_slip_time_ = 72; |
control.fields.set_hmc_sleep_ = 0; |
control.fields.run_length_enable_ = 1; |
|
p_sequencer.rf_seqr_hmc.write_reg(control); |
|
//-- Wait until the PHY is ready |
$cast(status,p_sequencer.rf_seqr_hmc.get_by_name("status_general")); |
status.set_check_on_read(1'b0); |
while (phy_ready == 1'b0) |
begin |
#3us; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
phy_ready = status.fields.phy_ready_; |
`uvm_info(get_type_name(), "Waiting for the phy to get ready", UVM_NONE) |
end |
`uvm_info(get_type_name(), "Phy is ready", UVM_NONE) |
|
//-- Set Reset and Init Continue; |
control.fields.p_rst_n_ = 1; |
control.fields.hmc_init_cont_set_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
|
//-- 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_info(get_type_name(), "The link didn't come up... Resetting it.", UVM_NONE) |
control.fields.p_rst_n_ = 0; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
#30us; |
control.fields.p_rst_n_ = 1; |
p_sequencer.rf_seqr_hmc.write_reg(control); |
timeout = 0; |
end |
#4ns; |
p_sequencer.rf_seqr_hmc.read_reg(status); |
link_up = status.fields.link_up_; |
timeout = timeout + 1; |
end |
|
endtask : body |
|
endclass : hmc_init_seq |
|
`endif // HMC_INIT_SEQ |
/openhmc/trunk/openHMC/sim/tb/bfm/testlib/test_lib.sv
0,0 → 1,52
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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" |
|
//-- the init sequence |
`include "hmc_init_seq.sv" |
|
//-- check registers after test ends |
`include "hmc_check_seq.sv" |
|
//-- the tests |
`include "simple_test/simple_test_seq.sv" |
`include "simple_test/simple_test.sv" |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/tag_handler.sv
0,0 → 1,185
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 |
//bit tag_used[]; //-- mitmap of 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]}; |
bins illegal_tags = {[tag_count+1:$]}; |
} |
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]; |
// tag_used = new [num_tags]; |
|
// foreach (tag_used[i]) begin |
// tag_used[i] = 0; |
// end |
|
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; |
// tag_used[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; |
// tag_used[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); |
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 |
/openhmc/trunk/openHMC/sim/tb/bfm/src/tb_top_bfm.sv
0,0 → 1,139
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_module_pkg.sv" |
`include "cag_rgm_rfs_if.sv" |
|
`timescale 100ps/10ps |
|
module tb_top (); |
|
import uvm_pkg::*; |
|
//-- include the UVCs |
import axi4_stream_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 "bfm_2_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( |
.ACLK(clk_user), |
.ARESET_N(res_n) |
); |
|
axi4_stream_if #( |
.DATA_BYTES(`AXI4BYTES), |
.TUSER_WIDTH(`AXI4BYTES) |
) axi4_hmc_rsp_if( |
.ACLK(clk_user), |
.ARESET_N(res_n) |
); |
|
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) |
) rfs_hmc_if(); |
|
dut dut_I ( |
.clk_user(clk_user), |
.clk_hmc_refclk(clk_hmc_refclk), |
.res_n(res_n), |
|
.axi4_req(axi4_hmc_req_if), |
.axi4_rsp(axi4_hmc_rsp_if), |
|
.rfs_hmc(rfs_hmc_if) |
); |
|
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); |
|
//-- connect the BFM monitors with the Module UVC BFM to HMC Packet monitors |
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]); |
|
run_test(); |
end |
|
initial begin |
clk_user <= 1'b1; |
clk_hmc_refclk <= 1'b1; |
res_n <= 1'b0; |
#5001ns res_n <= 1'b1; |
end |
|
//-- 312.5MHz user Clock, keep it at least 312.5MHz so that it is >= clk_hmc in any configuration |
always #1.6ns clk_user <= ~clk_user; |
|
//-- 125 MHz |
always #4ns clk_hmc_refclk <= ~clk_hmc_refclk; |
|
endmodule : tb_top |
/openhmc/trunk/openHMC/sim/tb/bfm/src/hmc_tb.sv
0,0 → 1,190
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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) 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_module_env hmc_module; |
|
axi4_stream_config axi4_rsp_config; |
axi4_stream_config axi4_req_config; |
|
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) |
) rfs_hmc_I; |
|
rf_hmc_controller_rf_c rf_model_hmc; |
|
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) )) |
|
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() |
|
); |
|
set_inst_override_by_type("hmc_module.hmc_req_mon",hmc_module_mon::get_type(),bfm_2_hmc_mon::get_type()); |
set_inst_override_by_type("hmc_module.hmc_rsp_mon",hmc_module_mon::get_type(),bfm_2_hmc_mon::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 |
|
|
//-- create instances |
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_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); |
|
v_seqr = hmc_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; |
|
bfm_2_hmc_mon hmc_rsp_mon; |
bfm_2_hmc_mon hmc_req_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")); |
|
//-- cast BFM to HMC pkt monitors |
if ( !$cast(hmc_req_mon, hmc_module.hmc_req_mon)) |
`uvm_fatal(get_type_name(), $psprintf("error in hmc_req_mon cast")); |
if ( !$cast(hmc_rsp_mon, hmc_module.hmc_rsp_mon)) |
`uvm_fatal(get_type_name(), $psprintf("error in hmc_rsp_mon scast")); |
|
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; |
|
endfunction : connect_phase |
|
endclass : hmc_tb |
|
`endif // hmc_TB_SV |
/openhmc/trunk/openHMC/sim/tb/bfm/src/rgm/openhmc/register_file_model_16x.sv
0,0 → 1,541
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_hmc_controller_rf_16x_status_general_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [15:0] lane_polarity_reversed_; |
bit [5:0] rsvd_status_general_3_; |
bit [9:0] rx_tokens_remaining_; |
bit [5:0] rsvd_status_general_2_; |
bit [9:0] hmc_tokens_remaining_; |
bit [6:0] rsvd_status_general_1_; |
bit [0:0] phy_ready_; |
bit [3:0] rsvd_status_general_0_; |
bit [0:0] lanes_reversed_; |
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_hmc_controller_rf_16x_status_general_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_status_general_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_status_general_c |
|
// |
// HMC controller initialization status |
// |
class reg_hmc_controller_rf_16x_status_init_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] hmc_init_TS1_; |
bit [1:0] tx_init_status_; |
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_hmc_controller_rf_16x_status_init_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_status_init_c"); |
super.new(name); |
this.name = name; |
set_address('h8); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_status_init_c |
|
// |
// HMC controller control |
// |
class reg_hmc_controller_rf_16x_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [7:0] bit_slip_time_; |
bit [2:0] rsvd_control_3_; |
bit [4:0] irtry_to_send_; |
bit [2:0] rsvd_control_2_; |
bit [4:0] irtry_received_threshold_; |
bit [5:0] rsvd_control_1_; |
bit [9:0] rx_token_count_; |
bit [6:0] rsvd_control_0_; |
bit [0:0] debug_dont_send_tret_; |
bit [2:0] first_cube_ID_; |
bit [0:0] run_length_enable_; |
bit [0:0] scrambler_disable_; |
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_hmc_controller_rf_16x_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_control_c"); |
super.new(name); |
this.name = name; |
set_address('h10); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_control_c |
|
// |
// Count of packets that had data errors but valid flow information |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_poisoned_packets_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_poisoned_packets_c"); |
super.new(name); |
this.name = name; |
set_address('h18); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_poisoned_packets_c |
|
// |
// Nonposted requests sent to the HMC |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_sent_np_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_sent_np_c"); |
super.new(name); |
this.name = name; |
set_address('h20); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_sent_np_c |
|
// |
// Posted requests sent to the HMC |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_sent_p_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_sent_p_c"); |
super.new(name); |
this.name = name; |
set_address('h28); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_sent_p_c |
|
// |
// Read requests sent to the HMC |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_sent_r_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_sent_r_c"); |
super.new(name); |
this.name = name; |
set_address('h30); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_sent_r_c |
|
// |
// Responses received from the HMC |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_rcvd_rsp_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_rcvd_rsp_c"); |
super.new(name); |
this.name = name; |
set_address('h38); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_rcvd_rsp_c |
|
// |
// Reset performance counters |
// |
class reg_hmc_controller_rf_16x_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_hmc_controller_rf_16x_counter_reset_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_counter_reset_c"); |
super.new(name); |
this.name = name; |
set_address('h40); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_counter_reset_c |
|
// |
// Count of re-transmit requests (seq num and bit errors) |
// |
class reg_hmc_controller_rf_16x_link_retries_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [31:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_hmc_controller_rf_16x_link_retries_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_link_retries_c"); |
super.new(name); |
this.name = name; |
set_address('h48); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_link_retries_c |
|
// |
// The number of bit_flips forced by the run length limiter |
// |
class reg_hmc_controller_rf_16x_run_length_bit_flip_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [31:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_hmc_controller_rf_16x_run_length_bit_flip_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_16x_run_length_bit_flip_c"); |
super.new(name); |
this.name = name; |
set_address('h50); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_16x_run_length_bit_flip_c |
|
class rf_hmc_controller_rf_16x_c extends cag_rgm_register_file; |
|
rand reg_hmc_controller_rf_16x_status_general_c status_general; |
rand reg_hmc_controller_rf_16x_status_init_c status_init; |
rand reg_hmc_controller_rf_16x_control_c control; |
rand reg_hmc_controller_rf_16x_poisoned_packets_c poisoned_packets; |
rand reg_hmc_controller_rf_16x_sent_np_c sent_np; |
rand reg_hmc_controller_rf_16x_sent_p_c sent_p; |
rand reg_hmc_controller_rf_16x_sent_r_c sent_r; |
rand reg_hmc_controller_rf_16x_rcvd_rsp_c rcvd_rsp; |
rand reg_hmc_controller_rf_16x_counter_reset_c counter_reset; |
rand reg_hmc_controller_rf_16x_link_retries_c link_retries; |
rand reg_hmc_controller_rf_16x_run_length_bit_flip_c run_length_bit_flip; |
|
`uvm_object_utils(rf_hmc_controller_rf_16x_c) |
|
function new(string name="rf_hmc_controller_rf_16x_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
status_general = reg_hmc_controller_rf_16x_status_general_c::type_id::create("status_general"); |
status_general.set_address('h0); |
add_register(status_general); |
status_init = reg_hmc_controller_rf_16x_status_init_c::type_id::create("status_init"); |
status_init.set_address('h8); |
add_register(status_init); |
control = reg_hmc_controller_rf_16x_control_c::type_id::create("control"); |
control.set_address('h10); |
add_register(control); |
poisoned_packets = reg_hmc_controller_rf_16x_poisoned_packets_c::type_id::create("poisoned_packets"); |
poisoned_packets.set_address('h18); |
add_register(poisoned_packets); |
sent_np = reg_hmc_controller_rf_16x_sent_np_c::type_id::create("sent_np"); |
sent_np.set_address('h20); |
add_register(sent_np); |
sent_p = reg_hmc_controller_rf_16x_sent_p_c::type_id::create("sent_p"); |
sent_p.set_address('h28); |
add_register(sent_p); |
sent_r = reg_hmc_controller_rf_16x_sent_r_c::type_id::create("sent_r"); |
sent_r.set_address('h30); |
add_register(sent_r); |
rcvd_rsp = reg_hmc_controller_rf_16x_rcvd_rsp_c::type_id::create("rcvd_rsp"); |
rcvd_rsp.set_address('h38); |
add_register(rcvd_rsp); |
counter_reset = reg_hmc_controller_rf_16x_counter_reset_c::type_id::create("counter_reset"); |
counter_reset.set_address('h40); |
add_register(counter_reset); |
link_retries = reg_hmc_controller_rf_16x_link_retries_c::type_id::create("link_retries"); |
link_retries.set_address('h48); |
add_register(link_retries); |
run_length_bit_flip = reg_hmc_controller_rf_16x_run_length_bit_flip_c::type_id::create("run_length_bit_flip"); |
run_length_bit_flip.set_address('h50); |
add_register(run_length_bit_flip); |
endfunction : new |
|
endclass : rf_hmc_controller_rf_16x_c |
|
// |
// Pattern Generator Control Register |
// |
class reg_pattern_gen_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [2:0] cubID_size_; |
bit [2:0] first_cube_ID_; |
bit [0:0] hmc_gen_running_; |
bit [0:0] hmc_gen_enable_; |
bit [6:0] hmc_gen_read_ratio_; |
bit [3:0] hmc_gen_write_size_; |
bit [3:0] hmc_gen_read_size_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_pattern_gen_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_pattern_gen_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h80); |
endfunction : new |
|
endclass : reg_pattern_gen_rf_control_c |
|
// |
// dummy |
// |
class reg_pattern_gen_rf_dummy_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [3:0] dummy_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_pattern_gen_rf_dummy_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_pattern_gen_rf_dummy_c"); |
super.new(name); |
this.name = name; |
set_address('h88); |
endfunction : new |
|
endclass : reg_pattern_gen_rf_dummy_c |
|
class rf_pattern_gen_rf_c extends cag_rgm_register_file; |
|
rand reg_pattern_gen_rf_control_c control; |
rand reg_pattern_gen_rf_dummy_c dummy; |
|
`uvm_object_utils(rf_pattern_gen_rf_c) |
|
function new(string name="rf_pattern_gen_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h80); |
control = reg_pattern_gen_rf_control_c::type_id::create("control"); |
control.set_address('h80); |
add_register(control); |
dummy = reg_pattern_gen_rf_dummy_c::type_id::create("dummy"); |
dummy.set_address('h88); |
add_register(dummy); |
endfunction : new |
|
endclass : rf_pattern_gen_rf_c |
|
// |
// General Reset controlable via i2c |
// |
class reg_res_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] res_n_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_res_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_res_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h90); |
endfunction : new |
|
endclass : reg_res_rf_control_c |
|
// |
// dummy |
// |
class reg_res_rf_dummy_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] dummy_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_res_rf_dummy_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_res_rf_dummy_c"); |
super.new(name); |
this.name = name; |
set_address('h98); |
endfunction : new |
|
endclass : reg_res_rf_dummy_c |
|
class rf_res_rf_c extends cag_rgm_register_file; |
|
rand reg_res_rf_control_c control; |
rand reg_res_rf_dummy_c dummy; |
|
`uvm_object_utils(rf_res_rf_c) |
|
function new(string name="rf_res_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h90); |
control = reg_res_rf_control_c::type_id::create("control"); |
control.set_address('h90); |
add_register(control); |
dummy = reg_res_rf_dummy_c::type_id::create("dummy"); |
dummy.set_address('h98); |
add_register(dummy); |
endfunction : new |
|
endclass : rf_res_rf_c |
|
class rf_vc107_1hmc_16lane_top_rf_c extends cag_rgm_register_file; |
|
rand rf_hmc_controller_rf_16x_c hmc_controller_rf_16x; |
rand rf_pattern_gen_rf_c pattern_gen_rf; |
rand rf_res_rf_c res_rf; |
|
`uvm_object_utils(rf_vc107_1hmc_16lane_top_rf_c) |
|
function new(string name="rf_vc107_1hmc_16lane_top_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
hmc_controller_rf_16x = rf_hmc_controller_rf_16x_c::type_id::create("hmc_controller_rf_16x"); |
add_register_file(hmc_controller_rf_16x); |
pattern_gen_rf = rf_pattern_gen_rf_c::type_id::create("pattern_gen_rf"); |
add_register_file(pattern_gen_rf); |
res_rf = rf_res_rf_c::type_id::create("res_rf"); |
add_register_file(res_rf); |
endfunction : new |
|
endclass : rf_vc107_1hmc_16lane_top_rf_c |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/rgm/openhmc/register_file_model_8x.sv
0,0 → 1,614
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_hmc_controller_rf_status_general_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [7:0] lane_polarity_reversed_; |
bit [5:0] rsvd_status_general_3_; |
bit [9:0] rx_tokens_remaining_; |
bit [5:0] rsvd_status_general_2_; |
bit [9:0] hmc_tokens_remaining_; |
bit [6:0] rsvd_status_general_1_; |
bit [0:0] phy_ready_; |
bit [3:0] rsvd_status_general_0_; |
bit [0:0] lanes_reversed_; |
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_hmc_controller_rf_status_general_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_status_general_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_status_general_c |
|
// |
// HMC controller initialization status |
// |
class reg_hmc_controller_rf_status_init_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] hmc_init_TS1_; |
bit [1:0] tx_init_status_; |
bit [0:0] all_descramblers_aligned_; |
bit [7:0] descrambler_aligned_; |
bit [7:0] descrambler_part_aligned_; |
bit [7:0] lane_descramblers_locked_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_hmc_controller_rf_status_init_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_status_init_c"); |
super.new(name); |
this.name = name; |
set_address('h8); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_status_init_c |
|
// |
// HMC controller control |
// |
class reg_hmc_controller_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [7:0] bit_slip_time_; |
bit [2:0] rsvd_control_3_; |
bit [4:0] irtry_to_send_; |
bit [2:0] rsvd_control_2_; |
bit [4:0] irtry_received_threshold_; |
bit [5:0] rsvd_control_1_; |
bit [9:0] rx_token_count_; |
bit [6:0] rsvd_control_0_; |
bit [0:0] debug_dont_send_tret_; |
bit [2:0] first_cube_ID_; |
bit [0:0] run_length_enable_; |
bit [0:0] scrambler_disable_; |
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_hmc_controller_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h10); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_control_c |
|
// |
// Count of packets that had data errors but valid flow information |
// |
class reg_hmc_controller_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_hmc_controller_rf_poisoned_packets_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_poisoned_packets_c"); |
super.new(name); |
this.name = name; |
set_address('h18); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_poisoned_packets_c |
|
// |
// Nonposted requests sent to the HMC |
// |
class reg_hmc_controller_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_hmc_controller_rf_sent_np_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_sent_np_c"); |
super.new(name); |
this.name = name; |
set_address('h20); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_sent_np_c |
|
// |
// Posted requests sent to the HMC |
// |
class reg_hmc_controller_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_hmc_controller_rf_sent_p_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_sent_p_c"); |
super.new(name); |
this.name = name; |
set_address('h28); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_sent_p_c |
|
// |
// Read requests sent to the HMC |
// |
class reg_hmc_controller_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_hmc_controller_rf_sent_r_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_sent_r_c"); |
super.new(name); |
this.name = name; |
set_address('h30); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_sent_r_c |
|
// |
// Responses received from the HMC |
// |
class reg_hmc_controller_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_hmc_controller_rf_rcvd_rsp_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_rcvd_rsp_c"); |
super.new(name); |
this.name = name; |
set_address('h38); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_rcvd_rsp_c |
|
// |
// Reset performance counters |
// |
class reg_hmc_controller_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_hmc_controller_rf_counter_reset_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_counter_reset_c"); |
super.new(name); |
this.name = name; |
set_address('h40); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_counter_reset_c |
|
// |
// Count of re-transmit requests (seq num and bit errors) |
// |
class reg_hmc_controller_rf_link_retries_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [31:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_hmc_controller_rf_link_retries_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_link_retries_c"); |
super.new(name); |
this.name = name; |
set_address('h48); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_link_retries_c |
|
// |
// The number of bit_flips forced by the run length limiter |
// |
class reg_hmc_controller_rf_run_length_bit_flip_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [31:0] count_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_hmc_controller_rf_run_length_bit_flip_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_hmc_controller_rf_run_length_bit_flip_c"); |
super.new(name); |
this.name = name; |
set_address('h50); |
endfunction : new |
|
endclass : reg_hmc_controller_rf_run_length_bit_flip_c |
|
class rf_hmc_controller_rf_c extends cag_rgm_register_file; |
|
rand reg_hmc_controller_rf_status_general_c status_general; |
rand reg_hmc_controller_rf_status_init_c status_init; |
rand reg_hmc_controller_rf_control_c control; |
rand reg_hmc_controller_rf_poisoned_packets_c poisoned_packets; |
rand reg_hmc_controller_rf_sent_np_c sent_np; |
rand reg_hmc_controller_rf_sent_p_c sent_p; |
rand reg_hmc_controller_rf_sent_r_c sent_r; |
rand reg_hmc_controller_rf_rcvd_rsp_c rcvd_rsp; |
rand reg_hmc_controller_rf_counter_reset_c counter_reset; |
rand reg_hmc_controller_rf_link_retries_c link_retries; |
rand reg_hmc_controller_rf_run_length_bit_flip_c run_length_bit_flip; |
|
`uvm_object_utils(rf_hmc_controller_rf_c) |
|
function new(string name="rf_hmc_controller_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
status_general = reg_hmc_controller_rf_status_general_c::type_id::create("status_general"); |
status_general.set_address('h0); |
add_register(status_general); |
status_init = reg_hmc_controller_rf_status_init_c::type_id::create("status_init"); |
status_init.set_address('h8); |
add_register(status_init); |
control = reg_hmc_controller_rf_control_c::type_id::create("control"); |
control.set_address('h10); |
add_register(control); |
poisoned_packets = reg_hmc_controller_rf_poisoned_packets_c::type_id::create("poisoned_packets"); |
poisoned_packets.set_address('h18); |
add_register(poisoned_packets); |
sent_np = reg_hmc_controller_rf_sent_np_c::type_id::create("sent_np"); |
sent_np.set_address('h20); |
add_register(sent_np); |
sent_p = reg_hmc_controller_rf_sent_p_c::type_id::create("sent_p"); |
sent_p.set_address('h28); |
add_register(sent_p); |
sent_r = reg_hmc_controller_rf_sent_r_c::type_id::create("sent_r"); |
sent_r.set_address('h30); |
add_register(sent_r); |
rcvd_rsp = reg_hmc_controller_rf_rcvd_rsp_c::type_id::create("rcvd_rsp"); |
rcvd_rsp.set_address('h38); |
add_register(rcvd_rsp); |
counter_reset = reg_hmc_controller_rf_counter_reset_c::type_id::create("counter_reset"); |
counter_reset.set_address('h40); |
add_register(counter_reset); |
link_retries = reg_hmc_controller_rf_link_retries_c::type_id::create("link_retries"); |
link_retries.set_address('h48); |
add_register(link_retries); |
run_length_bit_flip = reg_hmc_controller_rf_run_length_bit_flip_c::type_id::create("run_length_bit_flip"); |
run_length_bit_flip.set_address('h50); |
add_register(run_length_bit_flip); |
endfunction : new |
|
endclass : rf_hmc_controller_rf_c |
|
// |
// Pattern Generator Control Register |
// |
class reg_pattern_gen_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [2:0] cubID_size_; |
bit [2:0] first_cube_ID_; |
bit [0:0] hmc_gen_running_; |
bit [0:0] hmc_gen_enable_; |
bit [6:0] hmc_gen_read_ratio_; |
bit [3:0] hmc_gen_write_size_; |
bit [3:0] hmc_gen_read_size_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_pattern_gen_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_pattern_gen_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h80); |
endfunction : new |
|
endclass : reg_pattern_gen_rf_control_c |
|
// |
// dummy |
// |
class reg_pattern_gen_rf_dummy_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [3:0] dummy_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_pattern_gen_rf_dummy_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_pattern_gen_rf_dummy_c"); |
super.new(name); |
this.name = name; |
set_address('h88); |
endfunction : new |
|
endclass : reg_pattern_gen_rf_dummy_c |
|
class rf_pattern_gen_rf_c extends cag_rgm_register_file; |
|
rand reg_pattern_gen_rf_control_c control; |
rand reg_pattern_gen_rf_dummy_c dummy; |
|
`uvm_object_utils(rf_pattern_gen_rf_c) |
|
function new(string name="rf_pattern_gen_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h80); |
control = reg_pattern_gen_rf_control_c::type_id::create("control"); |
control.set_address('h80); |
add_register(control); |
dummy = reg_pattern_gen_rf_dummy_c::type_id::create("dummy"); |
dummy.set_address('h88); |
add_register(dummy); |
endfunction : new |
|
endclass : rf_pattern_gen_rf_c |
|
// |
// General Reset controlable via i2c |
// |
class reg_res_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] res_n_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_res_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_res_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('h90); |
endfunction : new |
|
endclass : reg_res_rf_control_c |
|
// |
// dummy |
// |
class reg_res_rf_dummy_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] dummy_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_res_rf_dummy_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_res_rf_dummy_c"); |
super.new(name); |
this.name = name; |
set_address('h98); |
endfunction : new |
|
endclass : reg_res_rf_dummy_c |
|
class rf_res_rf_c extends cag_rgm_register_file; |
|
rand reg_res_rf_control_c control; |
rand reg_res_rf_dummy_c dummy; |
|
`uvm_object_utils(rf_res_rf_c) |
|
function new(string name="rf_res_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h90); |
control = reg_res_rf_control_c::type_id::create("control"); |
control.set_address('h90); |
add_register(control); |
dummy = reg_res_rf_dummy_c::type_id::create("dummy"); |
dummy.set_address('h98); |
add_register(dummy); |
endfunction : new |
|
endclass : rf_res_rf_c |
|
// |
// General Reset controlable via i2c |
// |
class reg_phy_rf_control_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [0:0] lpm_en_; |
bit [0:0] rx_res_n_; |
bit [0:0] tx_res_n_; |
bit [0:0] res_n_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_phy_rf_control_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_phy_rf_control_c"); |
super.new(name); |
this.name = name; |
set_address('ha0); |
endfunction : new |
|
endclass : reg_phy_rf_control_c |
|
// |
// status |
// |
class reg_phy_rf_status_c extends cag_rgm_register; |
|
typedef struct packed { |
bit [7:0] cdr_locked_; |
} pkd_flds_s; |
|
`cag_rgm_register_fields(pkd_flds_s) |
|
`uvm_object_utils_begin(reg_phy_rf_status_c) |
`uvm_field_int(fields,UVM_ALL_ON) |
`uvm_object_utils_end |
|
function new(string name="reg_phy_rf_status_c"); |
super.new(name); |
this.name = name; |
set_address('ha8); |
endfunction : new |
|
endclass : reg_phy_rf_status_c |
|
class rf_phy_rf_c extends cag_rgm_register_file; |
|
rand reg_phy_rf_control_c control; |
rand reg_phy_rf_status_c status; |
|
`uvm_object_utils(rf_phy_rf_c) |
|
function new(string name="rf_phy_rf_c"); |
super.new(name); |
this.name = name; |
set_address('ha0); |
control = reg_phy_rf_control_c::type_id::create("control"); |
control.set_address('ha0); |
add_register(control); |
status = reg_phy_rf_status_c::type_id::create("status"); |
status.set_address('ha8); |
add_register(status); |
endfunction : new |
|
endclass : rf_phy_rf_c |
|
class rf_vc107_1hmc_8lane_top_rf_c extends cag_rgm_register_file; |
|
rand rf_hmc_controller_rf_c hmc_controller_rf; |
rand rf_pattern_gen_rf_c pattern_gen_rf; |
rand rf_res_rf_c res_rf; |
rand rf_phy_rf_c phy_rf; |
|
`uvm_object_utils(rf_vc107_1hmc_8lane_top_rf_c) |
|
function new(string name="rf_vc107_1hmc_8lane_top_rf_c"); |
super.new(name); |
this.name = name; |
set_address('h0); |
hmc_controller_rf = rf_hmc_controller_rf_c::type_id::create("hmc_controller_rf"); |
add_register_file(hmc_controller_rf); |
pattern_gen_rf = rf_pattern_gen_rf_c::type_id::create("pattern_gen_rf"); |
add_register_file(pattern_gen_rf); |
res_rf = rf_res_rf_c::type_id::create("res_rf"); |
add_register_file(res_rf); |
phy_rf = rf_phy_rf_c::type_id::create("phy_rf"); |
add_register_file(phy_rf); |
endfunction : new |
|
endclass : rf_vc107_1hmc_8lane_top_rf_c |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/targets/config.h
0,0 → 1,42
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 RX_TOKENS 100 |
`define HMC_TOKENS 100 |
`define HMC_CUBID 0 |
/openhmc/trunk/openHMC/sim/tb/bfm/src/targets/dut_openhmc_behavioral_bfm.sv
0,0 → 1,394
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/10ps |
|
|
`include "config.h" |
|
|
module dut #( |
//*************************Don't touch! Control the design in config.h and 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, |
|
//AXI4 interface ports |
axi4_stream_if axi4_req, |
axi4_stream_if axi4_rsp, |
|
//Register File interface |
cag_rgm_rfs_if rfs_hmc |
); |
|
//----------------------------- Configuration and Debug |
bit disable_lane_delays = 1; |
bit disable_lane_polarity = 1; |
bit disable_scramblers = 0; |
//Lane Reversal |
localparam LANE_REVERSAL_TX = 0; |
localparam LANE_REVERSAL_RX = 0; |
|
//Lane delays |
localparam LOG_DELAY = 5; |
typedef bit [LOG_DELAY-1:0] delay_t; |
delay_t [NUM_LANES-1:0] delays_Rx; |
delay_t [NUM_LANES-1:0] delays_Tx; |
//Polarity |
bit [NUM_LANES-1:0] polarity_Rx; |
|
//----------------------------- Wiring openHMC controller |
wire [DWIDTH-1:0] to_serializers; |
wire [DWIDTH-1:0] from_deserializers; |
wire [NUM_LANES-1:0] bit_slip; |
bit P_RST_N; |
|
// Wire the HMC BFM model |
wire LxRXPS; // HMC input |
wire LxTXPS; // HMC output |
wire FERR_N; // HMC output |
wire hmc_refclkp; |
wire hmc_refclkn; |
wire [16-1:0] LxRXP; |
wire [16-1:0] LxRXN; |
wire [16-1:0] LxTXP; |
wire [16-1:0] LxTXN; |
|
//----------------------------- Signal Routing from SerDes to HMC |
wire [NUM_LANES-1:0] serial_Rx; |
wire [NUM_LANES-1:0] serial_Rx_routed; |
wire [NUM_LANES-1:0] serial_Txn; |
wire [NUM_LANES-1:0] serial_Txp; |
wire [NUM_LANES-1:0] serial_Tx_routed; |
|
assign LxRXP = {serial_Tx_routed}; |
assign LxRXN = ~LxRXP; |
assign serial_Rx = LxTXP[NUM_LANES-1:0]; |
|
//----------------------------- Define the Clocks |
bit clk_10G; |
bit clk_hmc; |
assign hmc_refclkp = clk_hmc_refclk; |
assign hmc_refclkn = ~hmc_refclkp; |
|
//----------------------------- Attach the Register File System interface |
assign rfs_hmc_if.clk = clk_hmc; |
assign rfs_hmc_if.res_n = res_n; |
|
//----------------------------- Randomize configuration and Load HMC Link Config |
int n = 0; |
initial begin |
var cls_link_cfg link_cfg; // declare configuration object |
|
//Randomize lane delays, polarity, and reversal |
repeat(NUM_LANES) begin |
delays_Rx[n] = disable_lane_delays ? 0 : $urandom_range(0,8); |
delays_Tx[n] = disable_lane_delays ? 0 : $urandom_range(0,8); |
polarity_Rx[n] = disable_lane_polarity ? 0 : $urandom_range(0,1); |
n++; |
end |
|
#(5us); |
|
//Create a new HMC link config |
link_cfg = new(); |
|
link_cfg.cfg_cid = `HMC_CUBID; |
link_cfg.cfg_lane_auto_correct = 1; |
link_cfg.cfg_rsp_open_loop = 0; |
|
// These are set to match the design |
link_cfg.cfg_rx_clk_ratio = 40; |
link_cfg.cfg_half_link_mode_rx = (NUM_LANES==8); |
|
link_cfg.cfg_tx_clk_ratio = 40; |
link_cfg.cfg_half_link_mode_tx = (NUM_LANES==8); |
|
link_cfg.cfg_descram_enb = !disable_scramblers; |
link_cfg.cfg_scram_enb = !disable_scramblers; |
|
link_cfg.cfg_tokens = `HMC_TOKENS; |
link_cfg.cfg_init_retry_rxcnt = 16; |
link_cfg.cfg_init_retry_txcnt = 16; |
|
//***Enable Errors - Dont touch |
//link_cfg.cfg_rsp_dln = 5; |
//link_cfg.cfg_rsp_lng = 5; |
//link_cfg.cfg_rsp_crc = 5; |
//link_cfg.cfg_rsp_seq = 5; |
//link_cfg.cfg_rsp_poison= 5; |
// |
|
link_cfg.cfg_retry_enb = 1; |
|
if(!disable_scramblers) |
link_cfg.cfg_tx_rl_lim = 85; |
|
tb_top.dut_I.hmc_bfm0.set_config(link_cfg,0); |
//link_cfg.display(); //uncomment for full link configuration output |
|
$display("***** HMC BFM CONFIGURATION IS COMPLETE *****"); |
end |
|
//----------------------------- Generate Clocks |
generate |
begin : clocking_gen |
initial clk_10G = 1'b1; |
always #0.05ns clk_10G = ~clk_10G; |
|
initial clk_hmc = 1'bZ; |
always begin |
if (clk_hmc == 1'bZ ) |
begin |
@(posedge clk_hmc_refclk); |
clk_hmc = 1'b1; |
end |
//Clock frequency depends on the link-width and datapath-width. Lane speed is fixed to 10Gbit |
case(FPW) |
2: begin |
if(NUM_LANES==8) |
#1.6ns clk_hmc = !clk_hmc; |
else begin |
$display("*******************************************************"); |
$display("***** Sorry - This configuration is not supported *****"); |
$display("***** Please use FPW=2 only with 8 lanes *****"); |
$display("*******************************************************"); |
$finish; |
end |
end |
4: begin |
if(NUM_LANES==8) |
#3.2ns clk_hmc = !clk_hmc; |
else |
#1.6ns clk_hmc = !clk_hmc; |
end |
6: begin |
if(NUM_LANES==8) |
#4.8ns clk_hmc = !clk_hmc; |
else |
#2.4ns clk_hmc = !clk_hmc; |
end |
8: begin |
if(NUM_LANES==8) |
#6.4ns clk_hmc = !clk_hmc; |
else |
#3.2ns clk_hmc = !clk_hmc; |
end |
endcase |
end |
end |
endgenerate |
|
//----------------------------- Signal Routing |
genvar lane; |
generate |
for (lane=0; lane<NUM_LANES; lane++) begin : delay_lanes_gen |
routing #( |
.LOG_DELAY(LOG_DELAY) |
) routing_Tx ( |
.clk(clk_10G), |
.data_in(serial_Txp[lane]), |
.delay_in(delays_Tx[lane]), |
.polarity_reverse_in(1'b0), |
.data_out(serial_Tx_routed[(LANE_REVERSAL_TX ? NUM_LANES-1-lane : lane)]) |
); |
routing #( |
.LOG_DELAY(LOG_DELAY) |
) routing_Rx ( |
.clk(clk_10G), |
.data_in(serial_Rx[lane]), |
.delay_in(delays_Rx[lane]), |
.polarity_reverse_in(polarity_Rx[lane]), |
.data_out(serial_Rx_routed[(LANE_REVERSAL_RX ? NUM_LANES-1-lane : lane)]) |
); |
end |
endgenerate |
|
//----------------------------- Behavioral SerDes |
generate |
begin : serializers_gen |
assign serial_Txn = ~serial_Txp; |
|
for (lane=0; lane<NUM_LANES; lane++) begin : behavioral_gen |
serializer #( |
.DWIDTH(LANE_WIDTH) |
) serializer_I ( |
.clk(clk_hmc), |
.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), |
.fast_clk(clk_10G), |
.bit_slip(bit_slip[lane]), |
.data_in(serial_Rx_routed[lane]), |
.data_out(from_deserializers[lane*LANE_WIDTH+LANE_WIDTH-1:lane*LANE_WIDTH]) |
); |
end |
end |
endgenerate |
|
//===================================================================================================== |
//----------------------------------------------------------------------------------------------------- |
//---------INSTANTIATIONS HERE------------------------------------------------------------------------- |
//----------------------------------------------------------------------------------------------------- |
//===================================================================================================== |
hmc_controller_top #( |
.DWIDTH(DWIDTH), |
.LOG_FPW(LOG_FPW), |
.FPW(FPW), |
.LOG_NUM_LANES(LOG_NUM_LANES), |
.NUM_LANES(NUM_LANES), |
.NUM_DATA_BYTES(NUM_DATA_BYTES) |
) |
hmc_controller_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_ready(res_n), |
|
//---------------------------------- |
//----Connect HMC |
//---------------------------------- |
.P_RST_N(P_RST_N), |
.hmc_LxRXPS(LxRXPS), |
.hmc_LxTXPS(LxTXPS), |
.FERR_N(FERR_N), |
|
//---------------------------------- |
//----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) |
|
); |
|
|
//******************************************************************************** |
// From MICRON's hmc_bfm_tb.sv |
//****************************************** |
//BFM |
hmc_bfm #( |
.num_links_c (1) |
) |
hmc_bfm0 ( |
.LxRXP (LxRXP), |
.LxRXN (LxRXN), |
.LxTXP (LxTXP), |
.LxTXN (LxTXN), |
.LxRXPS (LxRXPS), |
.LxTXPS (LxTXPS), |
.FERR_N (FERR_N), |
|
.REFCLKP (hmc_refclkp), |
.REFCLKN (hmc_refclkn), |
.REFCLKSEL (1'b0), |
.P_RST_N (P_RST_N), |
|
.TRST_N (1'b0), |
.TCK (1'b0), |
.TMS (1'b0), |
.TDI (1'b0), |
.TDO (), |
|
.SCL (1'b0), |
.SDA (), |
|
.CUB (3'b0), |
.REFCLK_BOOT (2'b0), |
|
.EXTRESTP (), |
.EXTRESTN (), |
.EXTRESBP (), |
.EXTRESBN () |
); |
|
endmodule : dut |
|
`default_nettype wire |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/bfm_2_hmc_monitor.sv
0,0 → 1,126
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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; |
|
pkt_analysis_port#() mb_pkt; |
cls_pkt pkt; |
hmc_packet hmc_pkt; |
|
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; |
|
`uvm_component_utils(bfm_2_hmc_mon) |
|
function new ( string name="bfm_2_hmc_mon", uvm_component parent ); |
super.new(name, parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
if(uvm_config_db#(pkt_analysis_port#())::get(this, "", "mb_pkt",mb_pkt) ) begin |
end else |
`uvm_fatal(get_type_name(),"pkt_analysis_port#() is not set") |
endfunction : build_phase |
|
task run(); |
`uvm_info(get_type_name(),$psprintf("starting BFM_2_HMC converter"), UVM_MEDIUM) |
forever begin |
mb_pkt.get(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 |
|
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 |
|
hmc_pkt = hmc_packet::type_id::create("packet", this); |
void'(hmc_pkt.unpack(bitstream)); |
|
`uvm_info(get_type_name(),$psprintf("Got a BFM Packet: %s",pkt.convert2string()), UVM_HIGH) |
|
//-- write to HMC Monitor / Scoreboard |
|
if (hmc_pkt.get_command_type() == HMC_FLOW_TYPE )begin //-- do not write if Flow Control Packet |
`uvm_info(get_type_name(),$psprintf("receiving non request/response packet"), UVM_HIGH) |
`uvm_info(get_type_name(),$psprintf("hmc_packet: \n%s", hmc_pkt.sprint()), UVM_HIGH) |
end else begin |
`uvm_info(get_type_name(),$psprintf("commiting translated packet"), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("hmc_packet: \n%s", hmc_pkt.sprint()), UVM_HIGH) |
|
item_collected_port.write(hmc_pkt); |
end |
end |
end |
|
endtask |
|
endclass |
|
|
`endif |
/openhmc/trunk/openHMC/sim/tb/bfm/src/behavioral/deserializer.v
0,0 → 1,99
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
`timescale 100ps/100ps |
|
module deserializer #( |
parameter LOG_DWIDTH=7, |
parameter DWIDTH=64 |
) |
( |
input wire clk, |
input wire fast_clk, |
input wire bit_slip, |
input wire data_in, |
output reg [DWIDTH-1:0] data_out |
); |
|
reg [DWIDTH-1:0] tmp_buffer; |
reg [DWIDTH-1:0] buffer; |
reg [DWIDTH-1:0] buffer2; |
reg [DWIDTH-1:0] buffer3; |
reg [LOG_DWIDTH-1:0] curr_bit = 'h0; |
reg bit_slip_done = 1'b0; |
reg [8:0] bit_slip_cnt=9'h0; |
|
// SEQUENTIAL PROCESS |
always @ (posedge fast_clk) |
begin |
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; |
|
tmp_buffer[curr_bit] <= data_in; |
if (|curr_bit == 1'b0) |
buffer <= tmp_buffer; |
end |
|
always @ (posedge clk) |
begin |
buffer2 <= buffer; |
buffer3 <= buffer2; |
|
if (bit_slip) |
bit_slip_cnt = bit_slip_cnt + 1; |
if (bit_slip_cnt < 63) |
data_out <= buffer3; |
else if (bit_slip_cnt < 127) |
data_out <= buffer2; |
else if (bit_slip_cnt < 191) |
data_out <= buffer; |
end |
|
endmodule |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/behavioral/routing.v
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/>. |
* |
* |
*/ |
|
`timescale 100ps/100ps |
|
module routing #( |
parameter LOG_DELAY=6 |
) |
( |
input wire clk, |
input wire data_in, |
input wire [LOG_DELAY-1:0] delay_in, |
input wire polarity_reverse_in, |
output wire data_out |
); |
|
reg [2**(LOG_DELAY+1)-1:0] wire_delay; |
|
// SEQUENTIAL PROCESS |
always @ (posedge clk) |
begin |
wire_delay <= {wire_delay[2**(LOG_DELAY+1)-2:0], data_in^polarity_reverse_in}; |
end |
|
assign data_out = wire_delay[delay_in+2**LOG_DELAY]; |
|
endmodule |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/behavioral/serializer.v
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/>. |
* |
* |
*/ |
|
`timescale 100ps/100ps |
|
module serializer #( |
parameter LOG_DWIDTH=7, |
parameter DWIDTH=64 |
) |
( |
input wire clk, |
input wire fast_clk, |
input wire [DWIDTH-1:0] data_in, |
output wire data_out |
); |
|
reg [DWIDTH-1:0] buffer; |
|
// SEQUENTIAL PROCESS |
always @ (posedge clk) |
begin |
buffer <= data_in; |
end |
|
reg [LOG_DWIDTH-1:0] curr_bit = 'h0; |
reg clk_d1; |
|
always @ (posedge fast_clk) |
begin |
curr_bit <= curr_bit + 1; |
clk_d1 <= clk; |
if (!clk_d1 && clk) |
curr_bit <= 0; |
end |
|
assign data_out = buffer[curr_bit]; |
|
endmodule |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/hmc_2_axi4_sequence.sv
0,0 → 1,284
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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[$]; |
|
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_LOW) |
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 |
hmc_packet hmc_pkt; |
bit first_pkt = 1; |
|
|
|
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 |
//`uvm_info(get_type_name(),$psprintf("delay for axi4_cycle 0 is %0d", axi4_item.delay), UVM_MEDIUM) |
|
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 (first_pkt) begin |
if (current_flit[128]) begin //-- If current flit is header |
flit_offset+= hmc_pkt.flit_delay; |
end |
first_pkt = 0; |
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) |
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; |
axi4_item.delay = (flit_offset / FPW) -1; //-- flit offset contains also empty flits |
if (flit_offset % FPW >0) |
axi4_item.delay +=1; |
`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; |
`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//write flit to cycle |
axi4_item.tdata[(flit_offset*128)+i] = current_flit[i]; |
end |
|
//-- 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 footer |
axi4_item.tuser[TAILS +flit_offset] = current_flit[129]; //-- only 1 if tail |
|
if(current_flit[129]) begin |
pkts_in_cycle ++; |
end |
|
if(current_flit[128]) begin |
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 |
|
//-- insert empty flits between packets |
|
|
flit_offset++; |
end |
end |
//-- push last axi4_item to axi4_queue |
axi4_queue.push_back(axi4_item); |
|
endfunction : hmc_packet_2_axi_cycles |
|
task body(); |
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES),.TUSER_WIDTH(TUSER_WIDTH)) axi4_item; |
int working_pos = 0; |
|
`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 |
|
for (int i = working_pos; i < hmc_items.size(); i++) begin //-- get a tag for each packet |
//-- only register an 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.try_get_tag(tag); |
`uvm_info(get_type_name(),$psprintf("Tag for HMC Packet %0d is: %0d", i, tag), UVM_MEDIUM) |
end else begin |
tag = 0; |
// void'(randomize(tag)); //-- can be used to randomize the tag |
`uvm_info(get_type_name(),$psprintf("Tag for HMC Packet Type %0d is: %0d", hmc_items[i].get_command_type(), tag), UVM_HIGH) |
end |
if (tag >= 0) begin |
hmc_items[i].tag = tag; |
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 |
|
|
if (hmc_packets_ready.size()>0) begin |
|
//-- generate axi4_queue |
hmc_packet_2_axi_cycles(); |
|
//-- send axi4_queue |
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(); |
`uvm_send(axi4_item); |
|
`uvm_info(get_type_name(),$psprintf("\n%s", axi4_item.sprint()), UVM_HIGH) |
end |
end |
end |
endtask : body |
|
endclass : hmc_2_axi4_sequence |
|
`endif // HMC_2_AXI4_SEQUENCE_SV |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/hmc_req_packet.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/>. |
* |
* |
*/ |
|
// |
// 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 c_req_command { command >= HMC_WRITE_16 && command <= HMC_READ_128; } |
// constraint c_req_command_fix {command >= HMC_POSTED_WRITE_64 && command <= HMC_POSTED_WRITE_64;} |
// constraint c_req_command_fix {command >= HMC_WRITE_16 && command <= HMC_WRITE_128;} |
constraint c_req_command_fix { |
(command >= HMC_WRITE_16 && command <= HMC_WRITE_128) |
|| |
(command >= HMC_POSTED_WRITE_16 && command <= HMC_POSTED_WRITE_128) |
|| |
(command >= HMC_READ_16 && command <= 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 |
|
/openhmc/trunk/openHMC/sim/tb/bfm/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 |
|
/openhmc/trunk/openHMC/sim/tb/bfm/src/hmc_vseqr.sv
0,0 → 1,60
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 hmc_vseqr extends uvm_sequencer; |
|
// hmc_link_config link_config; |
|
//-- references to testbench sequencers |
cag_rgm_sequencer rf_seqr_hmc; |
|
hmc_2_axi4_sequencer #(.DATA_BYTES(`AXI4BYTES),.TUSER_WIDTH(`AXI4BYTES)) axi4_req_seqr; |
|
`uvm_component_utils(hmc_vseqr) |
|
function new (string name = "hmc_virtual_sequencer", uvm_component parent); |
super.new(name, parent); |
endfunction : new |
|
endclass : hmc_vseqr |
|
`endif // hmc_VIRTUAL_SEQUENCER_SV |
/openhmc/trunk/openHMC/sim/tb/run/clean_up.sh
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/>. |
# |
# |
|
#!/bin/bash |
rm -rf waves.shm |
rm -rf INCA_libs |
rm -rf cov_work |
rm -f *.log |
rm -f irun.key |
rm -rf .simvision |
/openhmc/trunk/openHMC/sim/tb/run/run_files/run.sh
0,0 → 1,192
# |
# .--------------. .----------------. .------------. |
# | .------------. | .--------------. | .----------. | |
# | | ____ ____ | | | ____ ____ | | | ______ | | |
# | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
# ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
# / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
# (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
# \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
# | | | | | | | | | | | | |
# |_| | '------------' | '--------------' | '----------' | |
# '--------------' '----------------' '------------' |
# |
# 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 |
|
function print_help { |
printf "Usage: %s: [-c] [-d DUT] [-f FPW] [-g] [-l NUM_LANES] [-p] [-s SEED] -t TEST_NAME\n [-v UVM_VERBOSITY] -?" $(basename $0) >&2 |
} |
|
#----------------------------------------------------------------- |
# set defaults |
if [ ! $CAG_DUT ] |
then |
CAG_DUT="default" |
fi |
|
#-- Controller params |
num_lanes="default" |
log_num_lanes="3" |
fpw="default" |
log_fpw="2" |
|
do_clean_up= |
tflag="0" |
dflag="0" |
test_name= |
verbosity="UVM_LOW" |
use_gui= |
coverage="" |
input_file="-input ${CAG_TB_DIR}/build/ncsim.tcl" |
seed="" |
num_pkt="default" |
num_axi_bytes="64" |
|
#-- parse options |
while getopts 'cgt:v:d:s:l:f:p:' OPTION |
do |
case $OPTION in |
c) do_clean_up=1 |
;; |
d) export CAG_DUT=${OPTARG} |
dflag="1" |
;; |
f) fpw="${OPTARG}" |
;; |
g) use_gui="+gui" |
;; |
l) num_lanes="${OPTARG}" |
;; |
p) num_pkt="${OPTARG}" |
;; |
s) seed="+svseed+${OPTARG}" |
;; |
t) tflag="1" |
test_name="$OPTARG" |
;; |
v) verbosity="$OPTARG" |
;; |
?) print_help |
exit 2 |
;; |
esac |
done |
shift $(($OPTIND - 1)) |
|
printf "****************************************************\n" |
printf "****************************************************\n" |
|
#-- Set up controller |
if [ $num_lanes == "default" ] |
then |
printf "No link-width specified. Defaulting to 8 lanes \n" |
else |
if [ $num_lanes != "8" -a $num_lanes != "16" ] |
then |
printf "Unsupported link-width specified. Defaulting to 8 lanes\n" |
else |
if [ $num_lanes == "16" ] |
then |
log_num_lanes="4" |
export X16 |
fi |
printf "Link width set: $num_lanes lanes\n" |
fi |
fi |
|
if [ $fpw == "default" ] |
then |
printf "No FPW specified. Defaulting to FPW=4 (512bit datapath)\n" |
fpw="4" |
else |
if [ $fpw != "2" -a $fpw != "4" -a $fpw != "6" -a $fpw != "8" ] |
then |
printf "Unsupported FPW specified. Defaulting to FPW=4 (512bit datapath)\n" |
fpw="4" |
else |
printf "FPW set: $fpw\n" |
case $fpw in |
2) |
log_fpw="1" |
num_axi_bytes="32" |
;; |
4) |
log_fpw="2" |
;; |
6) |
log_fpw="3" |
num_axi_bytes="96" |
;; |
8) |
log_fpw="3" |
num_axi_bytes="128" |
;; |
esac |
fi |
fi |
|
#-- check test |
if [ "$tflag" == "0" ] |
then |
printf "Test defaulted to simple_test.\n" |
test_name="simple_test" |
fi |
|
#-- Set up the test |
if [ $num_pkt == "default" ] |
then |
num_pkt="100" |
fi |
printf "Sending $num_pkt packets. \n" |
|
#-- select DUT |
if [ "$dflag" == "0" ] |
then |
printf "DUT is default: ${CAG_DUT}\n" |
else |
echo "DUT used: ${CAG_DUT}" |
fi |
CAG_TB_COMPILE_IUS="${CAG_TB_DIR}/build/compile_ius_${CAG_DUT}.f" |
|
printf "****************************************************\n" |
printf "****************************************************\n" |
|
#-- do some clean up |
if [ "$do_clean_up" ] |
then |
echo "Removing old build files..." |
${CAG_TB_DIR}/../run/clean_up.sh |
fi |
|
#-- all other stuff |
echo "Starting the verification environment..." |
irun ${input_file} \ |
-f ${CAG_TB_COMPILE_IUS} \ |
-access +rwc \ |
${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 NUM_PACKETS=$num_pkt -define AXI4BYTES=$num_axi_bytes" $* |
/openhmc/trunk/openHMC/sim/tb/run/run.sh
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/>. |
# |
# |
|
#!/bin/bash |
|
if [ ! $OPENHMC_SIM ] |
then |
echo "Please export the OPENHMC_SIM 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 "* * *" |
echo "* * *" |
echo "* *******************************************************" |
echo "" |
|
${OPENHMC_SIM}/tb/run/run_files/run.sh $* |
|
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_base.sv
0,0 → 1,156
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_base extends uvm_object; |
|
protected CAG_RGM_TYPE m_type = NONE; |
protected bit [63:0] address; |
protected bit [63:0] offset; |
protected int loop = -1; |
protected string name; |
protected bit check_on_read = 1; |
|
`uvm_object_utils_begin(cag_rgm_base) |
`uvm_field_int(address, UVM_NOCOMPARE | UVM_NOPACK | UVM_DEFAULT) |
`uvm_field_int(offset, UVM_NOCOMPARE | UVM_NOPACK | UVM_DEFAULT) |
`uvm_field_int(check_on_read, UVM_NOCOMPARE | UVM_NOPACK | UVM_DEFAULT) |
`uvm_field_string(name, UVM_NOCOMPARE | UVM_NOPACK | UVM_DEFAULT) |
`uvm_object_utils_end |
|
function new(string name="cag_rgm_base"); |
super.new(name); |
endfunction : new |
|
function CAG_RGM_TYPE get_rgm_type(); |
return m_type; |
endfunction : get_rgm_type |
|
function string get_name(); |
return name; |
endfunction : get_name |
|
function void set_name(string name); |
this.name = name; |
endfunction : set_name |
|
virtual function void set_address(bit [63:0] address); |
this.address = address; |
endfunction : set_address |
|
virtual function bit [63:0] get_address(); |
return address + offset; |
endfunction : get_address |
|
virtual function int address_match(bit [63:0] address); |
if(get_address() == address) |
return 1; |
else |
return -1; |
endfunction : address_match |
|
function void set_offset(bit [63:0] offset); |
this.offset = offset; |
endfunction : set_offset |
|
function bit [63:0] get_offset(); |
return offset; |
endfunction : get_offset |
|
virtual function void set_loop(int loop); |
this.loop = loop; |
endfunction : set_loop |
|
function int get_loop(); |
return loop; |
endfunction : get_loop |
|
function void set_check_on_read(bit check_on_read); |
this.check_on_read = check_on_read; |
endfunction : set_check_on_read |
|
function bit get_check_on_read(); |
return this.check_on_read; |
endfunction : get_check_on_read |
|
function void set_raw(bit [63:0] data, bit endian = 1); |
bit bitstream[]; |
int bits; |
|
bits = pack(bitstream); |
if (endian == 1) begin |
for(int i = 0, int j = bits-1; i < bits; i++, j--) |
bitstream[i] = data[j]; |
end else begin |
for(int i = 0; i < bits; i++) |
bitstream[i] = data[i]; |
end |
bits = unpack(bitstream); |
|
endfunction : set_raw |
|
function bit [63:0] get_raw(bit endian = 1); |
uvm_packer packer = new(); |
int bits; |
bit bitstream[]; |
bit [63:0] data = 0; |
|
packer.big_endian = endian; |
|
bits = pack(bitstream,packer); |
for(int i = 0; i < bits; i++) |
data[i] = bitstream[i]; |
|
return data; |
endfunction |
|
virtual function void print_rf(string prefix = ""); |
$display(do_print_rf($psprintf("%stype: %s, name: %s, address: %0h, offset: %0h",prefix,m_type.name,name,address,offset))); |
endfunction : print_rf |
|
virtual function string do_print_rf(string s = ""); |
return s; |
endfunction : do_print_rf |
|
endclass : cag_rgm_base |
|
/****************************************************************************** |
* |
* REVISION HISTORY: |
* |
*******************************************************************************/ |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_pkg.sv
0,0 → 1,49
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 CAG_RGM_PKG_SV |
`define CAG_RGM_PKG_SV |
|
package cag_rgm; |
|
`include "cag_rgm.svh" |
|
endpackage : cag_rgm |
|
`endif // CAG_RGM_PKG_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_container.sv
0,0 → 1,137
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_container extends cag_rgm_base; |
|
protected cag_rgm_base m_registers[$]; |
protected cag_rgm_base m_ramblocks[$]; |
|
`uvm_object_utils(cag_rgm_container) |
|
function new(string name = "cag_rgm_container"); |
super.new(name); |
this.name = name; |
this.m_type = CONTAINER; |
endfunction : new |
|
function void add_register(cag_rgm_register register, bit set_address = 0); |
if(set_address) |
register.set_address(address); |
m_registers.push_back(register); |
endfunction : add_register |
|
function void add_ramblock(cag_rgm_base ramblock, bit set_address = 0); |
if(set_address) |
ramblock.set_address(address); |
m_ramblocks.push_back(ramblock); |
endfunction : add_ramblock |
|
virtual function void set_address(bit [63:0] address); |
super.set_address(address); |
|
foreach(m_registers[i]) |
m_registers[i].set_address(address); |
|
foreach(m_ramblocks[i]) |
m_ramblocks[i].set_address(address); |
|
endfunction : set_address |
|
virtual function void set_loop(int loop); |
super.set_loop(loop); |
|
foreach(m_registers[i]) |
m_registers[i].set_loop(loop); |
|
foreach(m_ramblocks[i]) |
m_ramblocks[i].set_loop(loop); |
|
endfunction : set_loop |
|
virtual function cag_rgm_base get_by_name(string full_name = ""); |
|
foreach(m_registers[i]) begin |
if(m_registers[i].get_name() == full_name) begin |
return m_registers[i]; |
end |
end |
foreach(m_ramblocks[i]) begin |
if(m_ramblocks[i].get_name() == full_name) begin |
return m_ramblocks[i]; |
end |
end |
|
return null; |
endfunction : get_by_name |
|
virtual function cag_rgm_base get_by_address(bit [63:0] address); |
foreach(m_registers[i]) begin |
if(m_registers[i].address_match(address) != -1) begin |
return m_registers[i]; |
end |
end |
foreach(m_ramblocks[i]) begin |
if(m_ramblocks[i].address_match(address) != -1) begin |
return m_ramblocks[i]; |
end |
end |
|
return null; |
endfunction : get_by_address |
|
virtual function void print_rf(string prefix = ""); |
super.print_rf(prefix); |
|
foreach (m_registers[i]) begin |
m_registers[i].print_rf({prefix," "}); |
end |
|
foreach (m_ramblocks[i]) begin |
m_ramblocks[i].print_rf({prefix," "}); |
end |
|
endfunction : print_rf |
|
endclass : cag_rgm_container |
|
/****************************************************************************** |
* |
* REVISION HISTORY: |
* |
*******************************************************************************/ |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_register_file.sv
0,0 → 1,145
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_register_file extends cag_rgm_container; |
|
protected cag_rgm_register_file m_register_files[$]; |
protected cag_rgm_repeat_block m_repeat_blocks[$]; |
|
`uvm_object_utils(cag_rgm_register_file) |
|
function new(string name="cag_rgm_register_file"); |
super.new(name); |
this.name = name; |
this.m_type = REGISTER_FILE; |
endfunction : new |
|
function void add_register_file(cag_rgm_register_file register_file); |
m_register_files.push_back(register_file); |
endfunction : add_register_file |
|
function void add_repeat_block(cag_rgm_repeat_block repeat_block); |
m_repeat_blocks.push_back(repeat_block); |
endfunction : add_repeat_block |
|
function cag_rgm_base get_by_name(string full_name = ""); |
bit check_registers = 1; |
cag_rgm_base base; |
cag_rgm_register_file m_reg_file; |
cag_rgm_repeat_block m_repeat; |
string name; |
|
for( int i = 0; i < full_name.len(); i++) begin |
if(full_name.getc(i) == ".") begin |
name = full_name.substr(0, i-1); |
full_name = full_name.substr(i + 1, full_name.len()-1); |
check_registers = 0; |
break; |
end |
end |
|
if(check_registers) begin |
base = super.get_by_name(full_name); |
if(base != null) |
return base; |
|
foreach(m_repeat_blocks[i]) begin |
if(m_repeat_blocks[i].get_name() == full_name) begin |
return m_repeat_blocks[i]; |
end |
end |
end else begin |
foreach(m_register_files[i]) begin |
if(m_register_files[i].get_name() == name) begin |
$cast(m_reg_file,m_register_files[i]); |
return m_reg_file.get_by_name(full_name); |
end |
end |
foreach(m_repeat_blocks[i]) begin |
if(m_repeat_blocks[i].get_name() == name) begin |
$cast(m_repeat,m_repeat_blocks[i]); |
return m_repeat_blocks[i].get_by_name(full_name); |
end |
end |
end |
|
return null; |
|
endfunction : get_by_name |
|
virtual function cag_rgm_base get_by_address(bit [63:0] address); |
// check registers and ram blocks |
get_by_address = super.get_by_address(address); |
if(get_by_address != null) |
return get_by_address; |
|
// check sub registerfiles |
foreach(m_register_files[i]) begin |
get_by_address = m_register_files[i].get_by_address(address); |
if(get_by_address != null) |
return get_by_address; |
end |
|
// check repeat blocks |
foreach(m_repeat_blocks[i]) begin |
get_by_address = m_repeat_blocks[i].get_by_address(address); |
if(get_by_address != null) |
return get_by_address; |
end |
|
return null; |
endfunction : get_by_address |
|
virtual function void print_rf(string prefix = ""); |
super.print_rf(prefix); |
|
foreach(m_register_files[i]) |
m_register_files[i].print_rf({prefix," "}); |
|
foreach(m_repeat_blocks[i]) |
m_repeat_blocks[i].print_rf({prefix," "}); |
endfunction : print_rf |
|
endclass : cag_rgm_register_file |
|
/****************************************************************************** |
* |
* REVISION HISTORY: |
* |
*******************************************************************************/ |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_transfer.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/>. |
* |
* |
*/ |
|
class cag_rgm_transfer extends uvm_sequence_item; |
|
CAG_RGM_TRANSFER_COMMAND command; |
bit [63:0] address; |
bit [63:0] data; |
int unsigned source_tag; |
rand int unsigned delay; |
bit error; |
|
`uvm_object_utils_begin(cag_rgm_transfer) |
`uvm_field_enum(CAG_RGM_TRANSFER_COMMAND, command, UVM_ALL_ON) |
`uvm_field_int(address, UVM_ALL_ON) |
`uvm_field_int(data, UVM_ALL_ON) |
`uvm_field_int(source_tag, UVM_ALL_ON) |
`uvm_field_int(delay, UVM_ALL_ON) |
`uvm_field_int(error, UVM_ALL_ON) |
`uvm_object_utils_end |
|
constraint c_delay { delay inside {[0:50]}; } |
|
function new(string name="cag_rgm_transfer"); |
super.new(name); |
endfunction : new |
|
endclass : cag_rgm_transfer |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_register.sv
0,0 → 1,52
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_register extends cag_rgm_base; |
|
//T fields; |
|
`uvm_object_utils(cag_rgm_register) |
|
function new(string name="cag_rgm_register"); |
super.new(name); |
this.name = name; |
this.m_type = REGISTER; |
endfunction : new |
|
endclass : cag_rgm_register |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_defines.svh
0,0 → 1,192
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
typedef enum { |
NONE, |
CONTAINER, |
REPEAT_BLOCK, |
REGISTER, |
RAM, |
REGISTER_FILE |
} CAG_RGM_TYPE; |
|
typedef enum { |
CAG_RGM_UNDEFINED, |
CAG_RGM_READ, |
CAG_RGM_WRITE, |
CAG_RGM_READ_RESPONSE, |
CAG_RGM_WRITE_RESPONSE |
} CAG_RGM_TRANSFER_COMMAND; |
|
typedef enum { |
SINGLE, |
ALL |
} CAG_RGM_MODE; |
|
`define cag_rgm_register_fields(T) \ |
rand T fields; |
|
`define cag_rgm_driver_utils_start \ |
task start_rf(); \ |
super.start_rf(); \ |
fork |
|
`define cag_rgm_driver_utils_end \ |
join \ |
endtask : start_rf |
|
`define cag_rgm_driver_field_reg_begin(TYPE,PATH,NAME) \ |
begin \ |
TYPE m_reg; \ |
$cast(m_reg,rf_model.get_by_name(PATH)); \ |
if( m_reg == null ) \ |
uvm_report_fatal(get_type_name(),{PATH," not found"});\ |
forever begin \ |
wait(!vif.res_n); \ |
vif.NAME <= {16{1'b0}}; \ |
@(posedge vif.res_n); \ |
fork \ |
@(negedge vif.res_n); \ |
begin \ |
forever begin \ |
@(posedge vif.clk); |
|
`define cag_rgm_driver_field_reg_no_reset_begin(TYPE,PATH) \ |
begin \ |
TYPE m_reg; \ |
$cast(m_reg,rf_model.get_by_name(PATH)); \ |
if( m_reg == null ) \ |
uvm_report_fatal(get_type_name(),{PATH," not found"});\ |
forever begin \ |
wait(!vif.res_n); \ |
@(posedge vif.res_n); \ |
fork \ |
@(negedge vif.res_n); \ |
begin \ |
forever begin \ |
@(posedge vif.clk); |
|
`define cag_rgm_driver_field_reg_end \ |
end \ |
end \ |
join_any \ |
disable fork; \ |
end \ |
end |
|
`define cag_rgm_driver_reg_ro(TYPE,PATH,NAME,FIELD) \ |
`cag_rgm_driver_field_reg_begin(TYPE,PATH,NAME) \ |
vif.NAME <= m_reg.fields.FIELD; \ |
`cag_rgm_driver_field_reg_end |
|
`define cag_rgm_driver_reg_wo(TYPE,PATH,NAME,FIELD) \ |
`cag_rgm_driver_field_reg_no_reset_begin(TYPE,PATH) \ |
m_reg.fields.FIELD = vif.NAME``_next; \ |
`cag_rgm_driver_field_reg_end |
|
`define cag_rgm_driver_reg_wo_en(TYPE,PATH,NAME,FIELD) \ |
`cag_rgm_driver_field_reg_begin(TYPE,PATH,NAME) \ |
if(vif.NAME``_wen) \ |
m_reg.fields.FIELD = vif.NAME; \ |
`cag_rgm_driver_field_reg_end |
|
`define cag_rgm_driver_reg_rw(TYPE,PATH,NAME,FIELD) \ |
`cag_rgm_driver_field_reg_begin(TYPE,PATH,NAME) \ |
vif.NAME <= m_reg.fields.FIELD; \ |
m_reg.fields.FIELD = vif.NAME; \ |
`cag_rgm_driver_field_reg_end |
|
`define cag_rgm_driver_reg_rw_en(TYPE,PATH,NAME,FIELD) \ |
`cag_rgm_driver_field_reg_begin(TYPE,PATH,NAME) \ |
vif.NAME <= m_reg.fields.FIELD; \ |
if(vif.NAME``_wen) \ |
m_reg.fields.FIELD = vif.NAME; \ |
`cag_rgm_driver_field_reg_end |
|
`define cag_rgm_driver_ram_int(TYPE,PATH,NAME,WIDTH) \ |
begin \ |
TYPE m_ram; \ |
bit [WIDTH-1:0] ram_address; \ |
bit enable = 0; \ |
$cast(m_ram,rf_model.get_by_name(PATH)); \ |
if( m_ram == null ) \ |
uvm_report_fatal(get_type_name(),{PATH," not found"}); \ |
forever begin \ |
enable = vif.NAME``_ren; \ |
if(enable) \ |
ram_address = vif.NAME``_rf_addr; \ |
@(posedge vif.clk); \ |
if(enable) \ |
vif.NAME``_rdata <= m_ram.get_entry(ram_address); \ |
->m_ram.write_done; \ |
end \ |
end |
|
`define cag_rgm_driver_ram_ext(TYPE,PATH,NAME) \ |
begin \ |
TYPE m_ram; \ |
int unsigned entry; \ |
$cast(m_ram,rf_model.get_by_name(PATH)); \ |
if( m_ram == null ) \ |
uvm_report_fatal(get_type_name(),{PATH," not found"}); \ |
vif.NAME``_rf_wen <= 1'b0; \ |
vif.NAME``_rf_ren <= 1'b0; \ |
forever begin \ |
@(m_ram.read_event or m_ram.write_event); \ |
@(posedge vif.clk); \ |
entry = m_ram.entry; \ |
vif.NAME``_rf_addr <= entry; \ |
if(m_ram.read_write) begin \ |
vif.NAME``_rf_wdata <= m_ram.get_entry(entry); \ |
vif.NAME``_rf_wen <= 1'b1; \ |
end else begin \ |
vif.NAME``_rf_ren <= 1'b1; \ |
end \ |
@(posedge vif.clk); \ |
vif.NAME``_rf_wen <= 1'b0; \ |
while(!vif.NAME``_rf_access_complete) \ |
@(posedge vif.clk); \ |
vif.NAME``_rf_wen <= 1'b0; \ |
vif.NAME``_rf_ren <= 1'b0; \ |
if(!m_ram.read_write) \ |
m_ram.set_entry(vif.NAME``_rf_rdata, entry ); \ |
->m_ram.write_done; \ |
end \ |
end |
|
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_monitor.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 CAG_RGM_MONITOR_SV |
`define CAG_RGM_MONITOR_SV |
|
class cag_rgm_monitor extends uvm_monitor; |
|
`uvm_component_utils(cag_rgm_monitor) |
|
uvm_analysis_port#(cag_rgm_transfer) collected_port; |
|
function new(string name="cag_rgm_monitor",uvm_component parent); |
super.new(name,parent); |
|
collected_port = new("collected_port",this); |
endfunction : new |
|
endclass : cag_rgm_monitor |
|
`endif // CAG_RGM_MONITOR_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm.svh
0,0 → 1,71
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 CAG_RGM_SVH |
`define CAG_RGM_SVH |
|
`include "uvm_macros.svh" |
import uvm_pkg::*; |
|
`include "cag_rgm_defines.svh" |
|
`include "cag_rgm_base.sv" |
|
`include "cag_rgm_register.sv" |
|
`include "cag_rgm_container.sv" |
`include "cag_rgm_repeat_block.sv" |
|
`include "cag_rgm_register_file.sv" |
|
`include "cag_rgm_transfer.sv" |
|
`include "cag_rgm_sequencer.sv" |
`include "cag_rgm_sequence.sv" |
|
`include "cag_rgm_driver.sv" |
|
`include "cag_rgm_rfs_driver.sv" |
`include "cag_rgm_rfs_monitor.sv" |
`include "cag_rgm_rfs_env.sv" |
|
`include "cag_rgm_monitor.sv" |
`include "cag_rgm_env.sv" |
|
`endif // CAG_RGM_SVH |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_env.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/>. |
* |
* |
*/ |
|
`ifndef CAG_RGM_ENV_SV |
`define CAG_RGM_ENV_SV |
|
class cag_rgm_env extends uvm_env; |
|
uvm_active_passive_enum is_active = UVM_ACTIVE; |
|
`uvm_component_utils_begin(cag_rgm_env) |
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT) |
`uvm_component_utils_end |
|
cag_rgm_sequencer sequencer; |
|
cag_rgm_monitor tx_monitor; |
cag_rgm_monitor rx_monitor; |
|
function new(string name="cag_rgm_env", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build(); |
super.build(); |
|
if(is_active == UVM_ACTIVE) |
sequencer = cag_rgm_sequencer::type_id::create("sequencer",this); |
|
tx_monitor = cag_rgm_monitor::type_id::create("tx_monitor",this); |
rx_monitor = cag_rgm_monitor::type_id::create("rx_monitor",this); |
|
endfunction : build |
|
function void connect(); |
if(is_active == UVM_ACTIVE) begin |
rx_monitor.collected_port.connect(sequencer.resp_port); |
end |
endfunction : connect |
|
function void set_rf(cag_rgm_register_file rf); |
if(is_active == UVM_ACTIVE) |
sequencer.set_rf(rf); |
endfunction : set_rf |
|
endclass : cag_rgm_env |
|
`endif // CAG_RGM_ENV_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_sequencer.sv
0,0 → 1,180
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
typedef class cag_rgm_write_sequence; |
typedef class cag_rgm_read_sequence; |
|
class cag_rgm_sequencer extends uvm_sequencer #(cag_rgm_transfer); |
|
`uvm_analysis_imp_decl(_resp) |
uvm_analysis_imp_resp #(cag_rgm_transfer,cag_rgm_sequencer) resp_port; |
|
int unsigned source_tag_count = 1; |
protected mailbox #(int unsigned) source_tags; |
|
protected cag_rgm_register_file m_rf; |
protected cag_rgm_write_sequence write_seq; |
protected cag_rgm_read_sequence read_seq; |
|
protected mailbox #(cag_rgm_transfer) responses_mb; |
cag_rgm_transfer responses_q[$]; |
semaphore responses_s; |
event new_rsp; |
|
//`uvm_sequencer_utils_begin(cag_rgm_sequencer) |
// `uvm_field_int(source_tag_count, UVM_ALL_ON) |
//`uvm_sequencer_utils_end |
`uvm_component_utils_begin(cag_rgm_sequencer) |
`uvm_field_int(source_tag_count, UVM_ALL_ON) |
`uvm_component_utils_end |
|
function new(string name = "cag_rgm_sequencer",uvm_component parent); |
super.new(name,parent); |
//count = 0; |
//`uvm_update_sequence_lib |
|
resp_port = new("resp_port",this); |
responses_mb = new(); |
responses_s = new(1); |
source_tags = new(); |
endfunction : new |
|
function void build(); |
super.build(); |
|
for(int unsigned i = 0; i < source_tag_count; i++) |
void'(source_tags.try_put(i)); |
endfunction : build |
|
task run(); |
cag_rgm_transfer response; |
|
forever begin |
responses_mb.get(response); |
//uvm_report_info("DEBUG",$psprintf("received rsp with tag %0d",response.source_tag),UVM_NONE); |
//$stop; |
responses_s.get(1); |
responses_q.push_back(response); |
->new_rsp; |
responses_s.put(1); |
//$stop; |
end |
endtask : run |
|
function void set_rf(cag_rgm_register_file rf); |
this.m_rf = rf; |
endfunction : set_rf |
|
function void write_resp(input cag_rgm_transfer transfer); |
if(transfer.command == CAG_RGM_READ_RESPONSE) |
assert(responses_mb.try_put(transfer)); |
endfunction : write_resp |
|
task get_response(int unsigned source_tag, ref cag_rgm_transfer rsp); |
|
//responses.get(rsp); |
//if(rsp.source_tag != source_tag) |
// p_sequencer.uvm_report_fatal(get_type_name(),$psprintf("got the wrong source tag: %h",rsp.source_tag)); |
forever begin |
responses_s.get(1); |
while(responses_q.size() == 0) begin |
responses_s.put(1); |
//$stop; |
@new_rsp; |
//$stop; |
responses_s.get(1); |
end |
|
foreach(responses_q[i]) begin |
//uvm_report_info("DEBUG",$psprintf("foreach tag: %0d",responses_q[i].source_tag),UVM_NONE); |
if(responses_q[i].source_tag == source_tag) begin |
rsp = responses_q[i]; |
responses_q.delete(i); |
responses_s.put(1); |
//$stop; |
return; |
end |
end |
|
responses_s.put(1); |
//$stop; |
@new_rsp; |
end |
|
endtask : get_response |
|
task m_get_source_tag(output int unsigned tag); |
source_tags.get(tag); |
endtask : m_get_source_tag |
|
task m_release_source_tag(int unsigned tag); |
source_tags.put(tag); |
endtask : m_release_source_tag |
|
// |
// rf access functions |
// |
function cag_rgm_base get_by_name(string name = ""); |
return m_rf.get_by_name(name); |
endfunction : get_by_name |
|
function cag_rgm_base get_by_address(bit [63:0] address); |
return m_rf.get_by_address(address); |
endfunction : get_by_address |
|
task write_reg(cag_rgm_base reg_); |
write_seq = cag_rgm_write_sequence::type_id::create("write_seq"); |
write_seq.req_ = reg_; |
write_seq.start(this); |
endtask : write_reg |
|
task read_reg(cag_rgm_base reg_); |
read_seq = cag_rgm_read_sequence::type_id::create("read_seq"); |
read_seq.req_ = reg_; |
read_seq.start(this); |
endtask : read_reg |
|
endclass : cag_rgm_sequencer |
|
/****************************************************************************** |
* |
* REVISION HISTORY: |
* |
*******************************************************************************/ |
|
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_repeat_block.sv
0,0 → 1,117
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_repeat_block extends cag_rgm_container;//cag_rgm_base; |
|
protected int unsigned loop; |
protected bit [63:0] iter_size; |
protected cag_rgm_container containers[$]; |
|
`uvm_object_utils(cag_rgm_repeat_block) |
|
function new(string name = "cag_rgm_repeat_block"); |
super.new(name); |
this.name = name; |
this.m_type = REPEAT_BLOCK; |
endfunction : new |
|
function void add_container(cag_rgm_container container); |
container.set_address(address + (loop*iter_size)); |
container.set_loop(loop); |
this.containers.push_back(container); |
loop++; |
endfunction : add_container |
|
function void set_iter_size(bit [63:0] iter_size); |
this.iter_size = iter_size; |
endfunction : set_iter_size |
|
virtual function string do_print_rf(string s = ""); |
return {s,$psprintf(", loops: %0d, iter_size: %0h",loop,iter_size)}; |
endfunction : do_print_rf |
|
virtual function void print_rf(string prefix=""); |
super.print_rf(prefix); |
|
foreach(containers[i]) |
containers[i].print_rf({prefix," "}); |
endfunction : print_rf |
|
virtual function cag_rgm_base get_by_name(string full_name = ""); |
bit check_registers = 1; |
|
string name; |
|
for( int i = 0; i < full_name.len(); i++) begin |
if(full_name.getc(i) == ".") begin |
name = full_name.substr(0, i-1); |
full_name = full_name.substr(i + 1, full_name.len()-1); |
check_registers = 0; |
break; |
end |
end |
|
if(check_registers) begin |
foreach(containers[i]) begin |
if(containers[i].get_name() == full_name) begin |
return containers[i]; |
end |
end |
end else begin |
foreach(containers[i]) begin |
if(containers[i].get_name() == name) begin |
return containers[i].get_by_name(full_name); |
end |
end |
end |
|
return null; |
|
endfunction : get_by_name |
|
virtual function cag_rgm_base get_by_address(bit [63:0] address); |
foreach(containers[i]) begin |
get_by_address = containers[i].get_by_address(address); |
if( get_by_address != null) |
return get_by_address; |
end |
return null; |
endfunction : get_by_address |
|
endclass : cag_rgm_repeat_block |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_driver.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/>. |
* |
* |
*/ |
|
class cag_rgm_driver extends uvm_component; |
|
protected cag_rgm_register_file rf_model; |
|
`uvm_component_utils(cag_rgm_driver) |
|
function new(string name="cag_rgm_driver", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void set_model(cag_rgm_register_file model); |
this.rf_model = model; |
endfunction : set_model |
|
virtual task start_rf(); |
|
endtask : start_rf |
|
virtual task run(); |
if(rf_model == null) |
uvm_report_fatal(get_type_name(),"Register model not set."); |
start_rf(); |
endtask : run |
|
endclass : cag_rgm_driver |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_rfs_monitor.sv
0,0 → 1,217
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
// |
// |
// cag rgm rfs monitor OVC monitor |
// |
// |
|
`ifndef CAG_RGM_RFS_MONITOR_SV |
`define CAG_RGM_RFS_MONITOR_SV |
|
class cag_rgm_rfs_monitor #( |
parameter ADDR_WIDTH = 6, |
parameter READ_DATA_WIDTH = 64, |
parameter WRITE_DATA_WIDTH = 64 |
) extends uvm_monitor; |
|
uvm_analysis_port #(cag_rgm_transfer) request_port; |
uvm_analysis_port #(cag_rgm_transfer) response_port; |
|
virtual cag_rgm_rfs_if #( |
.ADDR_WIDTH(ADDR_WIDTH), |
.READ_DATA_WIDTH(READ_DATA_WIDTH), |
.WRITE_DATA_WIDTH(WRITE_DATA_WIDTH) |
) rfs_if; |
|
cag_rgm_transfer collected_request; |
cag_rgm_transfer collected_response; |
|
bit enable_coverage = 1; |
bit enable_checks = 1; |
|
int cycles_between_req = 0; |
int cycles_between_resp = 0; |
|
`uvm_component_param_utils_begin(cag_rgm_rfs_monitor #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH))) |
`uvm_field_int(enable_coverage, UVM_ALL_ON) |
`uvm_field_int(enable_checks, UVM_ALL_ON) |
`uvm_component_utils_end |
|
function new ( string name="cag_rgm_rfs_monitor", uvm_component parent ); |
super.new(name, parent); |
request_port = new("request_port", this); |
response_port = new("response_port", this); |
endfunction : new |
|
|
function void assign_vi( virtual interface cag_rgm_rfs_if #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH)) rfs_if ); |
this.rfs_if = rfs_if; |
endfunction : assign_vi |
|
|
task run(); |
#1; |
do_reset(); |
fork |
collect_request_transfers(); |
collect_response_transfers(); |
join_none |
endtask : run |
|
|
task do_reset(); |
while (rfs_if.res_n == 0) |
@( posedge rfs_if.clk ); |
endtask : do_reset |
|
|
task collect_request_transfers(); |
|
forever |
begin |
cycles_between_req = 0; |
|
// wait for write or read enable |
while (!(rfs_if.wen || rfs_if.ren)) begin |
cycles_between_req++; |
@(posedge rfs_if.clk); |
end |
|
collected_request = cag_rgm_transfer::type_id::create("collected_request", this); |
if(recording_detail == UVM_FULL) |
collected_request.enable_recording({get_full_name(),"_request"}); |
void'(collected_request.begin_tr()); |
|
if (rfs_if.ren) |
collected_request.command = CAG_RGM_READ; |
else |
collected_request.command = CAG_RGM_WRITE; |
|
collected_request.address = {{64-3-ADDR_WIDTH {1'b0}}, rfs_if.address,3'b0}; |
collected_request.data = rfs_if.write_data; |
collected_request.delay = cycles_between_req; |
collected_request.error = 1'b0; |
|
@(posedge rfs_if.clk); |
|
if (enable_checks) |
perform_request_checks(); |
if (enable_coverage) |
perform_request_coverage(); |
|
void'(collected_request.end_tr()); |
// forward the collected_request to the next higher layer of the verification environment |
// collected_request.print(); |
request_port.write(collected_request); |
end |
endtask : collect_request_transfers |
|
|
task collect_response_transfers(); |
|
forever begin |
cycles_between_resp = 0; |
|
while (!(rfs_if.wen || rfs_if.ren)) begin |
@(posedge rfs_if.clk); |
end |
|
collected_response = cag_rgm_transfer::type_id::create("collected_response", this); |
|
if(rfs_if.wen) |
collected_response.command = CAG_RGM_WRITE_RESPONSE; |
else |
collected_response.command = CAG_RGM_READ_RESPONSE; |
|
// wait for write or read enable |
while (!rfs_if.access_done) begin |
cycles_between_resp++; |
@(posedge rfs_if.clk); |
end |
|
if(recording_detail == UVM_FULL) |
collected_response.enable_recording({get_full_name(),"_response"}); |
void'(collected_response.begin_tr()); |
|
collected_response.address = {{64-ADDR_WIDTH {1'b0}}, rfs_if.address}; //-- FIXME? address should be byte aligned? not qw? |
collected_response.data = rfs_if.read_data; |
collected_response.delay = cycles_between_req; |
collected_response.error = rfs_if.invalid_address; |
|
@(posedge rfs_if.clk); |
|
if (enable_checks) |
perform_response_checks(); |
if (enable_coverage) |
perform_response_coverage(); |
|
void'(collected_response.end_tr()); |
// forward the collected_response to the next higher layer of the verification environment |
// collected_response.print(); |
response_port.write(collected_response); |
end |
endtask : collect_response_transfers |
|
|
// checks |
function void perform_request_checks(); |
// perform data checks on collected_packet |
endfunction : perform_request_checks |
|
function void perform_response_checks(); |
//-- perform data checks on collected_packet |
if(collected_response.error) |
uvm_report_fatal(get_type_name(),$psprintf("Invalid access to address 0x%0h",collected_response.address)); |
endfunction : perform_response_checks |
|
|
// coverage |
function void perform_request_coverage(); |
// perform coverage on collected_packet |
endfunction : perform_request_coverage |
|
function void perform_response_coverage(); |
// perform coverage on collected_packet |
endfunction : perform_response_coverage |
|
endclass : cag_rgm_rfs_monitor |
|
`endif // CAG_RGM_RFS_MONITOR_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_rfs_env.sv
0,0 → 1,99
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 CAG_RGM_RFS_ENV_SV |
`define CAG_RGM_RFS_ENV_SV |
|
class cag_rgm_rfs_env #( |
parameter ADDR_WIDTH = 6, |
parameter WRITE_DATA_WIDTH = 64, |
parameter READ_DATA_WIDTH = 64 |
) extends uvm_env; |
|
uvm_active_passive_enum is_active = UVM_ACTIVE; |
|
cag_rgm_rfs_driver #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH)) driver; |
cag_rgm_rfs_monitor #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH)) monitor; |
|
cag_rgm_sequencer sequencer; |
|
`uvm_component_param_utils_begin(cag_rgm_rfs_env #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH))) |
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_ALL_ON) |
`uvm_component_utils_end |
|
function new(string name="cag_rgm_rfs_env", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build(); |
super.build(); |
|
monitor = cag_rgm_rfs_monitor #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH))::type_id::create("monitor",this); |
|
if(is_active == UVM_ACTIVE) begin |
driver = cag_rgm_rfs_driver #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH))::type_id::create("driver",this); |
|
sequencer = cag_rgm_sequencer::type_id::create("sequencer",this); |
end |
|
endfunction : build |
|
function void connect(); |
super.connect(); |
|
if(is_active == UVM_ACTIVE) begin |
driver.seq_item_port.connect(sequencer.seq_item_export); |
monitor.response_port.connect(sequencer.resp_port); |
end |
endfunction : connect |
|
function void assign_vi( virtual interface cag_rgm_rfs_if #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH)) vif); |
monitor.assign_vi(vif); |
if(is_active == UVM_ACTIVE) |
driver.assign_vi(vif); |
endfunction : assign_vi |
|
function void set_rf(cag_rgm_register_file rf); |
if(is_active == UVM_ACTIVE) |
sequencer.set_rf(rf); |
endfunction : set_rf |
|
endclass : cag_rgm_rfs_env |
|
`endif // CAG_RGM_RFS_ENV_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_rfs_driver.sv
0,0 → 1,136
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
// |
// |
// cag rgm rfs driver |
// |
// |
|
`ifndef CAG_RGM_RFS_DRIVER_SV |
`define CAG_RGM_RFS_DRIVER_SV |
|
class cag_rgm_rfs_driver #( |
parameter ADDR_WIDTH = 6, |
parameter READ_DATA_WIDTH = 64, |
parameter WRITE_DATA_WIDTH = 64 |
) extends uvm_driver #(cag_rgm_transfer); |
|
virtual cag_rgm_rfs_if #( |
.ADDR_WIDTH(ADDR_WIDTH), |
.READ_DATA_WIDTH(READ_DATA_WIDTH), |
.WRITE_DATA_WIDTH(WRITE_DATA_WIDTH) |
) rfs_if; |
|
cag_rgm_transfer rgm_item; |
|
`uvm_component_param_utils(cag_rgm_rfs_driver #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH))) |
|
function new (string name="cag_rgm_rfs_driver", uvm_component parent); |
super.new(name, parent); |
endfunction : new |
|
function void build(); |
super.build(); |
endfunction : build |
|
function void assign_vi(virtual interface cag_rgm_rfs_if #(.ADDR_WIDTH(ADDR_WIDTH), .READ_DATA_WIDTH(READ_DATA_WIDTH), .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH)) rfs_if); |
this.rfs_if = rfs_if; |
endfunction : assign_vi |
|
task do_reset(); |
rfs_if.address <= {ADDR_WIDTH {1'b0}}; |
rfs_if.wen <= 1'b0; |
rfs_if.ren <= 1'b0; |
rfs_if.write_data <= {WRITE_DATA_WIDTH {1'b0}}; |
|
while (rfs_if.res_n == 0) |
@( posedge rfs_if.clk ); |
|
endtask : do_reset |
|
task run(); |
#1; |
do_reset(); |
|
forever |
begin |
if (rfs_if.res_n == 0) |
do_reset(); |
|
seq_item_port.get_next_item(rgm_item); |
drive_item(); |
seq_item_port.item_done(); |
end |
endtask : run |
|
|
task drive_item(); |
|
//uvm_report_info(get_type_name(), $psprintf("start sending rgm_item:\n%s",rgm_item.sprint())); |
// Start sending: |
@(posedge rfs_if.clk); |
|
// Wait until start delay is over |
repeat (rgm_item.delay) |
@(posedge rfs_if.clk); |
|
// start request |
rfs_if.address <= rgm_item.address[3+(ADDR_WIDTH-1):3]; |
rfs_if.write_data <= rgm_item.data; |
rfs_if.wen <= (rgm_item.command == CAG_RGM_WRITE); |
rfs_if.ren <= (rgm_item.command == CAG_RGM_READ); |
|
@(posedge rfs_if.clk); |
rfs_if.wen <= 1'b0; |
rfs_if.ren <= 1'b0; |
|
while (rfs_if.access_done == 0) |
@(posedge rfs_if.clk); |
|
@(posedge rfs_if.clk); |
// end request |
rfs_if.address <= {ADDR_WIDTH {1'b0}}; |
rfs_if.write_data <= {WRITE_DATA_WIDTH {1'b0}}; |
|
endtask : drive_item |
|
endclass : cag_rgm_rfs_driver |
|
`endif // CAG_RGM_RFS_DRIVER_SV |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_sequence.sv
0,0 → 1,197
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 cag_rgm_sequence extends uvm_sequence #(cag_rgm_transfer); |
|
//`uvm_sequence_utils(cag_rgm_sequence, cag_rgm_sequencer) |
`uvm_object_utils(cag_rgm_sequence) |
`uvm_declare_p_sequencer(cag_rgm_sequencer) |
|
function new(string name="cag_rgm_sequence"); |
super.new(name); |
endfunction : new |
|
virtual task pre_body(); |
uvm_test_done.raise_objection(p_sequencer); |
endtask : pre_body |
|
virtual task post_body(); |
uvm_test_done.drop_objection(p_sequencer); |
endtask : post_body |
|
function cag_rgm_base get_by_name(string name = ""); |
return p_sequencer.get_by_name(name); |
endfunction : get_by_name |
|
task write_reg(cag_rgm_base reg_); |
bit bitstream[]; |
int bits; |
cag_rgm_transfer trans; |
|
uvm_packer packer = new(); |
packer.big_endian = 0; |
|
bits = reg_.pack(bitstream,packer); |
//reg_.print(); |
|
`uvm_create(trans) |
trans.command = CAG_RGM_WRITE; |
trans.address = reg_.get_address(); |
trans.data = 64'd0; |
//for(int i = 0 , int j = bits-1; i < bits; i++ ,j--) |
// trans.data[i] = bitstream[j]; |
|
for(int i = 0; i < bits; i++) |
trans.data[i] = bitstream[i]; |
//$display("%b",trans.data); |
|
//uvm_report_info("DEBUG",$psprintf("write; address: %h, data: %h",trans.address,trans.data),UVM_NONE); |
|
`uvm_send(trans) |
//uvm_report_info("DEBUG",$psprintf("write; address: %h, data: %h done",trans.address,trans.data),UVM_NONE); |
endtask : write_reg |
|
task read_reg(cag_rgm_base reg_); |
int unsigned source_tag; |
bit bitstream[]; |
int bits; |
cag_rgm_transfer trans; |
cag_rgm_transfer response; |
|
uvm_packer packer = new(); |
packer.big_endian = 0; |
|
p_sequencer.m_get_source_tag(source_tag); |
//uvm_report_info("DEBUG",$psprintf("using tag: %0d",source_tag),UVM_NONE); |
|
bits = reg_.pack(bitstream,packer); |
|
`uvm_create(trans) |
trans.command = CAG_RGM_READ; |
trans.address = reg_.get_address(); |
trans.source_tag = source_tag; |
//uvm_report_info("DEBUG",$psprintf("read; address: %h, data: %h",trans.address,trans.data),UVM_NONE); |
`uvm_send(trans) |
|
//-- wait for response |
//p_sequencer.responses.get(response); |
//if(response.source_tag != source_tag) |
// p_sequencer.uvm_report_fatal(get_type_name(),$psprintf("got the wrong source tag: %h",response.source_tag)); |
p_sequencer.get_response(source_tag, response); |
|
for(int i = 0 /*, int j = bits-1*/; i < bits; i++ /*, j--*/) |
bitstream[i] = response.data[i]; |
|
bits = reg_.unpack(bitstream,packer); |
|
p_sequencer.m_release_source_tag(source_tag); |
//uvm_report_info("DEBUG",$psprintf("read; address: %h, data: %h done",response.address,response.data),UVM_NONE); |
endtask : read_reg |
|
endclass : cag_rgm_sequence |
|
class cag_rgm_write_sequence extends cag_rgm_sequence; |
|
rand cag_rgm_base req_; |
|
//`uvm_sequence_utils(cag_rgm_write_sequence, cag_rgm_sequencer) |
`uvm_object_utils(cag_rgm_write_sequence) |
|
function new(string name="cag_rgm_write_sequence"); |
super.new(name); |
endfunction : new |
|
task body(); |
cag_rgm_base m_req_; |
|
//p_sequencer.uvm_report_info(get_type_name(), $psprintf("Write Request:\n%s ",req_.sprint()),UVM_NONE); |
$cast(m_req_,req_.clone()); |
|
write_reg(m_req_); |
|
req_.copy(m_req_); |
endtask : body |
|
endclass : cag_rgm_write_sequence |
|
class cag_rgm_read_sequence extends cag_rgm_sequence; |
|
rand cag_rgm_base req_; |
|
`uvm_object_utils(cag_rgm_read_sequence) |
|
function new(string name="cag_rgm_read_sequence"); |
super.new(name); |
endfunction : new |
|
task body(); |
cag_rgm_base m_req_; |
cag_rgm_base old_reg; |
|
//req_ = cag_rgm_base::type_id::create("m_req"); |
//req_.copy(req_); |
$cast(m_req_,req_.clone()); |
|
if (m_req_.get_check_on_read() == 1) begin//-- checking is enabled, so make a copy to compare afterwards |
$cast(old_reg,m_req_.clone()); |
end |
|
//if (m_req_.get_check_on_read() == 1) |
// p_sequencer.uvm_report_info(get_type_name(), $psprintf("Read Request:\n%s\n, Saved:\n%s ",m_req_.sprint(),old_reg.sprint()),UVM_NONE); |
read_reg(m_req_); |
|
//uvm_report_info(get_type_name(),$psprintf("Compare of:\n%s\n%s",m_req_.sprint(),old_reg.sprint()),UVM_NONE); |
|
if (m_req_.get_check_on_read() == 1) begin |
|
if (m_req_.compare(old_reg) != 1) |
p_sequencer.uvm_report_fatal(get_type_name(), |
$psprintf("Compare for check_on_read failed for:\n%s\nShould be:\n%s\nMaybe checking on this register has to be turned off. ",m_req_.sprint(), old_reg.sprint())); |
end |
|
req_.copy(m_req_); |
endtask : body |
|
endclass : cag_rgm_read_sequence |
|
/****************************************************************************** |
* |
* REVISION HISTORY: |
* |
*******************************************************************************/ |
/openhmc/trunk/openHMC/sim/UVC/cag_rgm/sv/cag_rgm_rfs_if.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/>. |
* |
* |
*/ |
|
// |
// |
// register file interface |
// |
// |
|
`ifndef CAG_RGM_RFS_IF_SV |
`define CAG_RGM_RFS_IF_SV |
|
interface cag_rgm_rfs_if #( |
parameter ADDR_WIDTH = 6, |
parameter WRITE_DATA_WIDTH = 64, |
parameter READ_DATA_WIDTH = 64 |
) (); |
|
logic res_n; |
logic clk; |
|
logic [ADDR_WIDTH-1:0] address; |
logic wen; |
logic ren; |
logic [WRITE_DATA_WIDTH-1:0] write_data; |
logic [READ_DATA_WIDTH-1:0] read_data; |
logic access_done; |
logic invalid_address; |
|
property valid_wen; |
@(posedge clk) disable iff(!res_n) |
wen |-> !$isunknown(address) && !$isunknown(write_data); |
endproperty : valid_wen |
assert property(valid_wen); |
|
|
property valid_ren; |
@(posedge clk) disable iff(!res_n) |
ren |-> !$isunknown(address); |
endproperty : valid_ren |
assert property(valid_ren); |
|
|
property valid_access_done; |
@(posedge clk) disable iff(!res_n) |
wen || ren |=> !(wen || ren) [*0:1150] ##1 access_done; |
endproperty : valid_access_done |
assert property(valid_access_done); |
|
access_done_one_clk : assert property(@(posedge clk) disable iff(!res_n) $rose(access_done) |=> !access_done ); |
|
property invalid_address_on_done_only; |
@(posedge clk) disable iff(!res_n) |
invalid_address |-> access_done; |
endproperty : invalid_address_on_done_only |
assert property(invalid_address_on_done_only); |
|
property no_simultaneous_read_and_write_on_0; |
@(posedge clk) disable iff(!res_n) |
ren |-> !wen; |
endproperty : no_simultaneous_read_and_write_on_0 |
assert property(no_simultaneous_read_and_write_on_0); |
|
property no_simultaneous_read_and_write_on_1; |
@(posedge clk) disable iff(!res_n) |
wen |-> !ren; |
endproperty : no_simultaneous_read_and_write_on_1 |
assert property(no_simultaneous_read_and_write_on_1); |
|
endinterface : cag_rgm_rfs_if |
|
`endif // CAG_RGM_RFS_IF_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_env.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 AXI4_STREAM_ENV_SV |
`define AXI4_STREAM_ENV_SV |
|
class axi4_stream_env #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_env; |
|
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
axi4_stream_master_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) master; |
axi4_stream_slave_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) slave; |
|
axi4_stream_monitor #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) monitor; |
|
axi4_stream_config axi4_stream_cfg; |
|
|
|
`uvm_component_param_utils_begin(axi4_stream_env #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(axi4_stream_cfg, UVM_DEFAULT) |
`uvm_field_object(master, UVM_DEFAULT) |
`uvm_field_object(slave, UVM_DEFAULT) |
`uvm_field_object(monitor, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="axi4_stream_env", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
//-- configure interfaces |
if(uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::get(this, "", "vif",vif) ) begin |
uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::set(this, "monitor","vif",vif); |
uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::set(this, "master" ,"vif",vif); |
uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::set(this, "slave" ,"vif",vif); |
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_config_db#(axi4_stream_config)::set(this, "master" , "axi4_stream_cfg", axi4_stream_cfg); //distributing axi4_stream_cfg to master agent |
uvm_config_db#(axi4_stream_config)::set(this, "slave" , "axi4_stream_cfg", axi4_stream_cfg); //distributing axi4_stream_cfg to slave agent |
end else begin |
uvm_report_fatal(get_type_name(), $psprintf("axi4_stream_cfg not set via config_db")); |
end |
|
//-- create |
monitor = axi4_stream_monitor #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("monitor", this); |
master = axi4_stream_master_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("master", this); |
slave = axi4_stream_slave_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("slave", this); |
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
endfunction : connect_phase |
|
endclass : axi4_stream_env |
|
`endif // AXI4_STREAM_ENV_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_slave_agent.sv
0,0 → 1,81
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 AXI4_STREAM_SLAVE_AGENT_SV |
`define AXI4_STREAM_SLAVE_AGENT_SV |
|
class axi4_stream_slave_agent #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_agent; |
|
axi4_stream_config axi4_stream_cfg; |
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
axi4_stream_slave_driver #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) driver; |
|
`uvm_component_param_utils_begin(axi4_stream_slave_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(axi4_stream_cfg, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="axi4_stream_slave_agent", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
if(uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::get(this, "", "vif",vif) ) begin |
uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::set(this, "driver","vif",vif); |
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 |
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); |
end |
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
endfunction : connect_phase |
|
endclass : axi4_stream_slave_agent |
|
`endif // AXI4_STREAM_SLAVE_AGENT_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_master_agent.sv
0,0 → 1,91
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 AXI4_STREAM_MASTER_AGENT_SV |
`define AXI4_STREAM_MASTER_AGENT_SV |
|
class axi4_stream_master_agent #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_agent; |
|
axi4_stream_config axi4_stream_cfg; |
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
axi4_stream_master_driver #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) driver; |
axi4_stream_master_sequencer #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) sequencer; |
|
`uvm_component_param_utils_begin(axi4_stream_master_agent #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(axi4_stream_cfg, UVM_DEFAULT) |
`uvm_field_object(driver, UVM_DEFAULT) |
`uvm_field_object(sequencer, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="axi4_stream_master_agent", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::get(this, "", "vif",vif) ) begin |
uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::set(this, "driver","vif",vif); |
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 |
if(axi4_stream_cfg.master_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_master_driver #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("driver", this); |
sequencer = axi4_stream_master_sequencer#(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))::type_id::create("sequencer",this); |
end |
|
endfunction : build_phase |
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
if(axi4_stream_cfg.master_active == UVM_ACTIVE)begin |
driver.seq_item_port.connect(sequencer.seq_item_export); |
end |
endfunction : connect_phase |
|
endclass : axi4_stream_master_agent |
|
`endif // AXI4_STREAM_MASTER_AGENT_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_hmc_monitor.sv
0,0 → 1,262
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
// |
// |
// axi4_stream_packet hmc_monitor |
// |
// |
|
`ifndef AXI4_STREAM_HMC_MONITOR_SV |
`define AXI4_STREAM_HMC_MONITOR_SV |
|
class axi4_stream_hmc_monitor #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends hmc_module_mon ; |
|
|
int FPW ; |
int HEADERS ; |
int TAILS ; |
int VALIDS ; |
int valids_per_cycle = 0; |
int packet_length = 0; |
|
|
//-- uvm_analysis_port #(hmc_packet) item_collected_port; |
uvm_analysis_imp #( |
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)), |
axi4_stream_hmc_monitor #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) |
) axi4_port; |
|
int n_valids = 0; |
int n_valids_after_tail = 0; |
int n_valids_in_packet = 0; |
|
int headers_seen = 0; |
int tails_seen = 0; |
|
|
typedef bit [127:0] flit_t; |
flit_t flit_queue[$]; |
|
int packets_per_cycle = 0; |
|
hmc_packet packet; |
hmc_packet packet_queue[$]; |
|
//-- covergroup definition |
covergroup axi4_cg; |
HMC_PACKET_LENGTH : coverpoint packet_length; |
endgroup |
|
covergroup non_valids_cg; |
BETWEEN_PACKETS : coverpoint n_valids_after_tail; |
IN_PACKETS : coverpoint n_valids_in_packet; |
endgroup |
|
covergroup overlap_cg; |
PACKETS_WITH_2_CYCLES: coverpoint headers_seen>tails_seen; //-- boolean condition |
VALIDS_PER_CYCLE: coverpoint valids_per_cycle; |
endgroup |
|
|
`uvm_component_param_utils(axi4_stream_hmc_monitor #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
|
|
function new ( string name="axi4_stream_hmc_monitor", uvm_component parent ); |
super.new(name, parent); |
|
axi4_port = new("axi4_port",this); |
|
axi4_cg = new(); |
non_valids_cg = new(); |
overlap_cg = new(); |
|
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
FPW = DATA_BYTES/16;//-- convert to variables! |
HEADERS = FPW; |
TAILS = 2*FPW; |
VALIDS = 0; |
endfunction : build_phase |
|
//-- Stuff FLITs into a FIFO, separate control signals |
function void collect_flits(input axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vc); |
//-- read tuser flags for valid flags |
flit_t tmp_flit; |
flit_t current_flit; |
packets_per_cycle = 0; |
valids_per_cycle =0; |
for (int i = 0; i<FPW; i++) begin //-- Check bitvektor |
//-- Check if valid |
if (vc.tuser[VALIDS+i] == 1) begin |
valids_per_cycle ++; |
|
//-- Cover not valid flits |
if (n_valids > 0) begin |
//-- Check if between packets |
if (tails_seen == headers_seen) //-- non valids after packet tail |
n_valids_after_tail =n_valids; |
else //-- non valids between header and tail |
n_valids_in_packet = n_valids; |
non_valids_cg.sample(); |
n_valids =0; |
n_valids_after_tail = 0; |
n_valids_in_packet= 0; |
end |
|
//-- Write 2 flit queue |
for (int b=0; b<128; b++) |
tmp_flit[b] = vc.tdata[128*i+b]; |
flit_queue.push_back(tmp_flit); |
|
if (vc.tuser[HEADERS+i] == 1) begin |
headers_seen++; //-- Complete hmc_packets to assemble |
packets_per_cycle ++; |
end |
//-- Check if tail for complete hmc packet |
if (vc.tuser[TAILS+i] == 1) begin |
tails_seen++; //-- Complete hmc_packets to assemble |
end |
|
//-- Check complete hmc packets |
`uvm_info(get_type_name(),$psprintf("Seen %d header and %d tails", headers_seen, tails_seen) ,UVM_HIGH) |
assert (tails_seen<= headers_seen) |
else `uvm_fatal(get_type_name(), $psprintf("packet is null")) |
|
end |
else begin |
n_valids ++; |
end |
|
end |
//-- Sample covergroup |
overlap_cg.sample(); |
|
endfunction : collect_flits |
|
//-- Use FLITs to form packets |
function void collect_packet(); |
int current_packet_length; |
|
flit_t current_flit; |
bit bitstream[]; |
packet_length = 0; |
//-- Assemble 1 hmc packet |
flit_queue_underflow : assert (flit_queue.size() > 0); |
|
//-- First flit is always header |
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]; |
flit_queue_underflow2 : assert (flit_queue.size() >= current_packet_length - 1); //--check check hmc_packet complete received |
|
|
//-- pack flits 2 bitstream |
bitstream = new[current_packet_length*128]; |
|
//-- Pack first flit |
for (int i=0; i<128; i=i+1) |
bitstream[i] = current_flit[i]; |
|
//-- Get and pack the remaining flits |
for (int flit=1; flit < current_packet_length; flit ++) begin |
current_flit = flit_queue.pop_front(); |
`uvm_info(get_type_name(),$psprintf("pop flit %0d (%0x)", flit, current_flit), UVM_HIGH) |
for (int i=0; i<128; i=i+1) begin |
bitstream[flit*128+i] = current_flit[i]; |
end |
end |
packet_length =current_packet_length; |
axi4_cg.sample(); |
|
packet = hmc_packet::type_id::create("packet", this); |
void'(packet.unpack(bitstream)); |
|
tails_seen--; |
if (packet == null) begin |
`uvm_fatal(get_type_name(), $psprintf("packet is null")) |
end |
|
packet_queue.push_back(packet); |
|
if(packet.get_command_type() == HMC_RESPONSE_TYPE)begin |
`uvm_info("RESPONSE collected",$psprintf("Rsp %0d : %s",rsp_rcvd, packet.command.name()), UVM_LOW) |
rsp_rcvd++; |
end else begin |
`uvm_info("REQUEST collected",$psprintf("Req %0d : %s",req_rcvd, packet.command.name()), UVM_LOW) |
req_rcvd++; |
end |
`uvm_info("AXI4 to HMC Monitor",$psprintf("\n%s", packet.sprint()), UVM_HIGH) |
endfunction : collect_packet |
|
function void write(input axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vc); |
hmc_packet expected; |
|
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) |
|
|
//-- Convert flit_queue to hmc_packets |
while (tails_seen >0) begin |
collect_packet(); |
end |
//-- If flit queue is not empty -> hmc packet striped over 2 axi cycles |
|
|
while (packet_queue.size()>0) begin |
item_collected_port.write(packet_queue.pop_front()); |
end |
endfunction |
|
function void check_phase(uvm_phase phase); |
if (flit_queue.size() >0) |
`uvm_fatal(get_type_name(),$psprintf("flit_queue is not empty: %0d", flit_queue.size())) |
endfunction : check_phase |
endclass : axi4_stream_hmc_monitor |
|
`endif // AXI4_STREAM_HMC_MONITOR_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_if.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/>. |
* |
* |
*/ |
|
// |
// |
// AXI4 Stream Interface |
// |
// |
|
`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 signals |
//-- |
|
logic TVALID; // Master valid |
logic TREADY; // Slave ready |
logic [8*DATA_BYTES-1:0] TDATA; //-- Master data |
logic [TUSER_WIDTH-1:0] TUSER; //-- Master sideband signals |
|
|
|
|
//-- |
//-- Interface Assertions |
//-- |
|
property data_hold_p; |
logic [8*DATA_BYTES-1:0] m_data; |
|
@(posedge ACLK) disable iff(!ARESET_N) |
(TVALID == 1 && TREADY == 0,m_data = TDATA) |=> (TDATA == m_data); |
endproperty : data_hold_p |
|
chk_data_hold : assert property(data_hold_p); |
|
endinterface : axi4_stream_if |
|
`endif // AXI4_STREAM_IF_SV |
|
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_valid_cycle.sv
0,0 → 1,71
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
// |
// axi4_valid_cycle |
// |
|
`ifndef AXI4_STREAM_VALID_CYCLE_SV |
`define AXI4_STREAM_VALID_CYCLE_SV |
|
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 int unsigned delay = 0; |
|
constraint c_packet_delay { |
delay < 20 ; |
} |
|
|
`uvm_object_param_utils_begin(axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_int(tdata, UVM_ALL_ON | UVM_NOPACK | UVM_HEX) |
`uvm_field_int(tuser, UVM_ALL_ON | UVM_NOPACK | UVM_HEX) |
`uvm_field_int(delay, UVM_DEFAULT | UVM_DEC| UVM_NOPACK) |
`uvm_object_utils_end |
|
function new (string name = "axi4_stream_valid_cycle"); |
super.new(name); |
endfunction : new |
|
endclass : axi4_stream_valid_cycle |
|
`endif // AXI4_STREAM_VALID_CYCLE_SV |
|
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_pkg.sv
0,0 → 1,76
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_if.sv" |
`include "hmc_base_types_pkg.sv" |
|
`timescale 100ps/10ps |
|
package axi4_stream_pkg; |
|
`include "uvm_macros.svh" |
import uvm_pkg::*; |
import hmc_base_types_pkg::*; |
`include "hmc_module_mon.sv" |
|
`include "axi4_stream_config.sv" |
|
|
`include "axi4_stream_valid_cycle.sv" |
|
`include "axi4_stream_monitor.sv" |
`include "axi4_stream_hmc_monitor.sv" |
|
|
`include "axi4_stream_master_driver.sv" |
|
`include "tag_handler.sv" |
|
`include "axi4_stream_master_sequencer.sv" |
|
`include "axi4_stream_master_agent.sv" |
|
`include "axi4_stream_slave_driver.sv" |
`include "axi4_stream_slave_agent.sv" |
|
`include "axi4_stream_env.sv" |
|
|
|
endpackage : axi4_stream_pkg |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_master_sequence.sv
0,0 → 1,109
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 AXI4_STREAM_MASTER_SEQUENCE_SV |
`define AXI4_STREAM_MASTER_SEQUENCE_SV |
|
class axi4_stream_master_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(axi4_stream_master_sequence) |
|
`uvm_declare_p_sequencer(axi4_stream_master_sequencer) |
|
function new(string name="axi4_stream_master_sequence"); |
super.new(name); |
endfunction : new |
|
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 : axi4_stream_master_sequence |
|
`endif // AXI4_STREAM_MASTER_SEQUENCER_SV |
|
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_config.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 AXI4_STREAM_CONFIG_SV |
`define AXI4_STREAM_CONFIG_SV |
|
class axi4_stream_config extends uvm_object; |
|
uvm_active_passive_enum master_active = UVM_PASSIVE; |
uvm_active_passive_enum slave_active = 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_object_utils_end |
|
function new(string name = "axi4_stream_config"); |
super.new(name); |
endfunction : new |
|
virtual function void do_print (uvm_printer printer); |
super.do_print(printer); |
endfunction : do_print |
|
endclass : axi4_stream_config |
|
`endif // AXI4_STREAM_CONFIG_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_master_sequencer.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/>. |
* |
* |
*/ |
|
`ifndef AXI4_STREAM_MASTER_SEQUENCER_SV |
`define AXI4_STREAM_MASTER_SEQUENCER_SV |
|
class axi4_stream_master_sequencer #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_sequencer #(axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))); |
|
`uvm_component_param_utils(axi4_stream_master_sequencer #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
|
function new(string name = "axi4_stream_master_sequencer", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
|
|
endclass : axi4_stream_master_sequencer |
|
`endif // AXI4_STREAM_MASTER_SEQUENCER_SV |
|
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_slave_driver.sv
0,0 → 1,117
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 AXI4_STREAM_SLAVE_DRIVER_SV |
`define AXI4_STREAM_SLAVE_DRIVER_SV |
|
//-- After this works for HMC, generalize for PCIe as well |
class axi4_stream_slave_driver #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_driver #(hmc_packet); |
|
axi4_stream_config axi4_stream_cfg; |
|
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
|
`uvm_component_param_utils_begin(axi4_stream_slave_driver #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(axi4_stream_cfg, UVM_DEFAULT) |
`uvm_component_utils_end |
|
|
|
function new(string name="axi4_stream_slave_driver", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::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 ready_asserted = 0; |
bit last_valid = 0; |
int set_probability; |
|
super.run_phase(phase); |
|
forever begin |
if(vif.ARESET_N !== 1) begin |
vif.TREADY <= 1'b0; |
@(posedge vif.ARESET_N); |
end |
|
fork |
forever begin |
//-- Accept packets |
@(negedge 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; |
end |
|
vif.TREADY <= ready_asserted; |
last_valid = vif.TVALID == 1'b1; |
end |
begin //-- Asynchronous reset |
@(negedge vif.ARESET_N); |
end |
join_any |
disable fork; |
end |
|
endtask : run_phase |
|
endclass : axi4_stream_slave_driver |
|
`endif // AXI4_STREAM_SLAVE_DRIVER_SV |
|
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_master_driver.sv
0,0 → 1,127
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 AXI4_STREAM_MASTER_DRIVER_SV |
`define AXI4_STREAM_MASTER_DRIVER_SV |
|
class axi4_stream_master_driver #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_driver #(axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))); |
|
axi4_stream_config axi4_stream_cfg; |
|
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
`uvm_component_param_utils_begin(axi4_stream_master_driver #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
`uvm_field_object(axi4_stream_cfg, UVM_DEFAULT) |
`uvm_component_utils_end |
|
function new(string name="axi4_stream_master_driver", uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
if(!uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::get(this, "", "vif",vif) ) begin |
`uvm_fatal(get_type_name(),"vif is not set") |
end |
endfunction : build_phase |
|
task run_phase(uvm_phase phase); |
super.run_phase(phase); |
|
forever begin |
if(vif.ARESET_N !== 1) begin |
vif.TVALID <= 0; |
`uvm_info(get_type_name(),$psprintf("reset"), UVM_HIGH) |
@(posedge vif.ARESET_N); |
`uvm_info(get_type_name(),$psprintf("coming out of reset"), UVM_HIGH) |
end |
|
fork |
begin //-- Asynchronous reset |
@(negedge vif.ARESET_N); |
end |
begin |
drive_valid_cycles(); |
end |
join_any |
disable fork; |
end |
|
endtask : run_phase |
|
task drive_valid_cycles(); |
@(posedge vif.ACLK); |
|
forever begin |
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vc; |
|
//-- Try next AXI4 item |
seq_item_port.try_next_item(vc); |
if( vc != null) begin |
`uvm_info(get_type_name(),$psprintf("There is an item to sent"), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("send %0x %0x", vc.tuser, vc.tdata), UVM_MEDIUM) |
|
//-- Wait until delay |
repeat(vc.delay) |
@(posedge vif.ACLK); |
|
//-- Send AXI4 cycle |
vif.TDATA <= vc.tdata; |
vif.TUSER <= vc.tuser; |
vif.TVALID <= 1; |
@(posedge vif.ACLK) |
while(vif.TREADY == 0) |
@(posedge vif.ACLK); |
|
vif.TUSER <= 0; |
vif.TDATA <= 0; |
vif.TVALID <= 0; |
`uvm_info(get_type_name(),$psprintf("send done: %0x %0x", vc.tuser, vc.tdata), UVM_MEDIUM) |
|
seq_item_port.item_done(); |
end else //-- Else wait 1 cycle |
@(posedge vif.ACLK); |
|
end |
endtask : drive_valid_cycles |
|
endclass : axi4_stream_master_driver |
|
`endif //AXI4_STREAM_MASTER_DRIVER_SV |
/openhmc/trunk/openHMC/sim/UVC/axi4_stream/sv/axi4_stream_monitor.sv
0,0 → 1,122
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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/>. |
* |
* |
*/ |
|
// |
// |
// axi4_stream_packet monitor |
// |
// |
|
`ifndef AXI4_STREAM_MONITOR_SV |
`define AXI4_STREAM_MONITOR_SV |
|
class axi4_stream_monitor #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) extends uvm_monitor; |
|
virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vif; |
|
uvm_analysis_port #(axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) item_collected_port; |
|
`uvm_component_param_utils(axi4_stream_monitor #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH))) |
|
|
|
function new ( string name="axi4_stream_monitor", uvm_component parent ); |
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); |
|
if(uvm_config_db#(virtual interface axi4_stream_if #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)))::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(); |
axi4_stream_valid_cycle #(.DATA_BYTES(DATA_BYTES), .TUSER_WIDTH(TUSER_WIDTH)) vc; |
|
forever begin |
if (vif.ARESET_N !== 1) |
begin |
@(posedge vif.ARESET_N); |
end |
|
fork |
begin // Asynchronous reset |
@(negedge vif.ARESET_N); |
end |
forever begin |
// At the positive edge of ACLK |
@(posedge vif.ACLK); |
|
// Capture valid bus cycles |
if (vif.TVALID == 1 && vif.TREADY == 1) begin |
|
|
vc = new(); |
vc.tuser = vif.TUSER; |
vc.tdata = vif.TDATA; |
|
assert ( vc.tuser[DATA_BYTES/4-1:0] == //-- assert that hdr flags are part of valid flags |
vc.tuser[2*DATA_BYTES/4-1:DATA_BYTES/16] |
|vc.tuser[DATA_BYTES/4-1:0]) |
|
assert ( vc.tuser[DATA_BYTES/4-1:0] == //-- assert that hdr flags are part of valid flags |
vc.tuser[3*DATA_BYTES/4-1:DATA_BYTES/16] |
|vc.tuser[DATA_BYTES/4-1:0]) |
|
|
item_collected_port.write(vc); |
`uvm_info(get_type_name(),$psprintf("valid cycle tuser %0x tdata %0x", vc.tuser, vc.tdata), UVM_HIGH) |
end |
end |
join_any |
disable fork; |
|
|
end |
endtask : run |
|
endclass : axi4_stream_monitor |
|
`endif // AXI4_STREAM_MONITOR_SV |
/openhmc/trunk/openHMC/sim/UVC/hmc_base_types/sv/hmc_packet.sv
0,0 → 1,381
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 |
// |
|
`ifndef HMC_PACKET_SV |
`define HMC_PACKET_SV |
|
`define HMC_TYPE_MASK 6'h38 |
|
class hmc_packet extends uvm_sequence_item; |
|
// request header fields |
rand bit [2:0] cube_ID; // CUB |
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 |
rand hmc_command_encoding command; // CMD |
|
bit [127:0] payload[$]; // 16-byte granularity |
|
// request tail fields |
rand bit [4:0] return_token_count; // RTC |
rand bit [2:0] source_link_ID; // SLID |
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 |
|
// response header fields not used before |
rand bit [8:0] return_tag; // TGA (Optional) |
|
// response tail fields not used before |
rand bit [6:0] error_status; // ERRSTAT |
rand bit data_invalid; // DINV |
|
// special bits for IRTRY |
rand bit start_retry; |
rand bit clear_error_abort; |
|
// CRC status fields |
rand bit poisoned; // Inverted CRC |
rand bit crc_error; |
|
// helper fields |
rand int flit_delay; |
|
`uvm_object_utils_begin(hmc_packet) |
`uvm_field_int(flit_delay, UVM_ALL_ON | UVM_NOPACK | UVM_DEC | UVM_NOCOMPARE | UVM_DEC) |
`uvm_field_int(cube_ID, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(address, UVM_ALL_ON | UVM_NOPACK | UVM_HEX) |
`uvm_field_int(tag, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(packet_length, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(duplicate_length, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_enum(hmc_command_encoding, command, UVM_ALL_ON | UVM_NOPACK ) |
`uvm_field_queue_int(payload, UVM_ALL_ON | UVM_NOPACK) |
`uvm_field_int(return_token_count, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(source_link_ID, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(sequence_number, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(forward_retry_pointer, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(return_retry_pointer, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(packet_crc, UVM_ALL_ON | UVM_NOPACK | UVM_HEX) |
`uvm_field_int(return_tag, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(error_status, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(data_invalid, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`uvm_field_int(poisoned, UVM_ALL_ON | UVM_NOPACK | UVM_DEC) |
`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_crc_error { crc_error == 0; } |
constraint c_matching_length { packet_length == duplicate_length; } |
constraint c_return_tag { return_tag == 0; } |
constraint c_packet_length { ( |
(packet_length == 2 && command == HMC_POSTED_WRITE_16) || |
(packet_length == 3 && command == HMC_POSTED_WRITE_32) || |
(packet_length == 4 && command == HMC_POSTED_WRITE_48) || |
(packet_length == 5 && command == HMC_POSTED_WRITE_64) || |
(packet_length == 6 && command == HMC_POSTED_WRITE_80) || |
(packet_length == 7 && command == HMC_POSTED_WRITE_96) || |
(packet_length == 8 && command == HMC_POSTED_WRITE_112) || |
(packet_length == 9 && command == HMC_POSTED_WRITE_128) || |
(packet_length == 2 && command == HMC_WRITE_16) || |
(packet_length == 3 && command == HMC_WRITE_32) || |
(packet_length == 4 && command == HMC_WRITE_48) || |
(packet_length == 5 && command == HMC_WRITE_64) || |
(packet_length == 6 && command == HMC_WRITE_80) || |
(packet_length == 7 && command == HMC_WRITE_96) || |
(packet_length == 8 && command == HMC_WRITE_112) || |
(packet_length == 9 && command == HMC_WRITE_128) || |
(packet_length > 1 && packet_length <= 9 && command == HMC_READ_RESPONSE) || |
(packet_length == 1 && command == HMC_WRITE_RESPONSE) || |
(packet_length == 1 && command == HMC_MODE_WRITE_RESPONSE) || |
(packet_length == 1 && command == HMC_ERROR_RESPONSE) || |
(packet_length == 2 && (command & `HMC_TYPE_MASK) == HMC_MISC_WRITE_TYPE) || |
(packet_length == 2 && (command & `HMC_TYPE_MASK) == HMC_POSTED_MISC_WRITE_TYPE) || |
(packet_length == 1 && (command & `HMC_TYPE_MASK) == HMC_MODE_READ_TYPE) || |
(packet_length == 1 && (command & `HMC_TYPE_MASK) == HMC_READ_TYPE) || |
(packet_length == 1 && (command & `HMC_TYPE_MASK) == HMC_FLOW_TYPE) |
); } |
constraint c_flit_delay { |
flit_delay dist{0:/90, [1:8]:/8, [8:50]:/2 }; |
} |
|
function new (string name = "hmc_packet"); |
super.new(name); |
endfunction : new |
|
function void post_randomize(); |
bit [127:0] rand_flit; |
|
super.post_randomize(); |
|
if (packet_length > 9) |
`uvm_fatal(get_type_name(),$psprintf("post_randomize packet_length = %0d",packet_length)) |
|
`uvm_info("AXI Packet queued",$psprintf("%0s packet_length = %0d",command.name(), packet_length), UVM_HIGH) |
|
if (packet_length < 2) |
return; |
|
for (int i=0; i<packet_length-1; i++) begin |
randomize_flit_successful : assert (std::randomize(rand_flit)); |
payload.push_back(rand_flit); |
end |
|
endfunction |
|
function hmc_command_type get_command_type(); |
|
case(command & `HMC_TYPE_MASK) |
HMC_FLOW_TYPE: return HMC_FLOW_TYPE; |
HMC_READ_TYPE: return HMC_READ_TYPE; |
HMC_MODE_READ_TYPE: return HMC_MODE_READ_TYPE; |
HMC_POSTED_WRITE_TYPE: return HMC_POSTED_WRITE_TYPE; |
HMC_POSTED_MISC_WRITE_TYPE: return HMC_POSTED_MISC_WRITE_TYPE; |
HMC_WRITE_TYPE: return HMC_WRITE_TYPE; |
HMC_MISC_WRITE_TYPE: return HMC_MISC_WRITE_TYPE; |
HMC_RESPONSE_TYPE: return HMC_RESPONSE_TYPE; |
default: uvm_report_fatal(get_type_name(), $psprintf("command with an illegal command type='h%0h!", command)); |
endcase |
|
endfunction : get_command_type |
|
/* |
The CRC algorithm used on the HMC is the Koopman CRC-32K. This algorithm was |
chosen for the HMC because of its balance of coverage and ease of implementation. The |
polynomial for this algorithm is: |
x32 + x30 + x29 + x28 + x26 + x20 + x19 + x17 + x16 + x15 + x11 + x10 + x7 + x6 + x4 + x2 + x + 1 |
|
bit [31:0] polynomial = 33'b1_0111_0100_0001_1011_1000_1100_1101_0111; // Normal |
|
The CRC calculation operates on the LSB of the packet first. The packet CRC calculation |
must insert 0s in place of the 32-bits representing the CRC field before generating or |
checking the CRC. For example, when generating CRC for a packet, bits [63: 32] of the |
Tail presented to the CRC generator should be all zeros. The output of the CRC generator |
will have a 32-bit CRC value that will then be inserted in bits [63:32] of the Tail before |
forwarding that FLIT of the packet. When checking CRC for a packet, the CRC field |
should be removed from bits [63:32] of the Tail and replaced with 32-bits of zeros, then |
presented to the CRC checker. The output of the CRC checker will have a 32-bit CRC |
value that can be compared with the CRC value that was removed from the tail. If the two |
compare, the CRC check indicates no bit failures within the packet. |
*/ |
|
function bit [31:0] calculate_crc(); |
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 |
remainder = {remainder[31:0], bitstream[i]}; |
if( remainder[32] ) begin |
remainder = remainder ^ polynomial; |
end |
end |
|
for( int i=0; i < 64; i++ ) begin // zeroes for CRC and remainder |
remainder = {remainder[31:0], 1'b0}; |
if( remainder[32] ) begin |
remainder = remainder ^ polynomial; |
end |
end |
|
return remainder[31:0]; |
|
endfunction : calculate_crc |
|
virtual function void do_pack(uvm_packer packer); |
|
super.do_pack(packer); |
packer.big_endian = 0; |
|
// pack header half flit |
case(command & `HMC_TYPE_MASK) |
HMC_FLOW_TYPE: |
case (command) |
HMC_NULL: packer.pack_field( {64'h0}, 64); |
HMC_PRET: 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); |
HMC_TRET: 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); |
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, 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, address[33:0], 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, 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 |
|
// Allow for errors when packet_length != duplicate_length |
if ((packet_length == duplicate_length) && payload.size() + 1 != packet_length && command != HMC_NULL) |
uvm_report_fatal(get_type_name(), $psprintf("pack function size mismatch payload.size=%0d packet_length=%0d!", payload.size(), packet_length)); |
|
// pack payload |
for( int i=0; i<payload.size(); i++ ) packer.pack_field ( payload[i], 128); |
|
// pack tail half flit |
case(command & `HMC_TYPE_MASK) |
HMC_FLOW_TYPE: |
case (command) |
HMC_NULL: packer.pack_field( {64'h0}, 64); |
HMC_PRET: packer.pack_field ( {packet_crc[31:0], 5'h0, 3'h0, 5'h0, 3'h0, 8'h0, return_retry_pointer[7:0]}, 64); |
HMC_TRET: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], 3'h0, 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_IRTRY: packer.pack_field ( {packet_crc[31:0], 5'h0, 3'h0, 5'h0, 3'h0, 6'h0, clear_error_abort, start_retry, return_retry_pointer[7:0]}, 64); |
default: uvm_report_fatal(get_type_name(), $psprintf("pack function (tail) called for a hmc_packet with an illegal FLOW type='h%0h!", command)); |
endcase |
HMC_READ_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_POSTED_WRITE_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_WRITE_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_MODE_READ_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_POSTED_MISC_WRITE_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_MISC_WRITE_TYPE: packer.pack_field ( {packet_crc[31:0], return_token_count[4:0], source_link_ID[2:0], 5'h0, sequence_number[2:0], forward_retry_pointer[7:0], return_retry_pointer[7:0]}, 64); |
HMC_RESPONSE_TYPE: packer.pack_field ( {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]}, 64); |
default: uvm_report_fatal(get_type_name(), $psprintf("pack function (tail) called for a hmc_packet with an illegal command type='h%0h!", command)); |
endcase |
endfunction : do_pack |
|
|
virtual function void do_unpack(uvm_packer packer); |
bit [63:0] header; |
bit [31:0] calculated_crc; |
bit [21:0] rsvd22; |
bit [5:0] rsvd6; |
bit [4:0] rsvd5; |
bit [2:0] rsvd3; |
bit rsvd1; |
|
super.do_unpack(packer); |
packer.big_endian = 0; |
|
// header |
header = packer.unpack_field(64); |
command[5:0] = header[5:0]; |
|
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)); |
|
// payload |
for (int i = 0; i < packet_length-1; i++) |
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); |
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); |
|
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(); |
|
// Inverted CRC means poisoned |
poisoned = (packet_crc == ~calculated_crc) ? 1'b1 : 1'b0; |
|
crc_error = (packet_crc != calculated_crc && !poisoned) ? 1'b1 : 1'b0; |
endfunction : do_unpack |
|
|
virtual function bit compare_adaptive_packet(hmc_packet rhs, uvm_comparer comparer); |
|
string name_string; |
|
compare_adaptive_packet &= comparer.compare_field("packet_length", packet_length, rhs.packet_length, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("payload.size()", payload.size(), rhs.payload.size(), 64, UVM_DEC); |
|
for (int i=0; i<packet_length; i++) |
begin |
if (!compare_adaptive_packet) |
return 0; |
$sformat(name_string, "payload[%0d]", i); |
compare_adaptive_packet &= comparer.compare_field(name_string, payload[i], rhs.payload[i], 128, UVM_HEX); |
end |
|
compare_adaptive_packet &= comparer.compare_field("cube_ID", cube_ID, rhs.cube_ID, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("address", address, rhs.address, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("tag", tag, rhs.tag, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("packet_length", packet_length, rhs.packet_length, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("duplicate_length", duplicate_length, rhs.duplicate_length, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("command", command, rhs.command, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("return_token_count", return_token_count, rhs.return_token_count, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("source_link_ID", source_link_ID, rhs.source_link_ID, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("sequence_number", sequence_number, rhs.sequence_number, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("forward_retry_pointer", forward_retry_pointer, rhs.forward_retry_pointer, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("return_tag", return_tag, rhs.return_tag, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("error_status", error_status, rhs.error_status, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("data_invalid", data_invalid, rhs.data_invalid, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("start_retry", start_retry, rhs.start_retry, 64, UVM_DEC); |
compare_adaptive_packet &= comparer.compare_field("clear_error_abort", clear_error_abort, rhs.clear_error_abort, 64, UVM_DEC); |
|
endfunction : compare_adaptive_packet |
|
endclass : hmc_packet |
|
`endif // HMC_PACKET_SV |
|
/openhmc/trunk/openHMC/sim/UVC/hmc_base_types/sv/hmc_types.svh
0,0 → 1,114
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_TYPES_SVH |
`define HMC_TYPES_SVH |
|
typedef enum bit [5:0] { |
HMC_FLOW_TYPE = 6'h00, |
HMC_WRITE_TYPE = 6'h08, |
HMC_MISC_WRITE_TYPE = 6'h10, |
HMC_POSTED_WRITE_TYPE = 6'h18, |
HMC_POSTED_MISC_WRITE_TYPE = 6'h20, |
HMC_MODE_READ_TYPE = 6'h28, |
HMC_READ_TYPE = 6'h30, |
HMC_RESPONSE_TYPE = 6'h38 |
} hmc_command_type; |
|
typedef enum bit [5:0] { |
HMC_NULL = 6'h00, |
HMC_PRET = 6'h01, |
HMC_TRET = 6'h02, |
HMC_IRTRY = 6'h03, |
HMC_WRITE_16 = 6'h08, |
HMC_WRITE_32 = 6'h09, |
HMC_WRITE_48 = 6'h0a, |
HMC_WRITE_64 = 6'h0b, |
HMC_WRITE_80 = 6'h0c, |
HMC_WRITE_96 = 6'h0d, |
HMC_WRITE_112 = 6'h0e, |
HMC_WRITE_128 = 6'h0f, |
//HMC_MODE_WRITE = 6'h10, |
//HMC_BIT_WRITE = 6'h11, |
//HMC_DUAL_8B_ADDI = 6'h12, |
//HMC_SINGLE_16B_ADDI = 6'h13, |
HMC_POSTED_WRITE_16 = 6'h18, |
HMC_POSTED_WRITE_32 = 6'h19, |
HMC_POSTED_WRITE_48 = 6'h1a, |
HMC_POSTED_WRITE_64 = 6'h1b, |
HMC_POSTED_WRITE_80 = 6'h1c, |
HMC_POSTED_WRITE_96 = 6'h1d, |
HMC_POSTED_WRITE_112 = 6'h1e, |
HMC_POSTED_WRITE_128 = 6'h1f, |
HMC_POSTED_BIT_WRIT = 6'h21, |
//HMC_POSTED_DUAL_8B_ADDI = 6'h22, |
//HMC_POSTED_SINGLE_16B_ADDI = 6'h23, |
HMC_MODE_READ = 6'h28, |
HMC_READ_16 = 6'h30, |
HMC_READ_32 = 6'h31, |
HMC_READ_48 = 6'h32, |
HMC_READ_64 = 6'h33, |
HMC_READ_80 = 6'h34, |
HMC_READ_96 = 6'h35, |
HMC_READ_112 = 6'h36, |
HMC_READ_128 = 6'h37, |
HMC_READ_RESPONSE = 6'h38, |
HMC_WRITE_RESPONSE = 6'h39, |
HMC_MODE_READ_RESPONSE = 6'h3A, |
HMC_MODE_WRITE_RESPONSE = 6'h3B, |
HMC_ERROR_RESPONSE = 6'h3E |
} hmc_command_encoding; |
|
typedef enum { |
RESET, |
INIT, |
PRBS, |
NULL_FLITS, |
TS1, |
NULL_FLITS_2, |
INITIAL_TRETS, |
LINK_UP, |
START_RETRY_INIT, |
CLEAR_RETRY, |
SEND_RETRY_PACKETS |
|
} init_state_t; |
|
`endif // HMC_TYPES_SVH |
|
/openhmc/trunk/openHMC/sim/UVC/hmc_base_types/sv/hmc_base_types_pkg.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/>. |
* |
* |
*/ |
|
`timescale 100ps/10ps |
|
package hmc_base_types_pkg; |
|
`include "uvm_macros.svh" |
import uvm_pkg::*; |
|
`include "hmc_types.svh" |
`include "hmc_packet.sv" |
|
endpackage : hmc_base_types_pkg |
/openhmc/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_cfg.sv
0,0 → 1,52
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_MODULE_CFG |
`define HMC_MODULE_CFG |
class hmc_module_cfg extends uvm_object; |
bit cover_enable; |
|
`uvm_object_utils(hmc_module_cfg) |
|
function new(string name="hmc_module_cfg"); |
super.new(name); |
endfunction : new |
|
endclass hmc_module_cfg |
`endif |
/openhmc/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_pkg.sv
0,0 → 1,60
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_MODULE_PKG |
`define HMC_MODULE_PKG |
`timescale 100ps/10ps |
|
package hmc_module_pkg; |
|
import uvm_pkg::*; |
`include "uvm_macros.svh" |
import hmc_base_types_pkg::*; |
import axi4_stream_pkg::*; |
|
|
`include "hmc_module_scb.sv" |
`include "hmc_module_mon.sv" |
|
//`include "hmc_module_cfg.sv" |
`include "hmc_module_env.sv" |
|
endpackage : hmc_module_pkg |
|
`endif |
/openhmc/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_scb.sv
0,0 → 1,324
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_SCOREBOARD_SV |
`define HMC_SCOREBOARD_SV |
|
|
class hmc_module_scb extends uvm_scoreboard; |
|
protected int hmc_rsp_packet_count = 0; |
protected int hmc_req_packet_count = 0; |
protected int axi4_rsp_packet_count = 0; |
protected int axi4_req_packet_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[$]; |
|
int valid_cycle = 0; |
|
//--check tags |
int tag_count = 512; |
bit [512:0]used_tags; |
|
|
|
|
//-- analysis imports |
//-- HMC Interface |
`uvm_analysis_imp_decl(_hmc_req) |
uvm_analysis_imp_hmc_req #(hmc_packet, hmc_module_scb) hmc_req_port; |
`uvm_analysis_imp_decl(_hmc_rsp) |
uvm_analysis_imp_hmc_rsp #(hmc_packet, hmc_module_scb) hmc_rsp_port; |
|
//-- Host Interface |
`uvm_analysis_imp_decl(_axi4_hmc_req) |
uvm_analysis_imp_axi4_hmc_req #(hmc_packet, hmc_module_scb ) axi4_hmc_req; |
`uvm_analysis_imp_decl(_axi4_hmc_rsp) |
uvm_analysis_imp_axi4_hmc_rsp #(hmc_packet, hmc_module_scb ) axi4_hmc_rsp; |
|
|
`uvm_component_utils(hmc_module_scb ) |
|
function new (string name="hmc_module_scb", uvm_component parent); |
super.new(name, parent); |
axi4_hmc_req = new("axi4_hmc_req",this); |
axi4_hmc_rsp = new("axi4_hmc_rsp",this); |
hmc_req_port = new("hmc_req_port",this); |
hmc_rsp_port = new("hmc_rsp_port",this); |
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); |
int i; |
hmc_packet request; |
|
//-- 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())); |
|
//-- delete the previous sent request packet |
request = axi4_np_requests[packet.tag].pop_front(); |
if (axi4_np_requests[packet.tag].size() == 0) |
axi4_np_requests.delete(packet.tag); |
|
//-- check the hmc_packet |
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())) |
|
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())) |
|
if (packet.command == HMC_READ_RESPONSE) begin |
int expected_count; |
case (request.command) |
HMC_MODE_READ: expected_count = 1; |
HMC_READ_16: expected_count = 1; |
HMC_READ_32: expected_count = 2; |
HMC_READ_48: expected_count = 3; |
HMC_READ_64: expected_count = 4; |
HMC_READ_80: expected_count = 5; |
HMC_READ_96: expected_count = 6; |
HMC_READ_112: expected_count = 7; |
HMC_READ_128: expected_count = 8; |
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())) |
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())) |
|
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())) |
|
if (expected.packet_length != packet.packet_length) |
`uvm_fatal(get_type_name(),$psprintf("hmc_2_axi4_compare: Packet length mismatch %0d != %0d ", expected.packet_length, packet.packet_length)) |
|
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())) |
|
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])) |
end |
|
endfunction : hmc_2_axi4_compare |
|
//-- compare and check 2 Request type packets |
function void axi4_2_hmc_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())) |
|
if (expected.command != packet.command) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_compare: Expected %s, got %s", expected.command.name(), packet.command.name())) |
|
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)) |
|
if (expected.address != packet.address) |
`uvm_fatal(get_type_name(),$psprintf("axi4_2_hmc_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)) |
|
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())) |
|
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])) |
end |
endfunction : axi4_2_hmc_compare |
|
function void write_hmc_rsp(input hmc_packet packet); |
hmc_packet expected; |
|
hmc_rsp_packet_count++; |
|
`uvm_info(get_type_name(),$psprintf("hmc_rsp: received packet #%0d %s", hmc_rsp_packet_count, packet.command.name()), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("hmc_rsp: \n%s", packet.sprint()), UVM_HIGH) |
|
//-- check this packet later |
hmc_2_axi4.push_back(packet); |
endfunction : write_hmc_rsp |
|
function void write_hmc_req(input hmc_packet packet); |
hmc_packet expected; |
|
if (packet == null) begin |
`uvm_fatal(get_type_name(), $psprintf("packet is null")) |
end |
|
hmc_req_packet_count++; |
|
`uvm_info(get_type_name(),$psprintf("hmc_req: received packet #%0d %s@%0x (tok %0d)", hmc_req_packet_count, packet.command.name(), packet.address, packet.return_token_count), UVM_MEDIUM) |
`uvm_info(get_type_name(),$psprintf("hmc_req: \n%s", packet.sprint()), UVM_HIGH) |
|
//-- expect an request packet on the host (AXI4) request queue |
if (axi4_2_hmc.size() == 0) |
`uvm_fatal(get_type_name(),$psprintf("write_hmc_req: Unexpected packet (the request queue is empty)\n%s",packet.sprint())) |
else |
expected = axi4_2_hmc.pop_front(); |
|
//-- compare and check 2 Request type packets |
axi4_2_hmc_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 |
|
|
function void write_axi4_hmc_rsp(input hmc_packet packet); |
|
hmc_packet expected; |
if (packet == null) begin |
`uvm_fatal(get_type_name(), $psprintf("packet is null")) |
end |
|
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) |
|
//-- compare with previous on the HMC side received response packet |
expected = hmc_2_axi4.pop_front(); |
hmc_2_axi4_compare(expected, packet); |
`uvm_info(get_type_name(),$psprintf("axi4_rsp: checked packet #%0d %s", axi4_rsp_packet_count, packet.command.name()), UVM_MEDIUM) |
|
//-- 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 |
|
endfunction :write_axi4_hmc_rsp |
|
|
function void write_axi4_hmc_req(input hmc_packet packet); |
if (packet == null) begin |
`uvm_fatal(get_type_name(), $psprintf("packet is null")) |
end |
`uvm_info(get_type_name(),$psprintf("collected a packet %s", packet.command.name()), UVM_HIGH) |
`uvm_info(get_type_name(),$psprintf("\n%s", packet.sprint()), UVM_HIGH) |
|
//-- check packet later |
axi4_req_packet_count++; |
axi4_2_hmc.push_back(packet); |
|
//-- check if tag checking is necessary |
if (packet.get_command_type() == HMC_WRITE_TYPE |
|| packet.get_command_type() == HMC_MISC_WRITE_TYPE |
|| packet.get_command_type() == HMC_READ_TYPE |
|| packet.get_command_type() == HMC_MODE_READ_TYPE) |
begin |
//-- store this packet to check corresponding response packet later |
if (!axi4_np_requests.exists(packet.tag)) begin |
axi4_np_requests[packet.tag] = {}; |
end |
else begin |
`uvm_info(get_type_name(),$psprintf("There is already an outstanding axi4 request with tag %0x!", packet.tag), UVM_MEDIUM) |
end |
axi4_np_requests[packet.tag].push_back(packet); |
|
if (used_tags[packet.tag] == 1'b0) begin |
used_tags[packet.tag] = 1'b1; |
end else begin |
`uvm_fatal(get_type_name(), $psprintf("tag %0d is already in use", packet.tag)) |
|
end |
end |
|
`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); |
|
if (axi4_rsp_packet_count != hmc_rsp_packet_count) |
`uvm_fatal(get_type_name(),$psprintf("axi4_rsp_packet_count = %0d hmc_rsp_packet_count = %0d!", axi4_rsp_packet_count, hmc_rsp_packet_count)) |
if (axi4_req_packet_count != hmc_req_packet_count) |
`uvm_fatal(get_type_name(),$psprintf("axi4_req_packet_count = %0d hmc_req_packet_count = %0d!", axi4_req_packet_count, hmc_req_packet_count)) |
|
//-- check for open requests on the host side |
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) |
end |
end |
`uvm_fatal(get_type_name(),$psprintf("axi4_np_requests.size() = %0d, not all requests have been answered!", axi4_np_requests.size())) |
end |
|
//-- check for open tags |
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) |
end |
`uvm_fatal(get_type_name(),$psprintf("Open Tags!")) |
end |
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) |
endfunction : report_phase |
|
endclass : hmc_module_scb |
|
`endif // HMC_SCOREBOARD_SV |
/openhmc/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_env.sv
0,0 → 1,100
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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_MODULE_ENV |
`define HMC_MODULE_ENV |
class hmc_module_env extends uvm_env; |
//hmc_module_cfg module_cfg; |
|
hmc_module_mon axi4_req_mon; |
hmc_module_mon axi4_rsp_mon; |
|
hmc_module_mon hmc_req_mon; |
hmc_module_mon hmc_rsp_mon; |
|
|
hmc_module_scb scb; |
|
|
|
`uvm_component_utils(hmc_module_env) |
|
|
|
function new (string name = "hmc_module_env", uvm_component parent); |
super.new(name, parent); |
endfunction : new |
|
virtual function void build_phase(uvm_phase phase); |
string inst_name; |
super.build_phase(phase); |
|
|
|
//-- Additional monitor for AXI4 Stream 2 HMC packet conversion |
axi4_req_mon = hmc_module_mon::type_id::create("axi4_req_mon", this); |
axi4_rsp_mon = hmc_module_mon::type_id::create("axi4_rsp_mon", this); |
|
//-- Additional monitor for BFM 2 HMC packet conversion |
hmc_req_mon = hmc_module_mon::type_id::create("hmc_req_mon", this); |
hmc_rsp_mon = hmc_module_mon::type_id::create("hmc_rsp_mon", this); |
|
//-- scoreboard |
scb = hmc_module_scb::type_id::create("scb", this); |
|
|
endfunction : build_phase |
|
|
function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
//-- Connect module monitors to scoreboard |
axi4_req_mon.item_collected_port.connect(scb.axi4_hmc_req); |
axi4_rsp_mon.item_collected_port.connect(scb.axi4_hmc_rsp); |
|
hmc_req_mon.item_collected_port.connect(scb.hmc_req_port); |
hmc_rsp_mon.item_collected_port.connect(scb.hmc_rsp_port); |
|
|
|
endfunction : connect_phase |
|
endclass: hmc_module_env |
`endif |
/openhmc/trunk/openHMC/sim/UVC/hmc_module/sv/hmc_module_mon.sv
0,0 → 1,67
/* |
* .--------------. .----------------. .------------. |
* | .------------. | .--------------. | .----------. | |
* | | ____ ____ | | | ____ ____ | | | ______ | | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || | |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| | |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| | |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| | |
* | | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' | |
* '--------------' '----------------' '------------' |
* |
* 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 MODULE_MON |
`define MODULE_MON |
class hmc_module_mon extends uvm_monitor; |
//-- Basic Module monitor |
|
uvm_analysis_port #(hmc_packet) item_collected_port; |
int req_rcvd = 0; |
int rsp_rcvd = 0; |
|
|
`uvm_component_utils(hmc_module_mon) |
function new ( string name = "hmc_module_mon", uvm_component parent ); |
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 |
|
|
endclass |
|
`endif |