├── basic ├── tb.f ├── my_sequences_pkg.sv ├── my_sequence.sv ├── my_test.sv ├── dut.v ├── run.do ├── commands_sequence.sv ├── dut_if.sv ├── my_param_container.sv ├── test1.sv ├── my_transaction.sv ├── test2.sv ├── my_component.sv ├── top.sv ├── read_modify_write_sequence.sv ├── my_driver.sv ├── my_monitor.sv ├── my_subscriber.sv ├── my_env.sv ├── dut_pkg.sv └── my_agent.sv ├── mult ├── tb │ ├── booth_mult │ │ ├── tb.f │ │ ├── top.sv │ │ ├── dut_if.sv │ │ ├── mult_input_t.sv │ │ ├── run.do │ │ └── dut_pkg.sv │ ├── mult_div │ │ ├── tb.f │ │ ├── top.sv │ │ ├── mult_input_t.sv │ │ ├── dut_if.sv │ │ ├── run.do │ │ └── dut_pkg.sv │ ├── booth_mult2 │ │ ├── tb.f │ │ ├── top.sv │ │ ├── dut_if.sv │ │ ├── mult_input_t.sv │ │ ├── run.do │ │ └── dut_pkg.sv │ ├── unsigned_multi │ │ ├── tb.f │ │ ├── top.sv │ │ ├── mult_input_t.sv │ │ ├── run.do │ │ ├── dut_pkg.sv │ │ └── dut_if.sv │ └── common │ │ ├── mult_config.sv │ │ ├── dut_if_base.sv │ │ ├── mult_basic_seq.sv │ │ ├── neg_test.sv │ │ ├── smoke_test.sv │ │ ├── mult_one_seq.sv │ │ ├── mult_env.sv │ │ ├── mult_driver.sv │ │ ├── mult_scoreboard.sv │ │ ├── mult_coverage_unsigned.sv │ │ ├── mult_monitor.sv │ │ ├── mult_agent.sv │ │ ├── mult_zero_seq.sv │ │ ├── mult_coverage_signed.sv │ │ ├── zeros_ones_test.sv │ │ └── mult_neg_seq.sv └── dut │ ├── booth_mult │ ├── readme │ └── boothmult.vhdl │ ├── booth_mult2 │ ├── readme │ └── Booth_Multiplier.v │ ├── mult_div │ ├── readme │ ├── mudi64_tb.v │ ├── add32.v │ └── mudi64.v │ └── unsigned_multi │ └── mult.vhd ├── noc-router ├── hermes_router │ ├── rtl │ │ ├── hdl_v.f │ │ ├── src │ │ │ ├── RouterCC.vhd │ │ │ ├── Hermes_buffer.vhd │ │ │ ├── Hermes_switchcontrol.vhd │ │ │ └── RouterCC_wrapper.sv │ │ └── hdl_vhd.f │ ├── docs │ │ ├── tb.png │ │ ├── router.odp │ │ ├── router.png │ │ └── readme.md │ ├── sim │ │ ├── readme.md │ │ ├── shutup.do │ │ ├── wave.do │ │ ├── Makefile │ │ ├── run.do │ │ └── wave_full.do │ ├── syn │ │ ├── hdl_v.f │ │ ├── power.rep │ │ ├── area.rep │ │ ├── constraints.sdc │ │ ├── run.tcl │ │ ├── src │ │ │ └── RouterCC_wrapper.v │ │ ├── load.tcl │ │ ├── readme.md │ │ └── timing.rep │ └── tb │ │ ├── seqs │ │ ├── hermes_router_seq_pkg.sv │ │ └── src │ │ │ ├── repeat_seq.sv │ │ │ ├── parallel_seq.sv │ │ │ └── hermes_router_seq_config.sv │ │ ├── tests │ │ ├── hermes_router_test_pkg.sv │ │ └── src │ │ │ ├── base_test.sv │ │ │ ├── parallel_test.sv │ │ │ ├── random_test.sv │ │ │ ├── sequential_test.sv │ │ │ ├── repeat_test.sv │ │ │ └── bottleneck_test.sv │ │ └── testbench │ │ └── top.sv └── vips │ ├── sc │ ├── readme.md │ ├── queue.cpp │ ├── packet.h.in │ ├── queue.h │ ├── router_algorithm │ │ ├── wf │ │ │ └── switchcontrol.h │ │ └── xy │ │ │ └── switchcontrol.h │ └── router_cc.h │ ├── hermes_pkg │ ├── hvl.f │ ├── src │ │ ├── hermes_driver_bfm.sv │ │ ├── hermes_monitor_bfm.sv │ │ ├── hermes_base_seq.sv │ │ ├── hermes_if.sv │ │ ├── hermes_base_driver.sv │ │ ├── hermes_slave_driver.sv │ │ ├── hermes_monitor.sv │ │ ├── hermes_master_driver.sv │ │ ├── hermes_typedefs.sv │ │ ├── hermes_agent.sv │ │ ├── hermes_agent_config.sv │ │ └── hermes_packet_t.sv │ ├── hermes_pkg_hdl.sv │ ├── docs │ │ ├── agent.png │ │ ├── slave_low_credit.png │ │ ├── master_buffer_full.png │ │ ├── master_cycles2flit.png │ │ ├── master_buffer_not_full.png │ │ └── readme.md │ ├── hdl.f │ └── hermes_pkg.sv │ └── hermes_router_env_pkg │ ├── docs │ ├── env.png │ └── readme.md │ ├── src │ ├── hermes_router_env_config.sv │ ├── hermes_router_coverage.sv │ └── hermes_router_env.sv │ └── hermes_router_env_pkg.sv ├── .gitignore ├── minimal ├── run.do ├── design.sv └── tb.sv ├── LICENSE ├── README.md └── uart └── uart.v /basic/tb.f: -------------------------------------------------------------------------------- 1 | dut_pkg.sv 2 | dut_if.sv 3 | top.sv 4 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/tb.f: -------------------------------------------------------------------------------- 1 | dut_pkg.sv 2 | dut_if.sv 3 | top.sv 4 | -------------------------------------------------------------------------------- /mult/tb/mult_div/tb.f: -------------------------------------------------------------------------------- 1 | dut_pkg.sv 2 | dut_if.sv 3 | top.sv 4 | -------------------------------------------------------------------------------- /mult/tb/booth_mult2/tb.f: -------------------------------------------------------------------------------- 1 | dut_pkg.sv 2 | dut_if.sv 3 | top.sv 4 | -------------------------------------------------------------------------------- /mult/tb/unsigned_multi/tb.f: -------------------------------------------------------------------------------- 1 | dut_pkg.sv 2 | dut_if.sv 3 | top.sv 4 | -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/hdl_v.f: -------------------------------------------------------------------------------- 1 | src/RouterCC_wrapper.sv 2 | -------------------------------------------------------------------------------- /noc-router/vips/sc/readme.md: -------------------------------------------------------------------------------- 1 | Future SystemC based tb. Saving few reused parts for later. 2 | -------------------------------------------------------------------------------- /noc-router/vips/sc/queue.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/sc/queue.cpp -------------------------------------------------------------------------------- /mult/dut/booth_mult/readme: -------------------------------------------------------------------------------- 1 | source from 2 | https://github.com/JonathonReinhart/boothmult/blob/master/vhdl/boothmult.vhdl 3 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/hvl.f: -------------------------------------------------------------------------------- 1 | $VIP_LIBRARY_HOME/hermes_pkg/hermes_pkg_hdl.sv 2 | $VIP_LIBRARY_HOME/hermes_pkg/hermes_pkg.sv 3 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_driver_bfm.sv: -------------------------------------------------------------------------------- 1 | interface hermes_driver_bfm(hermes_if bus); 2 | // TO Be DONE 3 | endinterface -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_monitor_bfm.sv: -------------------------------------------------------------------------------- 1 | interface hermes_monitor_bfm(hermes_if bus); 2 | // TO Be DONE 3 | endinterface -------------------------------------------------------------------------------- /mult/dut/booth_mult2/readme: -------------------------------------------------------------------------------- 1 | source from 2 | https://raw.githubusercontent.com/MorrisMA/Booth_Multipliers/master/Src/Booth_Multiplier.v 3 | -------------------------------------------------------------------------------- /noc-router/hermes_router/docs/tb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/docs/tb.png -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/hermes_pkg_hdl.sv: -------------------------------------------------------------------------------- 1 | package hermes_pkg_hdl; 2 | 3 | //`include "src/spi_typedefs_hdl.svh" 4 | 5 | endpackage 6 | -------------------------------------------------------------------------------- /mult/tb/common/mult_config.sv: -------------------------------------------------------------------------------- 1 | class mult_config extends uvm_object; 2 | rand int width; 3 | constraint wc {soft width == 32;} 4 | endclass 5 | -------------------------------------------------------------------------------- /noc-router/hermes_router/docs/router.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/docs/router.odp -------------------------------------------------------------------------------- /noc-router/hermes_router/docs/router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/docs/router.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.ucdb 2 | **/*.wlf 3 | **/*.vcd 4 | **/*.log 5 | **/*.vstf 6 | **/*.bin 7 | **/transcript 8 | **/work 9 | **/certe_dump.xml 10 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_pkg/docs/agent.png -------------------------------------------------------------------------------- /mult/dut/mult_div/readme: -------------------------------------------------------------------------------- 1 | source from 2 | https://github.com/alice820621/Verilog-Implementation-of-a-64-bit-Signed-Binary-Multiplier-Divider-Circuit/ 3 | 4 | -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/src/RouterCC.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/rtl/src/RouterCC.vhd -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/src/Hermes_buffer.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/rtl/src/Hermes_buffer.vhd -------------------------------------------------------------------------------- /noc-router/vips/hermes_router_env_pkg/docs/env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_router_env_pkg/docs/env.png -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/slave_low_credit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_pkg/docs/slave_low_credit.png -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/hdl_vhd.f: -------------------------------------------------------------------------------- 1 | src/HeMPS_defaults.vhd 2 | src/Hermes_buffer.vhd 3 | src/Hermes_crossbar.vhd 4 | src/Hermes_switchcontrol.vhd 5 | src/RouterCC.vhd 6 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/master_buffer_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_pkg/docs/master_buffer_full.png -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/master_cycles2flit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_pkg/docs/master_cycles2flit.png -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/src/Hermes_switchcontrol.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/hermes_router/rtl/src/Hermes_switchcontrol.vhd -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/master_buffer_not_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amamory-verification/uvm-basics/HEAD/noc-router/vips/hermes_pkg/docs/master_buffer_not_full.png -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/readme.md: -------------------------------------------------------------------------------- 1 | 2 | To execute the testbench, run in this dir: 3 | 4 | $ vsim -c -do run.do 5 | 6 | In the future there will be a Makefile version of it. 7 | -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/shutup.do: -------------------------------------------------------------------------------- 1 | set StdArithNoWarnings 1 2 | set StdNumNoWarnings 1 3 | set NumericStdNoWarnings 1 4 | run 0 ns; 5 | set StdArithNoWarnings 0 6 | set StdNumNoWarnings 0 7 | set NumericStdNoWarnings 0 -------------------------------------------------------------------------------- /minimal/run.do: -------------------------------------------------------------------------------- 1 | #if [file exists "work"] {vdel -all} 2 | #vlib work 3 | 4 | vlog design.sv 5 | vlog tb.sv 6 | 7 | vsim top +UVM_CONFIG_DB_TRACE 8 | set NoQuitOnFinish 1 9 | onbreak {resume} 10 | log /* -r 11 | run -all 12 | 13 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/hdl.f: -------------------------------------------------------------------------------- 1 | $VIP_LIBRARY_HOME/hermes_pkg/hermes_pkg_hdl.sv 2 | 3 | $VIP_LIBRARY_HOME/hermes_pkg/src/hermes_if.sv 4 | $VIP_LIBRARY_HOME/hermes_pkg/src/hermes_driver_bfm.sv 5 | $VIP_LIBRARY_HOME/hermes_pkg/src/hermes_monitor_bfm.sv 6 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/hdl_v.f: -------------------------------------------------------------------------------- 1 | /soft64/design-kits/stm/65nm-cmos065_536/CORE65GPSVT_5.1/behaviour/verilog/CORE65GPSVT.v 2 | /soft64/design-kits/stm/65nm-cmos065_536/CLOCK65GPSVT_3.1/behaviour/verilog/CLOCK65GPSVT.v 3 | src/layout/RouterCC.v 4 | src/RouterCC_wrapper.v 5 | -------------------------------------------------------------------------------- /basic/my_sequences_pkg.sv: -------------------------------------------------------------------------------- 1 | package my_sequences; 2 | 3 | 4 | class seq_of_commands extends uvm_sequence #(my_transaction); 5 | 6 | class read_modify_write extends uvm_sequence #(my_transaction); 7 | 8 | class my_sequence extends uvm_sequence #(my_transaction); 9 | 10 | 11 | endpackage 12 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/seqs/hermes_router_seq_pkg.sv: -------------------------------------------------------------------------------- 1 | package hermes_router_seq_pkg; 2 | 3 | import uvm_pkg::*; 4 | import hermes_pkg::*; 5 | 6 | `include "uvm_macros.svh" 7 | 8 | `include "src/hermes_router_seq_config.sv" 9 | 10 | `include "src/repeat_seq.sv" 11 | `include "src/parallel_seq.sv" 12 | 13 | endpackage 14 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_router_env_pkg/src/hermes_router_env_config.sv: -------------------------------------------------------------------------------- 1 | class hermes_router_env_config extends uvm_object; 2 | `uvm_object_utils(hermes_router_env_config) 3 | 4 | bit enable_coverage = 1; 5 | 6 | hermes_agent_config agent_cfg[hermes_pkg::NPORT]; 7 | 8 | 9 | function new( string name = "" ); 10 | super.new( name ); 11 | endfunction: new 12 | 13 | endclass : hermes_router_env_config 14 | -------------------------------------------------------------------------------- /mult/tb/common/dut_if_base.sv: -------------------------------------------------------------------------------- 1 | virtual class dut_if_base extends uvm_object; 2 | `uvm_object_utils(dut_if_base) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | pure virtual task reset_dut(); 9 | pure virtual task do_mult(input int iA, input int iB, output int oRes); 10 | pure virtual task get_mult(ref shortint oA, ref shortint oB, ref int oRes); 11 | pure virtual task do_nothing(); 12 | endclass : dut_if_base 13 | 14 | -------------------------------------------------------------------------------- /basic/my_sequence.sv: -------------------------------------------------------------------------------- 1 | class my_sequence extends uvm_sequence #(my_transaction); 2 | `uvm_object_utils(my_sequence) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | forever 10 | begin 11 | my_transaction tx; 12 | tx = my_transaction::type_id::create("tx"); 13 | start_item(tx); 14 | assert(tx.randomize()); 15 | finish_item(tx); 16 | end 17 | endtask: body 18 | 19 | endclass: my_sequence 20 | 21 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_router_env_pkg/hermes_router_env_pkg.sv: -------------------------------------------------------------------------------- 1 | package hermes_router_env_pkg; 2 | 3 | import uvm_pkg::*; 4 | import hermes_pkg::*; 5 | 6 | `include "uvm_macros.svh" 7 | 8 | // #### configuration classes ##### 9 | `include "src/hermes_router_env_config.sv" 10 | 11 | // ##### env modules ##### 12 | `include "src/hermes_router_coverage.sv" 13 | `include "src/hermes_router_scoreboard.sv" 14 | `include "src/hermes_router_env.sv" 15 | endpackage 16 | -------------------------------------------------------------------------------- /basic/my_test.sv: -------------------------------------------------------------------------------- 1 | class my_test extends uvm_test; 2 | 3 | my_dut_config dut_config_0; 4 | 5 | function void build_phase(uvm_phase phase); 6 | dut_config_0 = new(); 7 | 8 | if (!uvm_config_db #(virtual dut_if)::get (this,"", "dut_vi", dut_config_0.dut_vi) ) 9 | `uvm_fatal("MY_TEST", "No DUT_IF"); 10 | // other DUT configuration 11 | uvm_config_db# (my_dut_config)::set(this,"*", "dut_config", dut_config_0); 12 | 13 | endfunction : build_phase 14 | 15 | endclass: my_test 16 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_base_seq.sv: -------------------------------------------------------------------------------- 1 | /* 2 | Using the 'The Configurable Sequence' as described in 3 | 'Seven Separate Sequence Styles Speed Stimulus Scenarios' 4 | */ 5 | class hermes_base_seq extends uvm_sequence #(uvm_sequence_item); 6 | `uvm_object_utils(hermes_base_seq) 7 | 8 | packet_sequencer sequencer[hermes_pkg::NPORT]; 9 | 10 | function new(string name = "hermes_base_seq"); 11 | super.new(name); 12 | endfunction: new 13 | 14 | endclass: hermes_base_seq 15 | 16 | -------------------------------------------------------------------------------- /basic/dut.v: -------------------------------------------------------------------------------- 1 | module dut (clk, rst, cmd, data, dout ); 2 | parameter N=8; 3 | input clk; 4 | input rst; 5 | input cmd; 6 | input [N-1:0] data; 7 | output [N-1:0] dout; 8 | 9 | reg [N-1:0] count; 10 | 11 | always @(posedge clk or negedge rst) 12 | if (!rst) begin 13 | count <= 0; 14 | end else begin 15 | if (cmd == 1'b0) begin 16 | count <= data; 17 | end else begin 18 | count <= count + 1; 19 | end 20 | //$display("DUT count is %0d, %0d, %0d",count, data, cmd); 21 | end 22 | 23 | assign dout = count; 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /mult/tb/common/mult_basic_seq.sv: -------------------------------------------------------------------------------- 1 | class mult_basic_seq extends uvm_sequence #(mult_input_t); 2 | `uvm_object_utils(mult_basic_seq) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | mult_input_t tx; 10 | repeat(5) 11 | begin 12 | tx = mult_input_t::type_id::create("tx"); 13 | start_item(tx); 14 | assert(tx.randomize()); 15 | finish_item(tx); 16 | end 17 | //#200 // wait a little bit to check the last stimuli in the scoreboard 18 | endtask: body 19 | 20 | endclass: mult_basic_seq 21 | 22 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/hermes_router_test_pkg.sv: -------------------------------------------------------------------------------- 1 | package hermes_router_test_pkg; 2 | 3 | import uvm_pkg::*; 4 | import hermes_pkg::*; 5 | import hermes_router_env_pkg::*; 6 | import hermes_router_seq_pkg::*; 7 | 8 | `include "uvm_macros.svh" 9 | 10 | `include "src/base_test.sv" 11 | //`include "src/single_test.sv" 12 | `include "src/repeat_test.sv" 13 | `include "src/random_test.sv" 14 | `include "src/bottleneck_test.sv" 15 | `include "src/parallel_test.sv" 16 | `include "src/sequential_test.sv" 17 | 18 | endpackage 19 | -------------------------------------------------------------------------------- /basic/run.do: -------------------------------------------------------------------------------- 1 | 2 | if [file exists "work"] {vdel -all} 3 | vlib work 4 | 5 | # Comment out either the SystemVerilog or VHDL DUT. 6 | # There can be only one! 7 | 8 | #VHDL DUT 9 | #vcom -f dut.f 10 | 11 | # SystemVerilog DUT 12 | # vlog ../misc/tinyalu.sv 13 | 14 | vlog dut.v 15 | vlog -f tb.f 16 | 17 | vsim top -coverage +UVM_VERBOSITY=UVM_HIGH +UVM_TESTNAME=test2 18 | set NoQuitOnFinish 1 19 | onbreak {resume} 20 | log /* -r 21 | run -all 22 | 23 | coverage attribute -name TESTNAME -value test2 24 | coverage save test2.ucdb 25 | 26 | #vcover merge smoke_test.ucdb zeros_test.ucdb neg_test.ucdb 27 | vcover report test2.ucdb -cvg -details -------------------------------------------------------------------------------- /basic/commands_sequence.sv: -------------------------------------------------------------------------------- 1 | class seq_of_commands extends uvm_sequence #(my_transaction); 2 | `uvm_object_utils(seq_of_commands) 3 | 4 | rand int n; 5 | 6 | constraint how_many {n inside {[2:4]}; } 7 | 8 | 9 | function new(string name = ""); 10 | super.new(name); 11 | endfunction: new 12 | 13 | task body(); 14 | int count = 0; 15 | repeat(n) 16 | begin 17 | read_modify_write seq; 18 | seq = read_modify_write::type_id::create("rmw_seq"); 19 | //`uvm_info("msg", $sformatf("starting sequence - %0d", count), UVM_NONE) 20 | seq.start(m_sequencer, this); 21 | count++; 22 | end 23 | endtask: body 24 | 25 | endclass: seq_of_commands 26 | 27 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/power.rep: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Generated by: Genus(TM) Synthesis Solution 17.14-s037_1 3 | Generated on: Jan 26 2019 09:26:44 pm 4 | Module: RouterCC 5 | Operating conditions: _nominal_ 6 | Interconnect mode: global 7 | Area mode: physical library 8 | ============================================================ 9 | 10 | Leakage Dynamic Total 11 | Instance Cells Power(nW) Power(nW) Power(nW) 12 | -------------------------------------------------- 13 | RouterCC 3313 257085.873 6436152.168 6693238.040 14 | 15 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/top.sv: -------------------------------------------------------------------------------- 1 | module top; 2 | import uvm_pkg::*; 3 | import dut_pkg::*; 4 | 5 | bit clock; 6 | always #10 clock = ~clock; // clock generator 7 | 8 | dut_if dut_if(clock); 9 | boothmult #(.N(dut_pkg::DATA_WIDTH)) dut1(.clk(clock), .reset(dut_if.reset), 10 | .start(dut_if.start), .multiplier(dut_if.A), .multiplicand(dut_if.B), 11 | .done(dut_if.done), .product(dut_if.dout)); 12 | 13 | initial 14 | begin: blk 15 | //uvm_config_db#(virtual dut_if_base)::set(null, "*", "dut_vi", unsigned_dut_if.get_concrete_bfm()); 16 | uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vi", dut_if); 17 | 18 | run_test(); // vsim +UVM_TESTNAME=my_test 19 | end // blk 20 | 21 | endmodule: top -------------------------------------------------------------------------------- /mult/tb/booth_mult2/top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1 ns / 1 ns 2 | module top; 3 | import uvm_pkg::*; 4 | import dut_pkg::*; 5 | 6 | bit clock; 7 | always #10 clock = ~clock; // clock generator 8 | 9 | dut_if dut_if(clock); 10 | Booth_Multiplier #(.pN($clog2(dut_pkg::DATA_WIDTH))) dut1(.Clk(clock), .Rst(dut_if.reset), 11 | .Ld(dut_if.start), .M(dut_if.A), .R(dut_if.B), 12 | .Valid(dut_if.done), .P(dut_if.dout)); 13 | 14 | initial 15 | begin: blk 16 | //uvm_config_db#(virtual dut_if_base)::set(null, "*", "dut_vi", unsigned_dut_if.get_concrete_bfm()); 17 | uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vi", dut_if); 18 | 19 | run_test(); // vsim +UVM_TESTNAME=my_test 20 | end // blk 21 | 22 | endmodule: top -------------------------------------------------------------------------------- /mult/tb/common/neg_test.sv: -------------------------------------------------------------------------------- 1 | class neg_test extends uvm_test; 2 | `uvm_component_utils(neg_test) 3 | 4 | mult_env env_h; 5 | 6 | function new (string name, uvm_component parent); 7 | super.new(name,parent); 8 | endfunction : new 9 | 10 | function void build_phase(uvm_phase phase); 11 | env_h = mult_env::type_id::create("env", this); 12 | `uvm_info("msg", "Building Environment DONE!", UVM_LOW) 13 | endfunction: build_phase 14 | 15 | task run_phase(uvm_phase phase); 16 | mult_neg_seq seq; 17 | seq = mult_neg_seq::type_id::create("seq"); 18 | phase.raise_objection(this); 19 | seq.start(env_h.agent_h.sequencer_h); 20 | phase.drop_objection(this); 21 | endtask 22 | 23 | endclass: neg_test 24 | -------------------------------------------------------------------------------- /basic/dut_if.sv: -------------------------------------------------------------------------------- 1 | interface dut_if; 2 | 3 | logic clk, rst; 4 | logic cmd; 5 | logic unsigned [31:0] data; 6 | logic unsigned [31:0] dout; 7 | 8 | 9 | task reset_dut(); 10 | rst = 1'b0; 11 | @(negedge clk); 12 | @(negedge clk); 13 | rst = 1'b1; 14 | endtask : reset_dut 15 | 16 | task do_dut(input bit iCmd, input logic [31:0] iData, output logic [31:0] oDout); 17 | @(posedge clk); 18 | cmd = iCmd; 19 | data = iData; 20 | @(posedge clk); 21 | oDout = dout; 22 | endtask : do_dut 23 | 24 | initial begin 25 | clk = 0; 26 | fork 27 | forever begin 28 | #10; 29 | clk = ~clk; 30 | end 31 | join_none 32 | end 33 | 34 | endinterface : dut_if 35 | -------------------------------------------------------------------------------- /mult/tb/mult_div/top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | 3 | module top; 4 | import uvm_pkg::*; 5 | import dut_pkg::*; 6 | 7 | bit clock; 8 | always #10 clock = ~clock; // clock generator 9 | 10 | dut_if dut_if(clock); 11 | mudi64 dut1(.clock(clock), .reset(dut_if.reset), 12 | .start(!dut_if.start), .opera1(dut_if.A), .opera2({32'h00000000 , dut_if.B}), .muordi(1'b0), 13 | .valid(dut_if.done), .result(dut_if.dout)); 14 | 15 | initial 16 | begin: blk 17 | //uvm_config_db#(virtual dut_if_base)::set(null, "*", "dut_vi", unsigned_dut_if.get_concrete_bfm()); 18 | uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vi", dut_if); 19 | 20 | run_test(); // vsim +UVM_TESTNAME=my_test 21 | end // blk 22 | 23 | endmodule: top -------------------------------------------------------------------------------- /mult/tb/unsigned_multi/top.sv: -------------------------------------------------------------------------------- 1 | module top; 2 | import uvm_pkg::*; 3 | import dut_pkg::*; 4 | 5 | bit clock; 6 | always #10 clock = ~clock; // clock generator 7 | 8 | dut_if unsigned_dut_if(clock); 9 | mult_serial dut1(.clock(clock), .reset(unsigned_dut_if.reset), 10 | .start(unsigned_dut_if.start), .A(unsigned_dut_if.A), .B(unsigned_dut_if.B), 11 | .done(unsigned_dut_if.done), .dout(unsigned_dut_if.dout)); 12 | 13 | initial 14 | begin: blk 15 | //uvm_config_db#(virtual dut_if_base)::set(null, "*", "dut_vi", unsigned_dut_if.get_concrete_bfm()); 16 | uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vi", unsigned_dut_if); 17 | 18 | run_test(); // vsim +UVM_TESTNAME=my_test 19 | end // blk 20 | 21 | endmodule: top -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/hermes_pkg.sv: -------------------------------------------------------------------------------- 1 | package hermes_pkg; 2 | 3 | import uvm_pkg::*; 4 | import hermes_pkg_hdl::*; 5 | 6 | `include "uvm_macros.svh" 7 | 8 | // ##### parameters ##### 9 | `include "src/hermes_typedefs.sv" 10 | 11 | // ##### transactions / seq_item ##### 12 | `include "src/hermes_packet_t.sv" 13 | 14 | // #### configuration classes ##### 15 | //`include "seq_config.sv" 16 | `include "src/hermes_agent_config.sv" 17 | 18 | // #### sequences ##### 19 | `include "src/hermes_base_seq.sv" 20 | 21 | // ##### agent modules ##### 22 | `include "src/hermes_base_driver.sv" 23 | `include "src/hermes_slave_driver.sv" 24 | `include "src/hermes_master_driver.sv" 25 | `include "src/hermes_monitor.sv" 26 | `include "src/hermes_agent.sv" 27 | endpackage 28 | -------------------------------------------------------------------------------- /basic/my_param_container.sv: -------------------------------------------------------------------------------- 1 | // The param_containter class hold the values 2 | // for all parameters in the design 3 | // from https://verificationacademy.com/verification-horizons/june-2012-volume-8-issue-2/Relieving-the-Parameterized-Coverage-Headache 4 | class my_param_container extends uvm_object; 5 | `uvm_object_utils(my_param_container) 6 | 7 | // Data members to hold parameter values 8 | // Each parameter is set to a default value 9 | // these values are overwritten in the 10 | // parameterized test base when the object 11 | // is created. 12 | int data_width = 31; 13 | int max_val = 20000; 14 | // other parameter values 15 | 16 | // constructor, etc. 17 | 18 | function new(string name = ""); 19 | super.new(name); 20 | endfunction 21 | 22 | endclass : my_param_container -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/area.rep: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Generated by: Genus(TM) Synthesis Solution 17.14-s037_1 3 | Generated on: Jan 26 2019 09:26:44 pm 4 | Module: RouterCC 5 | Technology libraries: CORE65GPSVT 6 | CLOCK65GPSVT 7 | IO65LPHVT_SF_1V8_50A_7M4X0Y2Z 8 | physical_cells 9 | Operating conditions: _nominal_ 10 | Interconnect mode: global 11 | Area mode: physical library 12 | ============================================================ 13 | 14 | Instance Module Cells Cell Area Net Area Total Area 15 | --------------------------------------------------------- 16 | RouterCC 3313 23269 8657 31926 17 | -------------------------------------------------------------------------------- /basic/test1.sv: -------------------------------------------------------------------------------- 1 | class test1 extends uvm_test; 2 | `uvm_component_utils(test1) 3 | 4 | my_env my_env_h; 5 | 6 | function new (string name, uvm_component parent); 7 | super.new(name,parent); 8 | endfunction : new 9 | 10 | function void build_phase(uvm_phase phase); 11 | my_env_h = my_env::type_id::create("my_env", this); 12 | `uvm_info("msg", "Building Environment DONE!", UVM_NONE) 13 | endfunction: build_phase 14 | 15 | task run_phase(uvm_phase phase); 16 | read_modify_write seq; 17 | `uvm_info("msg", "Running TEST1", UVM_NONE) 18 | seq = read_modify_write::type_id::create("seq"); 19 | phase.raise_objection(this); 20 | `uvm_info("msg", "Starting SEQ", UVM_NONE) 21 | seq.start(my_env_h.my_agent_h.my_sequencer_h); 22 | `uvm_info("msg", "SEQ STARTED!!!", UVM_NONE) 23 | phase.drop_objection(this); 24 | endtask 25 | 26 | endclass: test1 27 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/constraints.sdc: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | ## Logical / Physical synthesis constraints ## 3 | ## GAPH/FACIN/PUCRS ## 4 | ############################################################## 5 | 6 | ## DEFINE VARS 7 | set sdc_version 1.5 8 | set_load_unit -picofarads 1 9 | 10 | create_clock -name {clock} -period 2.0 [get_ports {clock}] 11 | 12 | set_false_path -from [get_ports {reset}] 13 | 14 | ## INPUTS 15 | set_input_delay -clock clock -max 0.2 [all_inputs] 16 | set_input_transition -min -rise 0.003 [all_inputs] 17 | set_input_transition -max -rise 0.16 [all_inputs] 18 | set_input_transition -min -fall 0.003 [all_inputs] 19 | set_input_transition -max -fall 0.16 [all_inputs] 20 | 21 | ## OUTPUTS 22 | set_load -min 0.0014 [all_outputs] 23 | set_load -max 0.32 [all_outputs] 24 | -------------------------------------------------------------------------------- /mult/tb/common/smoke_test.sv: -------------------------------------------------------------------------------- 1 | class smoke_test extends uvm_test; 2 | `uvm_component_utils(smoke_test) 3 | 4 | mult_env env_h; 5 | 6 | function new (string name, uvm_component parent); 7 | super.new(name,parent); 8 | endfunction : new 9 | 10 | function void build_phase(uvm_phase phase); 11 | env_h = mult_env::type_id::create("env", this); 12 | `uvm_info("msg", "Building Environment DONE!", UVM_LOW) 13 | endfunction: build_phase 14 | 15 | task run_phase(uvm_phase phase); 16 | mult_basic_seq seq; 17 | //`uvm_info("msg", "Running TEST1", UVM_LOW) 18 | seq = mult_basic_seq::type_id::create("seq"); 19 | phase.raise_objection(this); 20 | //`uvm_info("msg", "Starting SEQ", UVM_LOW) 21 | seq.start(env_h.agent_h.sequencer_h); 22 | //`uvm_info("msg", "SEQ STARTED!!!", UVM_LOW) 23 | phase.drop_objection(this); 24 | endtask 25 | 26 | endclass: smoke_test 27 | -------------------------------------------------------------------------------- /basic/my_transaction.sv: -------------------------------------------------------------------------------- 1 | class my_transaction extends uvm_sequence_item; 2 | `uvm_object_utils(my_transaction) 3 | 4 | rand cmd_t cmd; 5 | rand logic unsigned [dut_pkg::DATA_WIDTH-1:0] data; 6 | logic unsigned [dut_pkg::DATA_WIDTH-1:0] dout; 7 | 8 | constraint c_data { data >=0 ; data < dut_pkg::MAX_RAND_VAL; } 9 | 10 | function new(string name = ""); 11 | //my_param_container params; 12 | //string data_str; 13 | super.new(name); 14 | //if (!uvm_config_db #(my_param_container)::get(this, "","my_param",params) ) 15 | // `uvm_fatal("my_transaction", "No config"); 16 | //data_str = $psprintf("data width: %0d, max_val: %0d",params.data_width, params.max_val); 17 | //`uvm_info (" ==== TRANS ===== ", {"PASS: ", data_str}, UVM_HIGH) 18 | endfunction: new 19 | 20 | endclass: my_transaction 21 | 22 | typedef uvm_sequencer #(my_transaction) my_sequencer; 23 | 24 | -------------------------------------------------------------------------------- /basic/test2.sv: -------------------------------------------------------------------------------- 1 | class test2 extends uvm_test; 2 | `uvm_component_utils(test2) 3 | 4 | my_env my_env_h; 5 | 6 | function new (string name, uvm_component parent); 7 | super.new(name,parent); 8 | endfunction : new 9 | 10 | function void build_phase(uvm_phase phase); 11 | my_env_h = my_env::type_id::create("my_env", this); 12 | `uvm_info("msg", "Building Environment DONE!", UVM_NONE) 13 | endfunction: build_phase 14 | 15 | task run_phase(uvm_phase phase); 16 | seq_of_commands seq; 17 | seq = seq_of_commands::type_id::create("comm_seq"); 18 | seq.how_many.constraint_mode(0); // turn internal constraint off and replace it by the following constraint 19 | assert (seq.randomize() with {seq.n > 5 && seq.n < 10;}); 20 | phase.raise_objection(this); 21 | seq.start(my_env_h.my_agent_h.my_sequencer_h); 22 | phase.drop_objection(this); 23 | endtask 24 | endclass: test2 25 | -------------------------------------------------------------------------------- /basic/my_component.sv: -------------------------------------------------------------------------------- 1 | class my_component extends uvm_component; 2 | `uvm_component_utils(my_component); 3 | 4 | virtual dut_if dut_if_h; 5 | 6 | my_sequencer my_sequencer_h; 7 | my_driver my_driver_h; 8 | my_monitor my_monitor_h; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction: new 13 | 14 | function void build_phase(uvm_phase phase); 15 | // ... 16 | endfunction: build_phase 17 | 18 | function void connect_phase(uvm_phase phase); 19 | // ... 20 | endfunction: connect_phase 21 | 22 | 23 | function void start_of_simulation; 24 | 25 | task run_phase(uvm_phase phase); 26 | phase.raise_objection(this); 27 | #10 dut_vi.data = 0; 28 | #10 dut_vi.data = 1; 29 | #10 phase.drop_objection(this); 30 | endtask: run_phase 31 | 32 | task report_phase(uvm_phase phase); 33 | 34 | endtask: report_phase 35 | 36 | endclass: my_component 37 | -------------------------------------------------------------------------------- /mult/tb/common/mult_one_seq.sv: -------------------------------------------------------------------------------- 1 | class mult_one_seq extends uvm_sequence #(mult_input_t); 2 | `uvm_object_utils(mult_one_seq) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | mult_input_t tx; 10 | // a == 1 11 | repeat(10) begin 12 | tx = mult_input_t::type_id::create("tx"); 13 | start_item(tx); 14 | assert(tx.randomize() with {tx.A == 1;}); 15 | finish_item(tx); 16 | end 17 | // b == 1 18 | repeat(10) begin 19 | tx = mult_input_t::type_id::create("tx"); 20 | start_item(tx); 21 | assert(tx.randomize() with {tx.B == 1;}); 22 | finish_item(tx); 23 | end 24 | // a == b == 1 25 | repeat(1) begin 26 | tx = mult_input_t::type_id::create("tx"); 27 | start_item(tx); 28 | assert(tx.randomize() with {tx.A == 1; tx.B == 1;}); 29 | finish_item(tx); 30 | end 31 | endtask: body 32 | 33 | endclass: mult_one_seq 34 | 35 | -------------------------------------------------------------------------------- /basic/top.sv: -------------------------------------------------------------------------------- 1 | module top; 2 | import uvm_pkg::*; 3 | import dut_pkg::*; 4 | 5 | 6 | dut_if dut_if1(); 7 | dut #(.N(dut_pkg::DATA_WIDTH)) dut1(.clk(dut_if1.clk), .rst(dut_if1.rst), .cmd(dut_if1.cmd), 8 | .data(dut_if1.data[dut_pkg::DATA_WIDTH-1:0]), 9 | .dout(dut_if1.dout[dut_pkg::DATA_WIDTH-1:0])); 10 | 11 | initial 12 | begin: blk 13 | uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vi", dut_if1); 14 | 15 | 16 | // testing range of the main configuration parameters 17 | data_width_check: assert (dut_pkg::DATA_WIDTH <= 31) $display ("parameter DATA_WIDTH is OK"); 18 | else $fatal("INVALID parameter DATA_WIDTH"); 19 | 20 | max_val_check: assert (dut_pkg::MAX_RAND_VAL <= 2**dut_pkg::DATA_WIDTH-1) $display ("parameter MAX_RAND_VAL is OK"); 21 | else $fatal("INVALID parameter MAX_RAND_VAL"); 22 | 23 | //run_test("my_test"); 24 | run_test(); // vsim +UVM_TESTNAME=my_test 25 | end // blk 26 | 27 | endmodule: top -------------------------------------------------------------------------------- /minimal/design.sv: -------------------------------------------------------------------------------- 1 | // Simple adder/subtractor module 2 | module ADD_SUB( 3 | input clk, 4 | input [7:0] a0, 5 | input [7:0] b0, 6 | // if this is 1, add; else subtract 7 | input doAdd0, 8 | output reg [8:0] result0 9 | ); 10 | 11 | always @ (posedge clk) 12 | begin 13 | if (doAdd0) 14 | result0 <= a0 + b0; 15 | else 16 | result0 <= a0 - b0; 17 | end 18 | 19 | endmodule: ADD_SUB 20 | 21 | //--------------------------------------- 22 | // Interface for the adder/subtractor DUT 23 | //--------------------------------------- 24 | interface add_sub_if( input bit clk ); 25 | 26 | bit [7:0] a; 27 | bit [7:0] b; 28 | bit doAdd; 29 | bit [8:0] result; 30 | 31 | clocking cb @(posedge clk); 32 | output a; 33 | output b; 34 | output doAdd; 35 | input result; 36 | endclocking // cb 37 | 38 | endinterface: add_sub_if 39 | 40 | -------------------------------------------------------------------------------- /basic/read_modify_write_sequence.sv: -------------------------------------------------------------------------------- 1 | class read_modify_write extends uvm_sequence #(my_transaction); 2 | `uvm_object_utils(read_modify_write) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | 10 | begin 11 | my_transaction tx; 12 | int d; 13 | tx = my_transaction::type_id::create("tx"); 14 | start_item(tx); 15 | //`uvm_info("msg", "read transaction started", UVM_LOW) 16 | assert(tx.randomize()); 17 | tx.cmd = READ; 18 | finish_item(tx); 19 | d = tx.data; 20 | ++d; 21 | 22 | tx = my_transaction::type_id::create("tx"); 23 | start_item(tx); 24 | //`uvm_info("msg", "write transaction started", UVM_LOW) 25 | assert(tx.randomize() 26 | with {cmd == WRITE; data == d; }); 27 | finish_item(tx); 28 | //`uvm_info("msg", "sequence read_modify_write finished", UVM_LOW) 29 | end 30 | endtask: body 31 | 32 | endclass: read_modify_write 33 | 34 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_if.sv: -------------------------------------------------------------------------------- 1 | interface hermes_if (input bit clock, input bit reset); 2 | import hermes_pkg::*; 3 | 4 | // bit reset; 5 | 6 | /* 7 | Each of the five interfaces has the following ports: 8 | -- PORT 9 | -- _____________ 10 | -- RX ->| |-> TX 11 | -- DATA_IN ->| |-> DATA_OUT 12 | -- CLOCK_RX ->| |-> CLOCK_TX 13 | -- CREDIT_O <-| |<- CREDIT_I 14 | -- | | 15 | _____________ 16 | */ 17 | 18 | logic clk, avail, credit; 19 | logic [15:0] data; 20 | 21 | modport datain ( 22 | input clk, avail, data, 23 | output credit 24 | ); 25 | modport dataout ( 26 | output clk, avail, data, 27 | input credit 28 | ); 29 | 30 | endinterface : hermes_if 31 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_base_driver.sv: -------------------------------------------------------------------------------- 1 | // hermes base driver 2 | class hermes_base_driver extends uvm_driver #(hermes_packet_t); 3 | `uvm_component_utils(hermes_base_driver); 4 | 5 | uvm_analysis_port #(hermes_packet_t) aport; // used to send the incomming packet to the sb 6 | 7 | virtual hermes_if dut_vi; 8 | bit [3:0] port; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name, parent); 12 | endfunction : new 13 | 14 | function void build_phase(uvm_phase phase); 15 | aport = new("aport", this); 16 | 17 | // print config_db 18 | //print_config(); 19 | 20 | if (!uvm_config_db #(bit [3:0])::get (this,"", "port", port) ) 21 | `uvm_fatal("driver", "No port"); 22 | `uvm_info("driver", $sformatf("PORT number: %0d",port), UVM_HIGH) 23 | 24 | if(!uvm_config_db#(virtual hermes_if)::get (this,"", "if", dut_vi)) 25 | `uvm_fatal("driver", "No if"); 26 | 27 | endfunction : build_phase 28 | 29 | endclass: hermes_base_driver -------------------------------------------------------------------------------- /basic/my_driver.sv: -------------------------------------------------------------------------------- 1 | class my_driver extends uvm_driver #(my_transaction); 2 | `uvm_component_utils(my_driver); 3 | 4 | virtual dut_if dut_vi; 5 | 6 | function new(string name, uvm_component parent); 7 | super.new(name, parent); 8 | endfunction : new 9 | 10 | function void build_phase(uvm_phase phase); 11 | `uvm_info("msg", "Building DRIVER", UVM_NONE) 12 | 13 | if (!uvm_config_db #(virtual dut_if)::get (null,"*", "dut_vi", dut_vi) ) 14 | `uvm_fatal("my_driver", "No DUT_IF"); 15 | `uvm_info("msg", "DRIVER Done!!!", UVM_NONE) 16 | endfunction : build_phase 17 | 18 | task run_phase(uvm_phase phase); 19 | my_transaction tx; 20 | string data_str; 21 | dut_vi.reset_dut(); 22 | forever 23 | begin 24 | seq_item_port.get_next_item(tx); 25 | dut_vi.do_dut(tx.cmd,tx.data,tx.dout); 26 | data_str = $psprintf("data = %0d, dout = %0d", tx.data, tx.dout); 27 | `uvm_info ("DRIVER", {"PASS: ", data_str}, UVM_HIGH) 28 | seq_item_port.item_done(); 29 | end 30 | endtask: run_phase 31 | 32 | endclass: my_driver 33 | -------------------------------------------------------------------------------- /basic/my_monitor.sv: -------------------------------------------------------------------------------- 1 | class my_monitor extends uvm_monitor; 2 | `uvm_component_utils(my_monitor); 3 | 4 | uvm_analysis_port #(my_transaction) aport; 5 | virtual dut_if dut_vi; 6 | 7 | function new(string name, uvm_component parent); 8 | super.new(name,parent); 9 | endfunction: new 10 | 11 | function void build_phase(uvm_phase phase); 12 | `uvm_info("msg", "Building MONITOR", UVM_NONE) 13 | aport = new("aport", this); 14 | if (!uvm_config_db #(virtual dut_if)::get (null,"*", "dut_vi", dut_vi) ) 15 | `uvm_fatal("my_monitor", "No DUT_IF"); 16 | `uvm_info("msg", "MONITOR Done !!!", UVM_NONE) 17 | endfunction: build_phase 18 | 19 | task run_phase(uvm_phase phase); 20 | my_transaction tx; 21 | forever 22 | begin 23 | @(posedge dut_vi.clk); 24 | tx = my_transaction::type_id::create("tx"); 25 | $cast(tx.cmd, dut_vi.cmd); 26 | tx.data = dut_vi.data; 27 | aport.write(tx); 28 | //`uvm_info("msg", "New transaction", UVM_HIGH) 29 | end 30 | endtask: run_phase 31 | 32 | endclass : my_monitor 33 | -------------------------------------------------------------------------------- /mult/tb/common/mult_env.sv: -------------------------------------------------------------------------------- 1 | class mult_env extends uvm_env; 2 | `uvm_component_utils(mult_env); 3 | 4 | mult_agent agent_h; 5 | mult_coverage coverage_h; 6 | mult_scoreboard scoreboard_h; 7 | 8 | function new(string name, uvm_component parent); 9 | super.new(name,parent); 10 | endfunction: new 11 | 12 | function void build_phase(uvm_phase phase); 13 | `uvm_info("msg", "Building ENV", UVM_NONE) 14 | agent_h = mult_agent::type_id::create("agent", this); 15 | coverage_h = mult_coverage::type_id::create("coverage", this); 16 | scoreboard_h = mult_scoreboard::type_id::create("scoreboard", this); 17 | `uvm_info("msg", "ENV Done !", UVM_NONE) 18 | endfunction: build_phase 19 | 20 | function void connect_phase(uvm_phase phase); 21 | `uvm_info("msg", "Connecting ENV", UVM_NONE) 22 | agent_h.aport.connect(coverage_h.analysis_export); 23 | agent_h.aport.connect(scoreboard_h.analysis_export); 24 | `uvm_info("msg", "Connecting ENV Done !", UVM_NONE) 25 | endfunction: connect_phase 26 | 27 | endclass: mult_env 28 | -------------------------------------------------------------------------------- /basic/my_subscriber.sv: -------------------------------------------------------------------------------- 1 | class my_subscriber extends uvm_subscriber #(my_transaction); 2 | `uvm_component_utils(my_subscriber); 3 | 4 | cmd_t cmd; 5 | logic unsigned [31:0] data; 6 | 7 | covergroup cover_bus (int max_val); 8 | coverpoint cmd; 9 | coverpoint data { bins d[16] = {[0:max_val]};} 10 | endgroup: cover_bus 11 | 12 | function void write(my_transaction t); 13 | cmd = t.cmd; 14 | data = t.data; 15 | //`uvm_info("msg", "Transaction Received", UVM_HIGH) 16 | // UVM_NONE - msg always apper 17 | // UVM_LOW, UVM_MEDIUM, UVM_HIGH 18 | // UVM_FULL - usualyy filtered out 19 | // +UVM_VERBOSITY=UVM_LOW 20 | cover_bus.sample(); 21 | endfunction: write 22 | 23 | function new(string name, uvm_component parent); 24 | my_param_container params; 25 | super.new(name,parent); 26 | if (!uvm_config_db #(my_param_container)::get(this, "","my_param",params) ) 27 | `uvm_fatal("my_subscriber", "No config"); 28 | cover_bus = new(2**params.data_width-1); 29 | endfunction: new 30 | 31 | 32 | endclass: my_subscriber 33 | -------------------------------------------------------------------------------- /mult/tb/common/mult_driver.sv: -------------------------------------------------------------------------------- 1 | class mult_driver extends uvm_driver #(mult_input_t); 2 | `uvm_component_utils(mult_driver); 3 | 4 | //virtual dut_if_base dut_vi; 5 | virtual dut_if dut_vi; 6 | 7 | function new(string name, uvm_component parent); 8 | super.new(name, parent); 9 | endfunction : new 10 | 11 | function void build_phase(uvm_phase phase); 12 | `uvm_info("msg", "Building DRIVER", UVM_NONE) 13 | 14 | //if (!uvm_config_db #(virtual dut_if_base)::get (null,"*", "dut_vi", dut_vi) ) 15 | if (!uvm_config_db #(virtual dut_if)::get (null,"*", "dut_vi", dut_vi) ) 16 | `uvm_fatal("my_driver", "No DUT_IF"); 17 | `uvm_info("msg", "DRIVER Done!!!", UVM_NONE) 18 | endfunction : build_phase 19 | 20 | task run_phase(uvm_phase phase); 21 | mult_input_t tx; 22 | dut_vi.reset_dut(); 23 | 24 | forever 25 | begin 26 | seq_item_port.get_next_item(tx); 27 | dut_vi.do_mult(tx.A, tx.B, tx.dout); 28 | seq_item_port.item_done(); 29 | //`uvm_info("msg", "transaction done !", UVM_HIGH) 30 | end 31 | endtask: run_phase 32 | 33 | endclass: mult_driver 34 | -------------------------------------------------------------------------------- /mult/tb/common/mult_scoreboard.sv: -------------------------------------------------------------------------------- 1 | class mult_scoreboard extends uvm_subscriber #(mult_input_t); 2 | `uvm_component_utils(mult_scoreboard); 3 | 4 | function new(string name, uvm_component parent); 5 | super.new(name,parent); 6 | endfunction: new 7 | 8 | function void write(mult_input_t t); 9 | logic [2*dut_pkg::DATA_WIDTH-1:0] expected_output; 10 | string data_str, expected_output_str; 11 | expected_output = t.A * t.B; 12 | 13 | // generates the correct output format (signed or unsigned) for the expected ouput value 14 | if (dut_pkg::SIGNED_MULT == 1'b1) 15 | expected_output_str = $psprintf("%0d", $signed(expected_output)); 16 | else 17 | expected_output_str = $psprintf("%0d", expected_output); 18 | data_str = $psprintf("%0d x %0d = %0d (actual); %s (expected)",t.A, t.B, t.dout, expected_output_str); 19 | 20 | if (expected_output != t.dout) 21 | `uvm_error("SELF CHECKER", {"FAIL: ",data_str}) 22 | else 23 | `uvm_info ("SELF CHECKER", {"PASS: ", data_str}, UVM_HIGH) 24 | endfunction: write 25 | 26 | endclass: mult_scoreboard -------------------------------------------------------------------------------- /mult/tb/common/mult_coverage_unsigned.sv: -------------------------------------------------------------------------------- 1 | class mult_coverage extends uvm_subscriber #(mult_input_t); 2 | `uvm_component_utils(mult_coverage); 3 | 4 | logic [dut_pkg::DATA_WIDTH-1:0] A,B; 5 | logic [2*dut_pkg::DATA_WIDTH-1:0] result; 6 | 7 | covergroup range_value; 8 | a_leg: coverpoint A { 9 | bins zero = {0}; // zero 10 | bins plus1 = {1}; // 1 11 | bins pos = {[2:$]}; // positive values 12 | } 13 | b_leg: coverpoint B { 14 | bins zero = {0}; // zero 15 | bins plus1 = {1}; // 1 16 | bins pos = {[2:$]}; // positive values 17 | } 18 | 19 | a_b: cross a_leg, b_leg; 20 | endgroup: range_value 21 | 22 | 23 | function void write(mult_input_t t); 24 | result = t.dout; 25 | A = t.A; 26 | B = t.B; 27 | //`uvm_info("msg", "Transaction Received", UVM_HIGH) 28 | range_value.sample(); 29 | endfunction: write 30 | 31 | function new(string name, uvm_component parent); 32 | super.new(name,parent); 33 | range_value = new(); 34 | endfunction: new 35 | 36 | 37 | endclass: mult_coverage -------------------------------------------------------------------------------- /basic/my_env.sv: -------------------------------------------------------------------------------- 1 | class my_env extends uvm_env; 2 | `uvm_component_utils(my_env); 3 | 4 | my_agent my_agent_h; 5 | my_subscriber my_subscriber_h; 6 | my_param_container my_param_h; 7 | 8 | function new(string name, uvm_component parent); 9 | super.new(name,parent); 10 | endfunction: new 11 | 12 | 13 | function void build_phase(uvm_phase phase); 14 | `uvm_info("msg", "Building ENV", UVM_NONE) 15 | 16 | my_param_h = my_param_container::type_id::create("my_param"); 17 | uvm_config_db#(my_param_container)::set(null, "*", "my_param", my_param_h); 18 | 19 | my_agent_h = my_agent::type_id::create("my_agent", this); 20 | my_subscriber_h = my_subscriber::type_id::create("my_subscriber", this); 21 | `uvm_info("msg", "ENV Done !", UVM_NONE) 22 | endfunction: build_phase 23 | 24 | function void connect_phase(uvm_phase phase); 25 | `uvm_info("msg", "Connecting ENV", UVM_NONE) 26 | my_agent_h.aport.connect(my_subscriber_h.analysis_export); 27 | `uvm_info("msg", "Connecting ENV Done !", UVM_NONE) 28 | endfunction: connect_phase 29 | 30 | endclass: my_env 31 | -------------------------------------------------------------------------------- /mult/tb/common/mult_monitor.sv: -------------------------------------------------------------------------------- 1 | class mult_monitor extends uvm_monitor; 2 | `uvm_component_utils(mult_monitor); 3 | 4 | uvm_analysis_port #(mult_input_t) aport; 5 | //virtual dut_if_base dut_vi; 6 | virtual dut_if dut_vi; 7 | 8 | function new(string name, uvm_component parent); 9 | super.new(name,parent); 10 | endfunction: new 11 | 12 | function void build_phase(uvm_phase phase); 13 | `uvm_info("msg", "Building MONITOR", UVM_NONE) 14 | aport = new("aport", this); 15 | //if (!uvm_config_db #(virtual dut_if_base)::get (null,"*", "dut_vi", dut_vi) ) 16 | if (!uvm_config_db #(virtual dut_if)::get (null,"*", "dut_vi", dut_vi) ) 17 | `uvm_fatal("my_monitor", "No DUT_IF"); 18 | `uvm_info("msg", "MONITOR Done !!!", UVM_NONE) 19 | endfunction: build_phase 20 | 21 | task run_phase(uvm_phase phase); 22 | forever 23 | begin 24 | mult_input_t tx; 25 | tx = mult_input_t::type_id::create("tx"); 26 | dut_vi.get_mult(tx.A, tx.B, tx.dout); 27 | aport.write(tx); 28 | //`uvm_info("msg", "New transaction", UVM_HIGH) 29 | end 30 | endtask: run_phase 31 | 32 | endclass : mult_monitor 33 | -------------------------------------------------------------------------------- /basic/dut_pkg.sv: -------------------------------------------------------------------------------- 1 | package dut_pkg; 2 | import uvm_pkg::*; 3 | `include "uvm_macros.svh" 4 | 5 | typedef enum bit {READ = 1'b0, WRITE = 1'b1} cmd_t; 6 | 7 | // 1st and simplest method to pass parameter. used by my_transaction 8 | parameter MAX_RAND_VAL = 20000; 9 | parameter DATA_WIDTH = 16; 10 | 11 | `include "my_transaction.sv" 12 | // 2nd method to pass parameter. the env creates the classe and set with uvm_config_db. the subscriber gets the config 13 | // this approach based on uvm_config_db has performance issues, so it is better to avoid get config from frequently acesses class like seq_item 14 | `include "my_param_container.sv" 15 | 16 | 17 | `include "read_modify_write_sequence.sv" 18 | `include "my_sequence.sv" 19 | //`include "my_sequences.sv" 20 | `include "commands_sequence.sv" 21 | 22 | 23 | `include "my_subscriber.sv" 24 | `include "my_driver.sv" 25 | `include "my_monitor.sv" 26 | `include "my_agent.sv" 27 | //`include "my_component.sv" 28 | 29 | `include "my_env.sv" 30 | 31 | //`include "my_test.sv" 32 | `include "test1.sv" 33 | `include "test2.sv" 34 | 35 | 36 | endpackage : dut_pkg -------------------------------------------------------------------------------- /mult/tb/unsigned_multi/mult_input_t.sv: -------------------------------------------------------------------------------- 1 | class mult_input_t extends uvm_sequence_item; 2 | `uvm_object_utils(mult_input_t) 3 | 4 | rand logic [dut_pkg::DATA_WIDTH-1:0] A; 5 | rand logic [dut_pkg::DATA_WIDTH-1:0] B; 6 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | 8 | /* 9 | // TODO I have no ideia why this code below does not replace the code above. 10 | // I would not need to replicate the mult_input_t if it worked as expected 11 | `ifdef SIGNED_MULT == 1'b1 12 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 13 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 14 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 15 | `else 16 | rand logic [dut_pkg::DATA_WIDTH-1:0] A; 17 | rand logic [dut_pkg::DATA_WIDTH-1:0] B; 18 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 19 | `endif 20 | */ 21 | //constraint c_a { soft A >=1 ; soft A < dut_pkg::MAX_RAND_VAL; } 22 | //constraint c_b { soft B >=1 ; soft B < dut_pkg::MAX_RAND_VAL; } 23 | 24 | function new(string name = ""); 25 | super.new(name); 26 | endfunction: new 27 | 28 | endclass: mult_input_t 29 | 30 | typedef uvm_sequencer #(mult_input_t) mult_sequencer; 31 | 32 | -------------------------------------------------------------------------------- /basic/my_agent.sv: -------------------------------------------------------------------------------- 1 | class my_agent extends uvm_agent; 2 | `uvm_component_utils(my_agent); 3 | 4 | uvm_analysis_port #(my_transaction) aport; 5 | 6 | my_sequencer my_sequencer_h; 7 | my_driver my_driver_h; 8 | my_monitor my_monitor_h; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction: new 13 | 14 | function void build_phase(uvm_phase phase); 15 | aport = new("aport", this); 16 | `uvm_info("msg", "Building Agent", UVM_NONE) 17 | my_sequencer_h = my_sequencer::type_id::create("my_sequencer", this); 18 | my_driver_h = my_driver::type_id::create("my_driver", this); 19 | my_monitor_h = my_monitor::type_id::create("my_monitor", this); 20 | `uvm_info("msg", "Building Agent DONE!", UVM_NONE) 21 | endfunction: build_phase 22 | 23 | function void connect_phase(uvm_phase phase); 24 | `uvm_info("msg", "Connecting Agent", UVM_NONE) 25 | my_driver_h.seq_item_port.connect(my_sequencer_h.seq_item_export); 26 | my_monitor_h.aport.connect(aport); 27 | `uvm_info("msg", "Connecting Agent DONE!", UVM_NONE) 28 | endfunction: connect_phase 29 | 30 | endclass: my_agent 31 | -------------------------------------------------------------------------------- /mult/tb/mult_div/mult_input_t.sv: -------------------------------------------------------------------------------- 1 | class mult_input_t extends uvm_sequence_item; 2 | `uvm_object_utils(mult_input_t) 3 | 4 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 5 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 6 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | 8 | /* 9 | // TODO I have no ideia why this code below does not replace the code above. 10 | // I would not need to replicate the mult_input_t if it worked as expected 11 | `ifdef SIGNED_MULT == 1'b1 12 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 13 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 14 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 15 | `else 16 | rand logic [dut_pkg::DATA_WIDTH-1:0] A; 17 | rand logic [dut_pkg::DATA_WIDTH-1:0] B; 18 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 19 | `endif 20 | */ 21 | //constraint c_a { soft A >=1 ; soft A < dut_pkg::MAX_RAND_VAL; } 22 | //constraint c_b { soft B >=1 ; soft B < dut_pkg::MAX_RAND_VAL; } 23 | 24 | function new(string name = ""); 25 | super.new(name); 26 | endfunction: new 27 | 28 | endclass: mult_input_t 29 | 30 | typedef uvm_sequencer #(mult_input_t) mult_sequencer; 31 | 32 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/dut_if.sv: -------------------------------------------------------------------------------- 1 | interface dut_if (input bit clock); 2 | import dut_pkg::*; 3 | 4 | bit reset, start; 5 | logic [dut_pkg::DATA_WIDTH-1:0] A,B; 6 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | bit done; 8 | 9 | task reset_dut(); 10 | reset = 1'b1; 11 | @(negedge clock); 12 | @(negedge clock); 13 | reset = 1'b0; 14 | endtask : reset_dut 15 | 16 | 17 | task do_mult(input logic [dut_pkg::DATA_WIDTH-1:0] iA, input logic [dut_pkg::DATA_WIDTH-1:0] iB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 18 | @(posedge clock); 19 | start = 1'b1; 20 | A = iA; 21 | B = iB; 22 | @(posedge clock); 23 | start = 1'b0; 24 | @(posedge done); 25 | @(negedge clock); oRes = dout; 26 | endtask : do_mult 27 | 28 | task get_mult(output logic [dut_pkg::DATA_WIDTH-1:0] oA, output logic [dut_pkg::DATA_WIDTH-1:0] oB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 29 | @(posedge start); 30 | @(negedge clock); 31 | oA = A; 32 | oB = B; 33 | @(posedge done); 34 | @(negedge clock); 35 | oRes = dout; 36 | endtask : get_mult 37 | 38 | endinterface : dut_if 39 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/mult_input_t.sv: -------------------------------------------------------------------------------- 1 | class mult_input_t extends uvm_sequence_item; 2 | `uvm_object_utils(mult_input_t) 3 | 4 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 5 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 6 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | 8 | /* 9 | // TODO I have no ideia why this code below does not replace the code above. 10 | // I would not need to replicate the mult_input_t if it worked as expected 11 | `ifdef SIGNED_MULT == 1'b1 12 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 13 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 14 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 15 | `else 16 | rand logic [dut_pkg::DATA_WIDTH-1:0] A; 17 | rand logic [dut_pkg::DATA_WIDTH-1:0] B; 18 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 19 | `endif 20 | */ 21 | //constraint c_a { soft A >=1 ; soft A < dut_pkg::MAX_RAND_VAL; } 22 | //constraint c_b { soft B >=1 ; soft B < dut_pkg::MAX_RAND_VAL; } 23 | 24 | function new(string name = ""); 25 | super.new(name); 26 | endfunction: new 27 | 28 | endclass: mult_input_t 29 | 30 | typedef uvm_sequencer #(mult_input_t) mult_sequencer; 31 | 32 | -------------------------------------------------------------------------------- /mult/tb/booth_mult2/dut_if.sv: -------------------------------------------------------------------------------- 1 | interface dut_if (input bit clock); 2 | import dut_pkg::*; 3 | 4 | bit reset, start; 5 | logic [dut_pkg::DATA_WIDTH-1:0] A,B; 6 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | bit done; 8 | 9 | task reset_dut(); 10 | reset = 1'b1; 11 | @(negedge clock); 12 | @(negedge clock); 13 | reset = 1'b0; 14 | endtask : reset_dut 15 | 16 | 17 | task do_mult(input logic [dut_pkg::DATA_WIDTH-1:0] iA, input logic [dut_pkg::DATA_WIDTH-1:0] iB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 18 | @(posedge clock); 19 | start = 1'b1; 20 | A = iA; 21 | B = iB; 22 | @(posedge clock); 23 | start = 1'b0; 24 | @(posedge done); 25 | @(negedge clock); oRes = dout; 26 | endtask : do_mult 27 | 28 | task get_mult(output logic [dut_pkg::DATA_WIDTH-1:0] oA, output logic [dut_pkg::DATA_WIDTH-1:0] oB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 29 | @(posedge start); 30 | @(negedge clock); 31 | oA = A; 32 | oB = B; 33 | @(posedge done); 34 | @(negedge clock); 35 | oRes = dout; 36 | endtask : get_mult 37 | 38 | endinterface : dut_if 39 | -------------------------------------------------------------------------------- /mult/tb/booth_mult2/mult_input_t.sv: -------------------------------------------------------------------------------- 1 | class mult_input_t extends uvm_sequence_item; 2 | `uvm_object_utils(mult_input_t) 3 | 4 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 5 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 6 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | 8 | /* 9 | // TODO I have no ideia why this code below does not replace the code above. 10 | // I would not need to replicate the mult_input_t if it worked as expected 11 | `ifdef SIGNED_MULT == 1'b1 12 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] A; 13 | rand logic signed [dut_pkg::DATA_WIDTH-1:0] B; 14 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] dout; 15 | `else 16 | rand logic [dut_pkg::DATA_WIDTH-1:0] A; 17 | rand logic [dut_pkg::DATA_WIDTH-1:0] B; 18 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 19 | `endif 20 | */ 21 | //constraint c_a { soft A >=1 ; soft A < dut_pkg::MAX_RAND_VAL; } 22 | //constraint c_b { soft B >=1 ; soft B < dut_pkg::MAX_RAND_VAL; } 23 | 24 | function new(string name = ""); 25 | super.new(name); 26 | endfunction: new 27 | 28 | endclass: mult_input_t 29 | 30 | typedef uvm_sequencer #(mult_input_t) mult_sequencer; 31 | 32 | -------------------------------------------------------------------------------- /mult/tb/mult_div/dut_if.sv: -------------------------------------------------------------------------------- 1 | interface dut_if (input bit clock); 2 | import dut_pkg::*; 3 | 4 | bit reset, start; 5 | logic [dut_pkg::DATA_WIDTH-1:0] A,B; 6 | logic [2*dut_pkg::DATA_WIDTH-1:0] dout; 7 | bit done; 8 | 9 | 10 | task reset_dut(); 11 | reset = 1'b1; 12 | @(negedge clock); 13 | @(negedge clock); 14 | reset = 1'b0; 15 | endtask : reset_dut 16 | 17 | 18 | task do_mult(input logic [dut_pkg::DATA_WIDTH-1:0] iA, input logic [dut_pkg::DATA_WIDTH-1:0] iB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 19 | @(posedge clock); 20 | start = 1'b1; 21 | A = iA; 22 | B = iB; 23 | @(posedge clock); 24 | start = 1'b0; 25 | @(posedge done); 26 | @(negedge clock); oRes = dout; 27 | endtask : do_mult 28 | 29 | task get_mult(output logic [dut_pkg::DATA_WIDTH-1:0] oA, output logic [dut_pkg::DATA_WIDTH-1:0] oB, output logic [2*dut_pkg::DATA_WIDTH-1:0] oRes); 30 | @(posedge start); 31 | @(negedge clock); 32 | oA = A; 33 | oB = B; 34 | @(posedge done); 35 | @(negedge clock); 36 | oRes = dout; 37 | endtask : get_mult 38 | 39 | endinterface : dut_if 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alexandre Amory 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mult/tb/unsigned_multi/run.do: -------------------------------------------------------------------------------- 1 | 2 | #if [file exists "work"] {vdel -all} 3 | #vlib work 4 | 5 | # Comment out either the SystemVerilog or VHDL DUT. 6 | # There can be only one! 7 | 8 | #VHDL DUT 9 | vcom ../../dut/unsigned_multi/mult.vhd 10 | 11 | # SystemVerilog DUT 12 | # vlog ../misc/tinyalu.sv 13 | #vlog dut.v 14 | 15 | # TB 16 | vlog +incdir+../common -f tb.f 17 | 18 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=smoke_test 19 | set NoQuitOnFinish 1 20 | onbreak {resume} 21 | log /* -r 22 | run -all 23 | coverage attribute -name TESTNAME -value smoke_test 24 | coverage save smoke_test.ucdb 25 | 26 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=zeros_ones_test 27 | set NoQuitOnFinish 1 28 | onbreak {resume} 29 | log /* -r 30 | run -all 31 | # it is an unsigned mult, so there is no point in testing negative numbers 32 | #coverage exclude -cvgpath /dut_pkg/mult_coverage/range_value/a_leg/neg 33 | coverage attribute -name TESTNAME -value zeros_ones_test 34 | coverage save zeros_ones_test.ucdb 35 | 36 | vcover merge -out unsigned_multi.ucdb smoke_test.ucdb zeros_ones_test.ucdb 37 | vcover report unsigned_multi.ucdb -cvg -details 38 | -------------------------------------------------------------------------------- /noc-router/hermes_router/rtl/src/RouterCC_wrapper.sv: -------------------------------------------------------------------------------- 1 | import hermes_pkg::*; 2 | 3 | module RouterCC_wrapper (clock, reset, din, dout ); 4 | 5 | input logic clock, reset; 6 | hermes_if.datain din[5]; 7 | hermes_if.dataout dout[5]; 8 | 9 | logic [4:0] clock_rx, rx, credit_o; 10 | logic [15:0] data_in[4:0]; 11 | 12 | logic [4:0] clock_tx, tx, credit_i; 13 | logic [15:0] data_out[4:0]; 14 | 15 | generate 16 | for (genvar i = 0; i < 5; i++) begin 17 | // input port 18 | assign clock_rx[i] = clock; 19 | assign rx[i] = din[i].avail; 20 | assign din[i].credit = credit_o[i]; 21 | assign data_in[i] = din[i].data; 22 | // output port 23 | assign dout[i].clk = clock_tx[i]; 24 | assign dout[i].avail = tx[i]; 25 | assign credit_i[i] = dout[i].credit; 26 | assign dout[i].data = data_out[i]; 27 | end 28 | endgenerate 29 | 30 | RouterCC #(.address(8'h11)) CC ( .clock(clock), .reset(reset), 31 | //EAST port 32 | .clock_rx(clock_rx), 33 | .rx(rx), 34 | .data_in(data_in), 35 | .credit_o(credit_o), 36 | 37 | .clock_tx(clock_tx), 38 | .tx(tx), 39 | .data_out(data_out), 40 | .credit_i(credit_i) 41 | ); 42 | 43 | endmodule // RouterCC_wrapper 44 | 45 | -------------------------------------------------------------------------------- /mult/tb/common/mult_agent.sv: -------------------------------------------------------------------------------- 1 | class mult_agent extends uvm_agent; 2 | `uvm_component_utils(mult_agent); 3 | 4 | uvm_analysis_port #(mult_input_t) aport; 5 | 6 | mult_sequencer sequencer_h; 7 | mult_driver driver_h; 8 | mult_monitor monitor_h; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction: new 13 | 14 | function void build_phase(uvm_phase phase); 15 | aport = new("aport", this); 16 | `uvm_info("msg", "Building Agent", UVM_NONE) 17 | if (is_active == UVM_ACTIVE) begin 18 | sequencer_h = mult_sequencer::type_id::create("sequencer", this); 19 | driver_h = mult_driver::type_id::create("driver", this); 20 | end 21 | monitor_h = mult_monitor::type_id::create("monitor", this); 22 | `uvm_info("msg", "Building Agent DONE!", UVM_NONE) 23 | endfunction: build_phase 24 | 25 | function void connect_phase(uvm_phase phase); 26 | `uvm_info("msg", "Connecting Agent", UVM_NONE) 27 | if (is_active == UVM_ACTIVE) begin 28 | driver_h.seq_item_port.connect(sequencer_h.seq_item_export); 29 | end 30 | monitor_h.aport.connect(aport); 31 | `uvm_info("msg", "Connecting Agent DONE!", UVM_NONE) 32 | endfunction: connect_phase 33 | 34 | endclass: mult_agent 35 | -------------------------------------------------------------------------------- /mult/tb/common/mult_zero_seq.sv: -------------------------------------------------------------------------------- 1 | class mult_zero_seq extends uvm_sequence #(mult_input_t); 2 | `uvm_object_utils(mult_zero_seq) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | mult_input_t tx; 10 | // a == 0 11 | repeat(10) begin 12 | tx = mult_input_t::type_id::create("tx"); 13 | start_item(tx); 14 | assert(tx.randomize() with {tx.A == 0;}); 15 | finish_item(tx); 16 | end 17 | // b == 0 18 | repeat(10) begin 19 | tx = mult_input_t::type_id::create("tx"); 20 | start_item(tx); 21 | assert(tx.randomize() with {tx.B == 0;}); 22 | finish_item(tx); 23 | end 24 | // a == 0, b== 1 25 | tx = mult_input_t::type_id::create("tx"); 26 | start_item(tx); 27 | assert(tx.randomize() with {tx.A == 0; tx.B == 1;}); 28 | finish_item(tx); 29 | // a == 1, b== 0 30 | tx = mult_input_t::type_id::create("tx"); 31 | start_item(tx); 32 | assert(tx.randomize() with {tx.A == 1; tx.B == 0;}); 33 | finish_item(tx); 34 | // a == b == 0 35 | tx = mult_input_t::type_id::create("tx"); 36 | start_item(tx); 37 | assert(tx.randomize() with {tx.A == 0; tx.B == 0;}); 38 | finish_item(tx); 39 | endtask: body 40 | 41 | endclass: mult_zero_seq 42 | 43 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/run.do: -------------------------------------------------------------------------------- 1 | 2 | #if [file exists "work"] {vdel -all} 3 | #vlib work 4 | 5 | # Comment out either the SystemVerilog or VHDL DUT. 6 | # There can be only one! 7 | 8 | #VHDL DUT 9 | vcom ../../dut/booth_mult/boothmult.vhdl 10 | 11 | # SystemVerilog DUT 12 | # vlog ../misc/tinyalu.sv 13 | #vlog dut.v 14 | 15 | # TB 16 | vlog +incdir+../common -f tb.f 17 | 18 | 19 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=smoke_test 20 | set NoQuitOnFinish 1 21 | onbreak {resume} 22 | log /* -r 23 | run -all 24 | coverage attribute -name TESTNAME -value smoke_test 25 | coverage save smoke_test.ucdb 26 | 27 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=zeros_ones_test 28 | set NoQuitOnFinish 1 29 | onbreak {resume} 30 | log /* -r 31 | run -all 32 | coverage attribute -name TESTNAME -value zeros_ones_test 33 | coverage save zeros_ones_test.ucdb 34 | 35 | 36 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=neg_test 37 | set NoQuitOnFinish 1 38 | onbreak {resume} 39 | log /* -r 40 | run -all 41 | coverage attribute -name TESTNAME -value neg_test 42 | coverage save neg_test.ucdb 43 | 44 | vcover merge -out multi.ucdb smoke_test.ucdb zeros_ones_test.ucdb neg_test.ucdb 45 | vcover report multi.ucdb -cvg -details 46 | 47 | -------------------------------------------------------------------------------- /mult/tb/common/mult_coverage_signed.sv: -------------------------------------------------------------------------------- 1 | class mult_coverage extends uvm_subscriber #(mult_input_t); 2 | `uvm_component_utils(mult_coverage); 3 | 4 | logic signed [dut_pkg::DATA_WIDTH-1:0] A,B; 5 | logic signed [2*dut_pkg::DATA_WIDTH-1:0] result; 6 | 7 | covergroup range_value; 8 | a_leg: coverpoint A { 9 | bins neg = {[$:-2]}; // negative values 10 | bins minus1 = {-1}; // -1 11 | bins zero = {0}; // zero 12 | bins plus1 = {1}; // 1 13 | bins pos = {[2:$]}; // positive values 14 | } 15 | b_leg: coverpoint B { 16 | bins neg = {[$:-2]}; // negative values 17 | bins minus1 = {-1}; // -1 18 | bins zero = {0}; // zero 19 | bins plus1 = {1}; // 1 20 | bins pos = {[2:$]}; // positive values 21 | } 22 | 23 | a_b: cross a_leg, b_leg; 24 | endgroup: range_value 25 | 26 | 27 | function void write(mult_input_t t); 28 | result = t.dout; 29 | A = t.A; 30 | B = t.B; 31 | //`uvm_info("msg", "Transaction Received", UVM_HIGH) 32 | range_value.sample(); 33 | endfunction: write 34 | 35 | function new(string name, uvm_component parent); 36 | super.new(name,parent); 37 | range_value = new(); 38 | endfunction: new 39 | 40 | 41 | endclass: mult_coverage -------------------------------------------------------------------------------- /mult/tb/unsigned_multi/dut_pkg.sv: -------------------------------------------------------------------------------- 1 | package dut_pkg; 2 | import uvm_pkg::*; 3 | `include "uvm_macros.svh" 4 | 5 | // ##### packages ##### 6 | //`include "dut_if_base.sv" 7 | parameter DATA_WIDTH = 16; 8 | // max val for unsigned mults 9 | // check if it is a signed multiplier. used by the scoreboard and i tried to use it in the seq_item, with no success 10 | parameter SIGNED_MULT = 1'b0; 11 | 12 | //parameter MAX_RAND_VAL = 2**DATA_WIDTH-1; 13 | // max val for signed mults 14 | //parameter MAX_RAND_VAL = 2**(DATA_WIDTH-1)-1; 15 | 16 | 17 | // ##### transactions ##### 18 | `include "mult_input_t.sv" 19 | //`include "output_transaction.sv" 20 | 21 | 22 | // #### sequences ##### 23 | `include "mult_basic_seq.sv" 24 | `include "mult_zero_seq.sv" 25 | `include "mult_one_seq.sv" 26 | //`include "mult_neg_seq.sv" 27 | 28 | 29 | // ##### tb modules ##### 30 | `include "mult_driver.sv" 31 | `include "mult_monitor.sv" 32 | `include "mult_coverage_unsigned.sv" 33 | `include "mult_scoreboard.sv" 34 | `include "mult_agent.sv" 35 | `include "mult_env.sv" 36 | 37 | // ##### tests ##### 38 | `include "smoke_test.sv" 39 | `include "zeros_ones_test.sv" 40 | //`include "neg_test.sv" 41 | 42 | //`include "test1.sv" 43 | //`include "test2.sv" 44 | 45 | 46 | endpackage : dut_pkg 47 | -------------------------------------------------------------------------------- /mult/tb/booth_mult2/run.do: -------------------------------------------------------------------------------- 1 | 2 | #if [file exists "work"] {vdel -all} 3 | #vlib work 4 | 5 | # Comment out either the SystemVerilog or VHDL DUT. 6 | # There can be only one! 7 | 8 | #VHDL DUT 9 | #vcom ../../dut/booth_mult/boothmult.vhdl 10 | 11 | # SystemVerilog DUT 12 | # vlog ../misc/tinyalu.sv 13 | vlog ../../dut/booth_mult2/Booth_Multiplier.v 14 | 15 | # TB 16 | vlog +incdir+../common -f tb.f 17 | 18 | 19 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=smoke_test 20 | set NoQuitOnFinish 1 21 | onbreak {resume} 22 | log /* -r 23 | run -all 24 | coverage attribute -name TESTNAME -value smoke_test 25 | coverage save smoke_test.ucdb 26 | 27 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=zeros_ones_test 28 | set NoQuitOnFinish 1 29 | onbreak {resume} 30 | log /* -r 31 | run -all 32 | coverage attribute -name TESTNAME -value zeros_ones_test 33 | coverage save zeros_ones_test.ucdb 34 | 35 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=neg_test 36 | set NoQuitOnFinish 1 37 | onbreak {resume} 38 | log /* -r 39 | run -all 40 | coverage attribute -name TESTNAME -value neg_test 41 | coverage save neg_test.ucdb 42 | 43 | vcover merge -out unsigned_multi.ucdb smoke_test.ucdb zeros_ones_test.ucdb neg_test.ucdb 44 | vcover report unsigned_multi.ucdb -cvg -details 45 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/run.tcl: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | ## Logical synthesis commands ## 3 | ## Script Generated for Undergrad class of microelectronics ## 4 | ## Generated by Matheus Moreira - 9/11/2011 ## 5 | ## GAPH/FACIN/PUCRS ## 6 | ############################################################## 7 | 8 | ## 1) load synthesis configuration, read description and elaborate design 9 | include load.tcl 10 | read_hdl -vhdl HeMPS_defaults.vhd Hermes_buffer.vhd Hermes_crossbar.vhd Hermes_switchcontrol.vhd RouterCC.vhd 11 | elaborate RouterCC 12 | 13 | ## 2) read constraints 14 | read_sdc constraints.sdc 15 | 16 | ## 3) synthesize to generic 17 | synthesize -to_generic -eff high 18 | 19 | ## 4) synthesize to mapped 20 | synthesize -to_mapped -eff high -no_incr 21 | 22 | ## 4.1) write sdf and netlist 23 | write_sdf -timescale ps -design RouterCC > src/layout/RouterCC.sdf 24 | write_hdl RouterCC > src/layout/RouterCC.v 25 | 26 | ## 4.2) report area and timing 27 | report area > area.rep 28 | report timing > timing.rep 29 | report power > power.rep 30 | 31 | ## 5) build physical synthesis environment 32 | #write_design -innovus -base_name src/layout/RouterCC 33 | #write_encounter design -basename encounter/router 34 | -------------------------------------------------------------------------------- /mult/tb/mult_div/run.do: -------------------------------------------------------------------------------- 1 | 2 | #if [file exists "work"] {vdel -all} 3 | #vlib work 4 | 5 | # Comment out either the SystemVerilog or VHDL DUT. 6 | # There can be only one! 7 | 8 | #VHDL DUT 9 | vcom ../../dut/booth_mult/boothmult.vhdl 10 | 11 | # SystemVerilog DUT 12 | # vlog ../misc/tinyalu.sv 13 | vlog ../../dut/mult_div/add32.v 14 | vlog ../../dut/mult_div/mudi64.v 15 | vlog ../../dut/mult_div/mudi64_tb.v 16 | 17 | 18 | # TB 19 | vlog +incdir+../common -f tb.f 20 | 21 | 22 | vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=smoke_test 23 | set NoQuitOnFinish 1 24 | onbreak {resume} 25 | log /* -r 26 | #run -all 27 | #coverage attribute -name TESTNAME -value smoke_test 28 | #coverage save smoke_test.ucdb 29 | 30 | #vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=zeros_ones_test 31 | #set NoQuitOnFinish 1 32 | #onbreak {resume} 33 | #log /* -r 34 | #run -all 35 | #coverage attribute -name TESTNAME -value zeros_ones_test 36 | #coverage save zeros_ones_test.ucdb 37 | 38 | #vsim top -coverage +UVM_VERBOSITY=UVM_FULL +UVM_TESTNAME=neg_test 39 | #set NoQuitOnFinish 1 40 | #onbreak {resume} 41 | #log /* -r 42 | #run -all 43 | #coverage attribute -name TESTNAME -value neg_test 44 | #coverage save neg_test.ucdb 45 | 46 | #vcover merge -out unsigned_multi.ucdb smoke_test.ucdb zeros_ones_test.ucdb neg_test.ucdb 47 | #vcover report unsigned_multi.ucdb -cvg -details 48 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/seqs/src/repeat_seq.sv: -------------------------------------------------------------------------------- 1 | /* 2 | this flat sequence injects 'npackets' into a single port 'port' 3 | all packets will be sent to the same target address 4 | */ 5 | class repeat_seq extends hermes_base_seq; 6 | `uvm_object_utils(repeat_seq) 7 | 8 | // sequence configuration 9 | hermes_router_seq_config cfg; 10 | 11 | function new(string name = "repeat_seq"); 12 | super.new(name); 13 | endfunction: new 14 | 15 | task pre_body(); 16 | super.pre_body(); 17 | // the configuration and the sequencer must be set in the tests 18 | if(!uvm_config_db #(hermes_router_seq_config)::get(get_sequencer(), "", "config", cfg)) 19 | `uvm_fatal(get_type_name(), "config config_db lookup failed") 20 | endtask 21 | 22 | 23 | task body; 24 | hermes_packet_t tx; 25 | 26 | repeat(cfg.npackets) 27 | begin 28 | tx = hermes_packet_t::type_id::create("tx"); 29 | // set the driver port where these packets will be injected 30 | tx.dport = cfg.port; 31 | 32 | start_item(tx); 33 | if( ! tx.randomize() with { 34 | tx.p_size == cfg.p_size; 35 | tx.header == cfg.header; 36 | } 37 | ) 38 | `uvm_error("repeat_seq", "invalid seq item randomization"); 39 | `uvm_info("repeat_seq", cfg.convert2string(), UVM_HIGH) 40 | 41 | finish_item(tx); 42 | end 43 | endtask: body 44 | 45 | endclass: repeat_seq 46 | 47 | -------------------------------------------------------------------------------- /mult/dut/mult_div/mudi64_tb.v: -------------------------------------------------------------------------------- 1 | //a testbench for mudi64.v 2 | `timescale 1ns/10ps 3 | 4 | module mudi64_tb (); 5 | 6 | parameter full = 63; 7 | parameter half = 31; 8 | reg [half:0] opera1; 9 | reg [full:0] opera2; 10 | reg muordi, clock, reset, start; 11 | wire [full:0] result; 12 | wire valid; 13 | 14 | mudi64 U1 (result, opera1, opera2, muordi, clock, reset, start, valid); 15 | 16 | initial begin 17 | $dumpfile("mudi64.vcd"); 18 | $dumpvars(0, mudi64_tb); 19 | end 20 | 21 | initial muordi = 0; //0 for multiplication; 1 for divition 22 | 23 | initial begin 24 | clock = 0; 25 | forever 26 | #10 clock = ~clock; 27 | end 28 | 29 | initial begin 30 | reset = 0; 31 | #1 reset = ~reset; 32 | #1 reset = ~reset; 33 | end 34 | 35 | initial begin 36 | start = 1; 37 | #100 start = 0; 38 | opera1 = 32'h15555555; 39 | opera2 = 32'h55555555; //Q=4, R=1 40 | #100 start = ~start; 41 | #1000 start = ~start; 42 | opera1 = -32'h15555555; 43 | opera2 = 32'h55555555; //Q=fc, R=1 44 | #100 start = ~start; 45 | #1000 start = ~start; 46 | opera1 = 32'h15555555; 47 | opera2 = -32'h55555555; //Q=fc, R=ff 48 | #100 start = ~start; 49 | #1000 start = ~start; 50 | opera1 = -32'h15555555; 51 | opera2 = -32'h55555555; //Q=4, R=ff 52 | #100 start = ~start; 53 | #1000 start = ~start; 54 | opera1 = 0; 55 | opera2 = 0; 56 | end 57 | 58 | initial begin 59 | #20000; 60 | $finish; 61 | end 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /mult/dut/mult_div/add32.v: -------------------------------------------------------------------------------- 1 | //sub-module, a 32-bit adder including eight sequential 4-bit ripple-carry-adder 2 | 3 | module add32 (sum, cout, a, b, cin); 4 | output [31:0] sum; 5 | output cout; 6 | input [31:0] a, b; 7 | input cin; 8 | wire cin4, cin8, cin12, cin16, cin20, cin24, cin28; 9 | add_4 U1 (sum[3:0], cin4, a[3:0], b[3:0], cin); 10 | add_4 U2 (sum[7:4], cin8, a[7:4], b[7:4], cin4); 11 | add_4 U3 (sum[11:8], cin12, a[11:8], b[11:8], cin8); 12 | add_4 U4 (sum[15:12], cin16, a[15:12], b[15:12], cin12); 13 | add_4 U5 (sum[19:16], cin20, a[19:16], b[19:16], cin16); 14 | add_4 U6 (sum[23:20], cin24, a[23:20], b[23:20], cin20); 15 | add_4 U7 (sum[27:24], cin28, a[27:24], b[27:24], cin24); 16 | add_4 U8 (sum[31:28], cout, a[31:28], b[31:28], cin28); 17 | endmodule 18 | 19 | module add_half (sum, cout, a, b); 20 | input a, b; 21 | output cout, sum; 22 | xor (sum, a, b); 23 | and (cout, a, b); 24 | endmodule 25 | 26 | module add_full (sum, cout, a, b, cin); 27 | input a, b, cin; 28 | output cout, sum; 29 | wire w1, w2, w3; 30 | add_half U1 (w1, w2, a, b); 31 | add_half U2 (sum, w3, cin, w1); 32 | or (cout, w2, w3); 33 | endmodule 34 | 35 | module add_4 (sum, cout, a, b, cin); 36 | output [3:0] sum; 37 | output cout; 38 | input [3:0] a, b; 39 | input cin; 40 | wire cin1, cin2, cin3; 41 | add_full U1 (sum[0], cin1, a[0], b[0], cin); 42 | add_full U2 (sum[1], cin2, a[1], b[1], cin1); 43 | add_full U3 (sum[2], cin3, a[2], b[2], cin2); 44 | add_full U4 (sum[3], cout, a[3], b[3], cin3); 45 | endmodule 46 | 47 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/src/RouterCC_wrapper.v: -------------------------------------------------------------------------------- 1 | import hermes_pkg::*; 2 | 3 | module RouterCC_wrapper (clock, reset, din, dout ); 4 | 5 | input logic clock, reset; 6 | hermes_if.datain din[5]; 7 | hermes_if.dataout dout[5]; 8 | 9 | logic [4:0] clock_rx, rx, credit_o; 10 | logic [15:0] data_in[4:0]; 11 | 12 | logic [4:0] clock_tx, tx, credit_i; 13 | logic [15:0] data_out[4:0]; 14 | 15 | generate 16 | for (genvar i = 0; i < 5; i++) begin 17 | // input port 18 | assign clock_rx[i] = clock; 19 | assign rx[i] = din[i].avail; 20 | assign din[i].credit = credit_o[i]; 21 | assign data_in[i] = din[i].data; 22 | // output port 23 | assign dout[i].clk = clock_tx[i]; 24 | assign dout[i].avail = tx[i]; 25 | assign credit_i[i] = dout[i].credit; 26 | assign dout[i].data = data_out[i]; 27 | end 28 | endgenerate 29 | 30 | RouterCC CC ( .clock(clock), .reset(reset), 31 | //EAST port 32 | .clock_rx(clock_rx), 33 | .rx(rx), 34 | //.data_in(data_in), 35 | .\data_in[0] (data_in[0]), 36 | .\data_in[1] (data_in[1]), 37 | .\data_in[2] (data_in[2]), 38 | .\data_in[3] (data_in[3]), 39 | .\data_in[4] (data_in[4]), 40 | .credit_o(credit_o), 41 | 42 | .clock_tx(clock_tx), 43 | .tx(tx), 44 | //.data_out(data_out), 45 | .\data_out[0] (data_out[0]), 46 | .\data_out[1] (data_out[1]), 47 | .\data_out[2] (data_out[2]), 48 | .\data_out[3] (data_out[3]), 49 | .\data_out[4] (data_out[4]), 50 | .credit_i(credit_i) 51 | ); 52 | 53 | endmodule // RouterCC_wrapper 54 | 55 | 56 | -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/wave.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | quietly WaveActivateNextPane {} 0 3 | add wave -noupdate /top/dut1/address 4 | add wave -noupdate /top/dut1/clock 5 | add wave -noupdate /top/dut1/reset 6 | add wave -noupdate -divider -height 50 INPUT 7 | add wave -noupdate /top/dut1/clock_rx 8 | add wave -noupdate -expand /top/dut1/rx 9 | add wave -noupdate -expand /top/dut1/data_in 10 | add wave -noupdate /top/dut1/credit_o 11 | add wave -noupdate -divider -height 50 OUTPUT 12 | add wave -noupdate /top/dut1/clock_tx 13 | add wave -noupdate -expand /top/dut1/tx 14 | add wave -noupdate -expand /top/dut1/data_out 15 | add wave -noupdate -expand /top/dut1/credit_i 16 | add wave -noupdate -divider -height 50 BUFFERS 17 | add wave -noupdate /top/dut1/FEast/buf 18 | add wave -noupdate /top/dut1/FWest/buf 19 | add wave -noupdate /top/dut1/FNorth/buf 20 | add wave -noupdate /top/dut1/FSouth/buf 21 | add wave -noupdate /top/dut1/FLocal/buf 22 | TreeUpdate [SetDefaultTree] 23 | WaveRestoreCursors {{Cursor 1} {61 ns} 0} 24 | quietly wave cursor active 1 25 | configure wave -namecolwidth 220 26 | configure wave -valuecolwidth 100 27 | configure wave -justifyvalue left 28 | configure wave -signalnamewidth 0 29 | configure wave -snapdistance 10 30 | configure wave -datasetprefix 0 31 | configure wave -rowmargin 4 32 | configure wave -childrowmargin 2 33 | configure wave -gridoffset 0 34 | configure wave -gridperiod 1 35 | configure wave -griddelta 40 36 | configure wave -timeline 0 37 | configure wave -timelineunits ns 38 | update 39 | WaveRestoreZoom {0 ns} {578 ns} 40 | -------------------------------------------------------------------------------- /noc-router/vips/sc/packet.h.in: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // DISTRIBUTED HEMPS - version 5.0 4 | // 5 | // Research group: GAPH-PUCRS - contact fernando.moraes@pucrs.br 6 | // 7 | // Distribution: September 2013 8 | // 9 | // Source name: packet.h 10 | // 11 | // Brief description: NOC Definitions 12 | // 13 | //--------------------------------------------------------------------------------------- 14 | 15 | #ifndef _packet 16 | #define _packet 17 | 18 | //------------------------------------ NOC Definitions ---------------------------------- 19 | 20 | #define EAST 0 21 | #define WEST 1 22 | #define NORTH 2 23 | #define SOUTH 3 24 | #define LOCAL 4 25 | 26 | 27 | #define TAM_FLIT 32 28 | #define METADEFLIT (TAM_FLIT/2) 29 | #define QUARTOFLIT (TAM_FLIT/4) 30 | 31 | #define NPORT 5 32 | #define BUFFER_TAM @NOC_BUFFER_SIZE@ 33 | 34 | typedef sc_uint regflit; 35 | typedef sc_uint<16> regaddress; 36 | 37 | typedef sc_uint<3> reg3; 38 | typedef sc_uint<4> reg4; 39 | typedef sc_uint<8> reg8; 40 | typedef sc_uint<10> reg10; 41 | typedef sc_uint<11> reg11; 42 | typedef sc_uint<16> reg16; 43 | typedef sc_uint<32> reg32; 44 | typedef sc_uint<40> reg40; 45 | typedef sc_uint regNport; 46 | typedef sc_uint regflit; 47 | typedef sc_uint<(TAM_FLIT/2)> regmetadeflit; 48 | typedef sc_uint<(TAM_FLIT/4)> regquartoflit; 49 | typedef sc_uint<(3*NPORT)> reg_mux; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /mult/tb/common/zeros_ones_test.sv: -------------------------------------------------------------------------------- 1 | class zeros_ones_test extends uvm_test; 2 | `uvm_component_utils(zeros_ones_test) 3 | 4 | mult_env env_h; 5 | //int a; 6 | 7 | function new (string name, uvm_component parent); 8 | super.new(name,parent); 9 | endfunction : new 10 | 11 | function void build_phase(uvm_phase phase); 12 | env_h = mult_env::type_id::create("env", this); 13 | /* 14 | according to https://www.synopsys.com/content/dam/synopsys/services/whitepapers/hierarchical-testbench-configuration-using-uvm.pdf 15 | it is possible to pass parameter to the simulator avoiding recompilation 16 | +uvm _ set _ config _ int=,, 17 | +uvm _ set _ config _ string=,, 18 | exemple: 19 | +uvm_set_config_int=uvm_test_top.env_i, a, 6 20 | +uvm_set_config_string=uvm_test_top.env_i, color, red 21 | 22 | uvm_config_ db #( uvm_bitstream_t )::set(this, “env _ i”, “a”, a); 23 | usar isso p passar parametro se o teste eh signed ou unsigned, passar o width 24 | */ 25 | `uvm_info("msg", "Building Environment DONE!", UVM_LOW) 26 | endfunction: build_phase 27 | 28 | task run_phase(uvm_phase phase); 29 | mult_zero_seq seq; 30 | mult_one_seq seq1; 31 | 32 | seq = mult_zero_seq::type_id::create("seq"); 33 | phase.raise_objection(this); 34 | seq.start(env_h.agent_h.sequencer_h); 35 | phase.drop_objection(this); 36 | 37 | 38 | seq1 = mult_one_seq::type_id::create("seq1"); 39 | phase.raise_objection(this); 40 | seq1.start(env_h.agent_h.sequencer_h); 41 | phase.drop_objection(this); 42 | endtask 43 | 44 | endclass: zeros_ones_test 45 | -------------------------------------------------------------------------------- /mult/tb/booth_mult/dut_pkg.sv: -------------------------------------------------------------------------------- 1 | package dut_pkg; 2 | import uvm_pkg::*; 3 | `include "uvm_macros.svh" 4 | 5 | // ##### packages ##### 6 | //`include "dut_if_base.sv" 7 | 8 | // multiplier data width 9 | parameter DATA_WIDTH = 32; 10 | // check if it is a signed multiplier. used by the scoreboard and i tried to use it in the seq_item, with no success 11 | parameter SIGNED_MULT = 1'b1; 12 | /* 13 | // max val for signed mults 14 | parameter MAX_RAND_VAL = 2**(DATA_WIDTH-1)-1; 15 | // max val for unsigned mults 16 | parameter MAX_RAND_VAL = 2**DATA_WIDTH-1; 17 | */ 18 | //parameter MAX_RAND_VAL = (SIGNED_MULT == 1'b1)? 2**(DATA_WIDTH-1)-1 : 2**DATA_WIDTH-1; 19 | 20 | // TODO mult_input_t nao aceitou mult_type. funcionou como unsigned 21 | /* 22 | `ifdef SIGNED_MULT == 1'b1 23 | typedef logic signed mult_type; 24 | `else 25 | typedef logic unsigned mult_type; 26 | `endif 27 | */ 28 | 29 | // ##### transactions ##### 30 | `include "mult_input_t.sv" 31 | //`include "output_transaction.sv" 32 | 33 | 34 | // #### sequences ##### 35 | `include "mult_basic_seq.sv" 36 | `include "mult_zero_seq.sv" 37 | `include "mult_one_seq.sv" 38 | `include "mult_neg_seq.sv" 39 | 40 | 41 | // ##### tb modules ##### 42 | `include "mult_driver.sv" 43 | `include "mult_monitor.sv" 44 | `include "mult_coverage_signed.sv" 45 | `include "mult_scoreboard.sv" 46 | `include "mult_agent.sv" 47 | `include "mult_env.sv" 48 | 49 | // ##### tests ##### 50 | `include "smoke_test.sv" 51 | `include "zeros_ones_test.sv" 52 | `include "neg_test.sv" 53 | 54 | //`include "test1.sv" 55 | //`include "test2.sv" 56 | 57 | 58 | endpackage : dut_pkg 59 | -------------------------------------------------------------------------------- /mult/tb/booth_mult2/dut_pkg.sv: -------------------------------------------------------------------------------- 1 | package dut_pkg; 2 | import uvm_pkg::*; 3 | `include "uvm_macros.svh" 4 | 5 | // ##### packages ##### 6 | //`include "dut_if_base.sv" 7 | 8 | // multiplier data width 9 | parameter DATA_WIDTH = 32; 10 | // check if it is a signed multiplier. used by the scoreboard and i tried to use it in the seq_item, with no success 11 | parameter SIGNED_MULT = 1'b1; 12 | /* 13 | // max val for signed mults 14 | parameter MAX_RAND_VAL = 2**(DATA_WIDTH-1)-1; 15 | // max val for unsigned mults 16 | parameter MAX_RAND_VAL = 2**DATA_WIDTH-1; 17 | */ 18 | //parameter MAX_RAND_VAL = (SIGNED_MULT == 1'b1)? 2**(DATA_WIDTH-1)-1 : 2**DATA_WIDTH-1; 19 | 20 | // TODO mult_input_t nao aceitou mult_type. funcionou como unsigned 21 | /* 22 | `ifdef SIGNED_MULT == 1'b1 23 | typedef logic signed mult_type; 24 | `else 25 | typedef logic unsigned mult_type; 26 | `endif 27 | */ 28 | 29 | // ##### transactions ##### 30 | `include "mult_input_t.sv" 31 | //`include "output_transaction.sv" 32 | 33 | 34 | // #### sequences ##### 35 | `include "mult_basic_seq.sv" 36 | `include "mult_zero_seq.sv" 37 | `include "mult_one_seq.sv" 38 | `include "mult_neg_seq.sv" 39 | 40 | 41 | // ##### tb modules ##### 42 | `include "mult_driver.sv" 43 | `include "mult_monitor.sv" 44 | `include "mult_coverage_signed.sv" 45 | `include "mult_scoreboard.sv" 46 | `include "mult_agent.sv" 47 | `include "mult_env.sv" 48 | 49 | // ##### tests ##### 50 | `include "smoke_test.sv" 51 | `include "zeros_ones_test.sv" 52 | `include "neg_test.sv" 53 | 54 | //`include "test1.sv" 55 | //`include "test2.sv" 56 | 57 | 58 | endpackage : dut_pkg 59 | -------------------------------------------------------------------------------- /mult/tb/mult_div/dut_pkg.sv: -------------------------------------------------------------------------------- 1 | package dut_pkg; 2 | import uvm_pkg::*; 3 | `include "uvm_macros.svh" 4 | 5 | // ##### packages ##### 6 | //`include "dut_if_base.sv" 7 | 8 | // multiplier data width 9 | parameter DATA_WIDTH = 32; 10 | // check if it is a signed multiplier. used by the scoreboard and i tried to use it in the seq_item, with no success 11 | parameter SIGNED_MULT = 1'b1; 12 | /* 13 | // max val for signed mults 14 | parameter MAX_RAND_VAL = 2**(DATA_WIDTH-1)-1; 15 | // max val for unsigned mults 16 | parameter MAX_RAND_VAL = 2**DATA_WIDTH-1; 17 | */ 18 | //parameter MAX_RAND_VAL = (SIGNED_MULT == 1'b1)? 2**(DATA_WIDTH-1)-1 : 2**DATA_WIDTH-1; 19 | 20 | // TODO mult_input_t nao aceitou mult_type. funcionou como unsigned 21 | /* 22 | `ifdef SIGNED_MULT == 1'b1 23 | typedef logic signed mult_type; 24 | `else 25 | typedef logic unsigned mult_type; 26 | `endif 27 | */ 28 | 29 | // ##### transactions ##### 30 | `include "mult_input_t.sv" 31 | //`include "output_transaction.sv" 32 | 33 | 34 | // #### sequences ##### 35 | `include "mult_basic_seq.sv" 36 | `include "mult_zero_seq.sv" 37 | `include "mult_one_seq.sv" 38 | `include "mult_neg_seq.sv" 39 | 40 | 41 | // ##### tb modules ##### 42 | `include "mult_driver.sv" 43 | `include "mult_monitor.sv" 44 | `include "mult_coverage_signed.sv" 45 | `include "mult_scoreboard.sv" 46 | `include "mult_agent.sv" 47 | `include "mult_env.sv" 48 | 49 | // ##### tests ##### 50 | `include "smoke_test.sv" 51 | `include "zeros_ones_test.sv" 52 | `include "neg_test.sv" 53 | 54 | //`include "test1.sv" 55 | //`include "test2.sv" 56 | 57 | 58 | endpackage : dut_pkg 59 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/seqs/src/parallel_seq.sv: -------------------------------------------------------------------------------- 1 | /* 2 | this virtual hierarchical sequence injects 5 'repeat_seq' in all input ports in parallel 3 | */ 4 | class parallel_seq extends hermes_base_seq; 5 | `uvm_object_utils(parallel_seq) 6 | 7 | // enable for each port 8 | bit [4:0] enable_port = '{1,1,1,1,1} ;// by default, they are all enabled 9 | 10 | function new(string name = "parallel_seq"); 11 | super.new(name); 12 | endfunction: new 13 | 14 | task pre_body(); 15 | super.pre_body(); 16 | // get enable for each port 17 | endtask 18 | 19 | task body(); 20 | repeat_seq seq[hermes_pkg::NPORT]; 21 | 22 | 23 | foreach (seq[i]) begin 24 | seq[i] = repeat_seq::type_id::create($sformatf("seq_%0d",i)); 25 | // the repeat_seq gets the seq configuration from pre_body 26 | end 27 | // solution from https://verificationacademy.com/forums/systemverilog/fork-within-loop-join-all 28 | // to wait all threads to finish 29 | fork 30 | begin : isolating_thread 31 | for(int index=0;index 19 | #include "packet.h" 20 | 21 | SC_MODULE(fila){ 22 | 23 | sc_in clock; 24 | sc_in reset_n; 25 | sc_in data_in; 26 | sc_in rx; 27 | sc_out credit_o; 28 | //sc_out ack_rx; 29 | sc_out h; 30 | sc_in ack_h; 31 | sc_out data_av; 32 | sc_out data; 33 | sc_in data_ack; 34 | sc_out sender; 35 | 36 | enum fila_out{S_INIT, S_PAYLOAD, S_SENDHEADER, S_HEADER, S_END, S_END2}; 37 | sc_signal EA, PE; 38 | 39 | regflit buffer_in[BUFFER_TAM]; 40 | 41 | sc_signal > first,last; 42 | sc_signal tem_espaco_na_fila, auxack_rx; 43 | sc_signal counter_flit; 44 | 45 | void in_proc_FSM(); 46 | void in_proc_updPtr(); 47 | 48 | void out_proc_data(); 49 | void out_proc_FSM(); 50 | void change_state_sequ(); 51 | void change_state_comb(); 52 | 53 | SC_CTOR(fila){ 54 | SC_METHOD(in_proc_FSM); 55 | sensitive << reset_n.neg(); 56 | sensitive << clock.pos(); 57 | 58 | SC_METHOD(out_proc_data); 59 | sensitive << first; 60 | sensitive << last; 61 | 62 | SC_METHOD(out_proc_FSM); 63 | sensitive << reset_n.neg(); 64 | sensitive << clock.pos(); 65 | 66 | SC_METHOD(in_proc_updPtr); 67 | sensitive << reset_n.neg(); 68 | sensitive << clock.neg(); 69 | } 70 | 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /mult/dut/unsigned_multi/mult.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.std_logic_unsigned.all; 4 | 5 | entity mult_serial is 6 | port ( 7 | A, B : in std_logic_vector(15 downto 0); 8 | start, reset, clock : in std_logic; 9 | done : out std_logic; 10 | dout : out std_logic_vector(31 downto 0) 11 | ); 12 | end mult_serial; 13 | 14 | architecture arc of mult_serial is 15 | signal regP : std_logic_vector(32 downto 0); 16 | signal cont : std_logic_vector(4 downto 0); 17 | 18 | type state is(init, sum, shift, fim); 19 | signal EA, PE : state; 20 | begin 21 | 22 | -- reg FSM 23 | process(clock, reset) 24 | begin 25 | if reset = '1' then 26 | EA <= init; 27 | elsif rising_edge(clock) then 28 | EA <= PE; 29 | end if; 30 | end process; 31 | 32 | -- next state FSM 33 | process(EA, start, cont) 34 | begin 35 | case EA is 36 | when init => 37 | if start = '1' then 38 | PE <= sum; 39 | elsif start = '0' then 40 | PE <= init; 41 | end if; 42 | 43 | when sum => 44 | PE <= shift; 45 | 46 | when shift => 47 | if cont /= 0 then 48 | PE <= sum; 49 | elsif cont = 0 then 50 | PE <= fim; 51 | end if; 52 | 53 | when fim => 54 | PE <= init; 55 | end case; 56 | end process; 57 | 58 | 59 | process(reset, clock) 60 | begin 61 | if reset = '1' then 62 | regP <= (others => '0'); 63 | cont <= (others => '0'); 64 | dout <= (others => '0'); 65 | done <= '0'; 66 | elsif rising_edge(clock) then 67 | case EA is 68 | when init => 69 | regP(32 downto 16) <= (others => '0'); 70 | regP(15 downto 0) <= A; 71 | cont <= "10000"; -- 16 72 | done <= '0'; 73 | 74 | when sum => 75 | cont <= cont-1; 76 | if regP(0) = '1' then 77 | regP(32 downto 16) <= regP(32 downto 16) + ('0' & B); 78 | end if; 79 | 80 | when shift => 81 | regP <= '0' & regP(32 downto 1); 82 | 83 | when fim => 84 | dout <= regP(31 downto 0); 85 | done <= '1'; 86 | end case; 87 | end if; 88 | end process; 89 | 90 | end architecture arc; 91 | 92 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/load.tcl: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | ## Logical synthesis commands ## 3 | ## Modified by Fernando Moraes - 29/set/2012 ## 4 | ############################################################## 5 | 6 | #=============================================================================== 7 | ## load synthesis configuration, read description and elaborate design 8 | #=============================================================================== 9 | 10 | set_db script_search_path ./ 11 | set_db hdl_search_path ../rtl/src/ 12 | set_db information_level 9 13 | 14 | #=============================================================================== 15 | # Load libraries 16 | #=============================================================================== 17 | set DK_PATH "/soft64/design-kits/stm/65nm-cmos065_536" 18 | 19 | set_db library "${DK_PATH}/CORE65GPSVT_5.1/libs/CORE65GPSVT_nom_1.00V_25C.lib \ 20 | ${DK_PATH}/CLOCK65GPSVT_3.1/libs/CLOCK65GPSVT_nom_1.00V_25C.lib \ 21 | ${DK_PATH}/IO65LPHVT_SF_1V8_50A_7M4X0Y2Z_7.0/libs/IO65LPHVT_SF_1V8_50A_7M4X0Y2Z_nom_1.00V_1.80V_25C.lib" 22 | 23 | set_db lef_library "${DK_PATH}/EncounterTechnoKit_cmos065_7m4x0y2z_AP@5.3.1/TECH/cmos065_7m4x0y2z_AP_Worst.lef \ 24 | ${DK_PATH}/PRHS65_7.0.a/CADENCE/LEF/PRHS65_soc.lef \ 25 | ${DK_PATH}/CORE65GPSVT_5.1/CADENCE/LEF/CORE65GPSVT_soc.lef \ 26 | ${DK_PATH}/CLOCK65GPSVT_3.1/CADENCE/LEF/CLOCK65GPSVT_soc.lef \ 27 | ${DK_PATH}/IO65LPHVT_SF_1V8_50A_7M4X0Y2Z_7.0/CADENCE/LEF/IO65LPHVT_SF_1V8_50A_7M4X0Y2Z_soc.lef \ 28 | ${DK_PATH}/IO65LPHVT_CORESUPPLY_50A_7M4X0Y2Z@7.0.c.UD5357/CADENCE/LEF/IO65LPHVT_CORESUPPLY_50A_7M4X0Y2Z_gaph.lef \ 29 | ${DK_PATH}/IO65LP_SF_BASIC_50A_ST_7M4X0Y2Z_7.2/CADENCE/LEF/IO65LP_SF_BASIC_50A_ST_7M4X0Y2Z_soc.lef" 30 | 31 | ##Set captable 32 | set_db cap_table_file ${DK_PATH}/EncounterTechnoKit_cmos065_7m4x0y2z_AP@5.3.1/TECH/cmos065_7m4x0y2z_AP_Worst.captable 33 | 34 | -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright 2010-2018 Mentor Graphics Corporation 3 | # All Rights Reserved Worldwide 4 | # Licensed under the Apache License, Version 2.0 (the 5 | # "License"); you may not use this file except in 6 | # compliance with the License. You may obtain a copy of 7 | # the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in 12 | # writing, software distributed under the License is 13 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 | # CONDITIONS OF ANY KIND, either express or implied. See 15 | # the License for the specific language governing 16 | # permissions and limitations under the License. 17 | #------------------------------------------------------------------------------ 18 | SIMFLAGS=-coverage +UVM_TIMEOUT=1000000 +UVM_VERBOSITY=UVM_HIGH 19 | TOP=top 20 | 21 | all: work build opt sim 22 | 23 | tarball: clean_up tar 24 | 25 | work: 26 | vlib work 27 | 28 | build: 29 | vcom ../../../dut/HeMPS_defaults.vhd 30 | vcom ../../../dut/Hermes_buffer.vhd 31 | vcom ../../../dut/Hermes_crossbar.vhd 32 | vcom ../../../dut/Hermes_switchcontrol.vhd 33 | vcom ../../../dut/RouterCC.vhd 34 | vlog -f tb.f 35 | 36 | opt: 37 | vopt -o opt $(TOP) -debug +designfile 38 | 39 | sim: opt 40 | vsim -c -do sim.do 41 | 42 | smoke_test: 43 | vsim -c -do "run -all" $(TOP) $(SIMFLAGS) +UVM_TESTNAME=smoke_test 44 | 45 | sequential_test: 46 | vsim -c -do "run -all" $(TOP) $(SIMFLAGS) +UVM_TESTNAME=sequential_test 47 | 48 | main_test: 49 | vsim -c -do "run -all" $(TOP) $(SIMFLAGS) +UVM_TESTNAME=main_test 50 | 51 | vis: 52 | visualizer design.bin qwave.db 53 | 54 | clean_up: 55 | rm -rf work transcript *~ vsim.wlf *.log design.bin qwave.db *.tgz 56 | 57 | tar: 58 | @(cd ../.. ;\ 59 | tar -zcf generation/ex1_sequence_randomization/uvm_generation_seq_randomization.tgz \ 60 | generation/common \ 61 | generation/sequence_library \ 62 | generation/tests \ 63 | generation/ex1_sequence_randomization/Makefile \ 64 | generation/ex1_sequence_randomization/README.txt; \ 65 | cd generation/ex1_sequence_randomization) 66 | -------------------------------------------------------------------------------- /minimal/tb.sv: -------------------------------------------------------------------------------- 1 | /* 2 | An absolut minimal working UVM example adapted from 3 | https://www.edaplayground.com/s/example/546 4 | to work with Questa 5 | 6 | Alexandre Amory 7 | */ 8 | 9 | import uvm_pkg::*; 10 | `include "uvm_macros.svh" 11 | 12 | //---------------- 13 | // environment env 14 | //---------------- 15 | class env extends uvm_env; 16 | 17 | virtual add_sub_if m_if; 18 | 19 | function new(string name, uvm_component parent = null); 20 | super.new(name, parent); 21 | endfunction 22 | 23 | function void connect_phase(uvm_phase phase); 24 | `uvm_info("LABEL", "Started connect phase.", UVM_HIGH); 25 | // Get the interface from the resource database. 26 | assert(uvm_resource_db#(virtual add_sub_if)::read_by_name(get_full_name(), "add_sub_if", m_if)); 27 | `uvm_info("LABEL", "Finished connect phase.", UVM_HIGH); 28 | endfunction: connect_phase 29 | 30 | task run_phase(uvm_phase phase); 31 | phase.raise_objection(this); 32 | `uvm_info("LABEL", "Started run phase.", UVM_HIGH); 33 | begin 34 | int a = 8'h2, b = 8'h3; // applies 2 + 3 as stimuli 35 | @(m_if.cb); 36 | m_if.cb.a <= a; 37 | m_if.cb.b <= b; 38 | m_if.cb.doAdd <= 1'b1; 39 | repeat(2) @(m_if.cb); 40 | `uvm_info("RESULT", $sformatf("%0d + %0d = %0d", 41 | a, b, m_if.cb.result), UVM_LOW); // gets 5 as response 42 | end 43 | `uvm_info("LABEL", "Finished run phase.", UVM_HIGH); 44 | phase.drop_objection(this); 45 | endtask: run_phase 46 | 47 | endclass 48 | 49 | //----------- 50 | // module top 51 | //----------- 52 | module top; 53 | 54 | bit clk; 55 | add_sub_if duv_if(clk); 56 | env environment; 57 | //ADD_SUB dut(.clk (clk)); 58 | 59 | ADD_SUB dut( 60 | .clk(clk), 61 | .a0(duv_if.a), 62 | .b0(duv_if.b), 63 | .doAdd0(duv_if.doAdd), 64 | .result0(duv_if.result) 65 | ); 66 | 67 | 68 | initial begin 69 | environment = new("env"); 70 | // Put the interface into the resource database. 71 | uvm_resource_db#(virtual add_sub_if)::set("env", "add_sub_if", duv_if); 72 | clk = 0; 73 | run_test(); 74 | end 75 | 76 | initial begin 77 | forever begin 78 | #(50) clk = ~clk; 79 | end 80 | end 81 | 82 | initial begin 83 | // Dump waves 84 | $dumpvars(0, top); 85 | end 86 | 87 | endmodule 88 | -------------------------------------------------------------------------------- /mult/dut/booth_mult/boothmult.vhdl: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | --use IEEE.std_logic_arith.all; 4 | use IEEE.NUMERIC_STD.all; 5 | 6 | entity boothmult is 7 | generic ( 8 | N : positive := 32 9 | ); 10 | port ( 11 | clk, reset : in std_logic; 12 | multiplier : in std_logic_vector(N-1 downto 0); 13 | multiplicand : in std_logic_vector(N-1 downto 0); 14 | product : out std_logic_vector((2*N)-1 downto 0); 15 | start : in std_logic; 16 | done : out std_logic 17 | ); 18 | end boothmult; 19 | 20 | architecture boothmultarch of boothmult is 21 | 22 | signal a, s, p : SIGNED((2*N) downto 0); 23 | signal pp : signed((2*N)-1 downto 0); 24 | 25 | begin 26 | 27 | a(2*N downto N+1) <= signed(multiplicand(N-1 downto 0)); 28 | a(N downto 0) <= (others => '0'); 29 | s(2*N downto N+1) <= signed(not(multiplicand(N-1 downto 0))) + 1; 30 | s(N downto 0) <= (others => '0'); 31 | p(2*N downto N+1) <= (others => '0'); 32 | p(N downto 1) <= signed(multiplier(N-1 downto 0)); 33 | p(0) <= '0'; 34 | 35 | mult: process(clk) 36 | variable count : integer := 0; 37 | variable todo : signed(1 downto 0); 38 | variable ppp : signed((2*N) downto 0); 39 | variable ddd : boolean; 40 | begin 41 | 42 | --testing code 43 | todo := ppp(1) & ppp(0); 44 | 45 | if rising_edge(clk) then 46 | 47 | if (reset = '1') then 48 | ppp := (others => '0'); 49 | count := 0; 50 | ddd := false; 51 | elsif (start = '1') then 52 | ppp := p; 53 | count := 0; 54 | ddd := false; 55 | elsif (count = N) then 56 | ddd := true; 57 | else 58 | if (todo = "01") then 59 | ppp := ppp + a; 60 | elsif (todo = "10") then 61 | ppp := ppp + s; 62 | end if; 63 | count := count + 1; 64 | ppp := shift_right(ppp,1); 65 | end if; 66 | 67 | pp(2*N-1 downto 0) <= ppp(2*N downto 1); 68 | 69 | if ddd then 70 | done <= '1'; 71 | else 72 | done <= '0'; 73 | end if; 74 | 75 | end if; 76 | 77 | end process; 78 | 79 | --product <= std_logic_vector(s(2*N downto 1)); 80 | 81 | --product((2*N)-1) <= multiplier(N-1) xor multiplicand(N-1); 82 | --product((2*N-2) downto 0) <= std_logic_vector(pp((2*N-2) downto 0)); 83 | product <= std_logic_vector(pp); 84 | 85 | end boothmultarch; 86 | 87 | 88 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/base_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | base test. does not implement run_phase 3 | */ 4 | class base_test extends uvm_test; 5 | `uvm_component_utils(base_test) 6 | 7 | hermes_router_env env_h; 8 | hermes_router_env_config env_cfg; 9 | hermes_agent_config acfg[hermes_pkg::NPORT]; 10 | 11 | function new (string name, uvm_component parent); 12 | super.new(name,parent); 13 | endfunction : new 14 | 15 | // Initialise the virtual sequence handles 16 | function void init_vseq(hermes_base_seq vseq); 17 | foreach (vseq.sequencer[i]) begin 18 | vseq.sequencer[i] = env_h.agent_master_h[i].sequencer_h; 19 | end 20 | endfunction: init_vseq 21 | 22 | // print debug messages 23 | function void end_of_elaboration_phase(uvm_phase phase); 24 | super.end_of_elaboration_phase(phase); 25 | if (uvm_top.get_report_verbosity_level() >= UVM_HIGH) begin 26 | this.print(); 27 | uvm_top.print_topology(); 28 | //factory.print(); 29 | uvm_config_db #(int)::dump(); 30 | end 31 | endfunction 32 | 33 | // create the env and cfgs 34 | function void build_phase(uvm_phase phase); 35 | super.build_phase(phase); 36 | env_cfg = hermes_router_env_config::type_id::create("env_cfg",this); 37 | foreach(acfg[i]) begin 38 | acfg[i] = hermes_agent_config::type_id::create($sformatf("acfg[%0d]",i),this); 39 | // hook the env's config with the agent's config 40 | env_cfg.agent_cfg[i] = acfg[i]; 41 | end 42 | 43 | /* 44 | // in this TB i decided to leave the iterface out of the agent configuration. However, if it would be inside, 45 | // then the base test would need to get the interface here (set by top) to assign to the agent configuration 46 | foreach(acfg[i]) begin 47 | if ( ! uvm_config_db#( virtual router_if )::get( this, "", $sformatf("in_if[%0d]",i), ai_cfg[i].dut_if ) ) begin 48 | `uvm_error( "test", "in_if not found" ) 49 | end 50 | 51 | if ( ! uvm_config_db#( virtual router_if )::get( this, "", $sformatf("out_if[%0d]",i), ao_cfg[i].dut_if ) ) begin 52 | `uvm_error( "test", "out_if not found" ) 53 | end 54 | env_cfg.agent_in_cfg[i] = ai_cfg[i]; 55 | env_cfg.agent_out_cfg[i] = ao_cfg[i]; 56 | end 57 | */ 58 | endfunction: build_phase 59 | 60 | /* 61 | function void connect_phase(uvm_phase phase); 62 | super.connect_phase(phase); 63 | endfunction: connect_phase 64 | */ 65 | 66 | endclass: base_test 67 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Run 'genus' to update the netlist. 4 | 5 | > $ genus -no_gui -files run.tcl 6 | 7 | The library dependent settings are all located in the 'load.tcl' file 8 | in case someone needs to replace the technology library. 9 | 10 | 11 | ## report area 12 | 13 | ``` 14 | ============================================================ 15 | Generated by: Genus(TM) Synthesis Solution 18.11-s009_1 16 | Generated on: Jan 24 2019 02:21:20 pm 17 | Module: RouterCC 18 | Technology libraries: CORE65GPSVT 19 | CLOCK65GPSVT 20 | IO65LPHVT_SF_1V8_50A_7M4X0Y2Z 21 | physical_cells 22 | Operating conditions: _nominal_ 23 | Interconnect mode: global 24 | Area mode: physical library 25 | ============================================================ 26 | 27 | Instance Module Cell Count Cell Area Net Area Total Area 28 | -------------------------------------------------------------- 29 | RouterCC 3352 23375.040 8721.576 32096.616 30 | ``` 31 | 32 | ## report timing 33 | 34 | ``` 35 | ============================================================ 36 | Generated by: Genus(TM) Synthesis Solution 18.11-s009_1 37 | Generated on: Jan 24 2019 02:21:20 pm 38 | Module: RouterCC 39 | Operating conditions: _nominal_ 40 | Interconnect mode: global 41 | Area mode: physical library 42 | ============================================================ 43 | 44 | 45 | Path 1: MET (74 ps) Setup Check with Pin SwitchControl_ES_reg[2]/CP->D 46 | Group: clock 47 | Startpoint: (R) FWest_first_reg[0]/CP 48 | Clock: (R) clock 49 | Endpoint: (F) SwitchControl_ES_reg[2]/D 50 | Clock: (F) clock 51 | 52 | Capture Launch 53 | Clock Edge:+ 1000 0 54 | Src Latency:+ 0 0 55 | Net Latency:+ 0 (I) 0 (I) 56 | Arrival:= 1000 0 57 | 58 | Setup:- 67 59 | Required Time:= 933 60 | Launch Clock:- 0 61 | Data Path:- 860 62 | Slack:= 74 63 | 64 | ``` 65 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/testbench/top.sv: -------------------------------------------------------------------------------- 1 | /* 2 | UVM testbench for the router described in the following paper 3 | 4 | @article{moraes2004hermes, 5 | title={HERMES: an infrastructure for low area overhead packet-switching networks on chip}, 6 | author={Moraes, Fernando and Calazans, Ney and Mello, Aline and M{\"o}ller, Leandro and Ost, Luciano}, 7 | journal={INTEGRATION, the VLSI journal}, 8 | volume={38}, 9 | number={1}, 10 | pages={69--93}, 11 | year={2004}, 12 | publisher={Elsevier} 13 | } 14 | 15 | This TB simulates the middle router (addr 8'h11) in a 3x3 NoC 16 | 17 | 02 12 22 18 | 01 11 21 19 | 00 10 20 20 | 21 | The port's code number 22 | N2 23 | -------- 24 | W1 | | E0 25 | | | 26 | /------- 27 | L4 S3 28 | 29 | */ 30 | 31 | `timescale 1 ns / 1 ps 32 | 33 | module top; 34 | import uvm_pkg::*; 35 | import hermes_pkg::*; 36 | import hermes_router_test_pkg::*; 37 | 38 | bit clock; 39 | always #10 clock = ~clock; // clock generator 40 | 41 | 42 | // reset generator 43 | bit reset = 1; 44 | initial begin 45 | reset = 1; 46 | repeat (5) begin 47 | @(posedge clock); 48 | end 49 | reset = 0; 50 | end 51 | 52 | // generate interfaces 53 | hermes_if master_if[hermes_pkg::NPORT](clock, reset); 54 | hermes_if slave_if [hermes_pkg::NPORT](clock, reset); 55 | 56 | // pass the interfaces to the agents and they will pass it to their monitors and drivers 57 | genvar i; 58 | for(i=0; i< hermes_pkg::NPORT; i++) 59 | begin : dut_inst 60 | initial 61 | begin 62 | uvm_config_db#(virtual hermes_if)::set(null,$sformatf("uvm_test_top.env.agent_master_%0d",i),"if",master_if[i]); 63 | uvm_config_db#(virtual hermes_if)::set(null,$sformatf("uvm_test_top.env.agent_slave_%0d",i),"if",slave_if[i]); 64 | // this is read by the base test 65 | //uvm_config_db#(virtual hermes_if)::set(null,"uvm_test_top",$sformatf("in_if[%0d]",i),in_if[i]); 66 | //uvm_config_db#(virtual hermes_if)::set(null,"uvm_test_top",$sformatf("out_if[%0d]",i),out_if[i]); 67 | end 68 | end 69 | 70 | 71 | // instantiate a central router 72 | RouterCC_wrapper dut1(.clock(clock), 73 | .reset(reset), 74 | .din(master_if), 75 | .dout(slave_if) 76 | ); 77 | 78 | 79 | initial 80 | begin: blk 81 | //print_config(); 82 | // enable uvm transaction recording. must be executed before creating the uvm components 83 | uvm_config_db# (int) :: set (null, "*", "recording_detail",1); 84 | 85 | run_test(); // vsim +UVM_TESTNAME=my_test 86 | 87 | end // blk 88 | 89 | endmodule: top 90 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/parallel_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | test that injects packets in all input ports in parallel 3 | */ 4 | class parallel_test extends base_test; 5 | `uvm_component_utils(parallel_test) 6 | 7 | function new (string name, uvm_component parent); 8 | super.new(name,parent); 9 | endfunction : new 10 | 11 | function void build_phase(uvm_phase phase); 12 | super.build_phase(phase); 13 | 14 | // randomize here the agent configuration 15 | /* 16 | foreach(acfg[i]) begin 17 | if( !acfg[i].randomize() ) 18 | `uvm_error("test", "invalid agent cfg randomization"); 19 | end 20 | */ 21 | 22 | // in this test, all agents have the same behaviour 23 | foreach(acfg[i]) begin 24 | if( !acfg[i].randomize() with { 25 | cycle2send == 1; // a new packet is sent 1 clock cycle after the last one 26 | cycle2flit == 0; // a new flit is sent every cycle after the transaction starts 27 | cred_distrib == 5; // the slave ports have 50% availability 28 | } 29 | ) 30 | `uvm_error("test", "invalid agent cfg randomization"); 31 | end 32 | 33 | 34 | // last thing to do is to the agent configuration with config_db 35 | uvm_config_db#(hermes_router_env_config)::set(null, "uvm_test_top.env", "config", env_cfg); 36 | env_h = hermes_router_env::type_id::create("env", this); 37 | endfunction 38 | 39 | task run_phase(uvm_phase phase); 40 | parallel_seq seq = parallel_seq::type_id::create("seq"); 41 | hermes_router_seq_config cfg[hermes_pkg::NPORT]; 42 | 43 | foreach(cfg[i]) begin 44 | cfg[i] = hermes_router_seq_config::type_id::create($sformatf("seq_cfg[%0d]",i)); 45 | if( !cfg[i].randomize() with { 46 | // number of packets to be simulated per sequencer 47 | npackets == 5; 48 | port == i; 49 | // only small packets 50 | p_size == hermes_packet_t::SMALL; 51 | } 52 | ) 53 | `uvm_error("test", "invalid cfg randomization"); 54 | // send the sequence configuration to each sequencer 55 | uvm_config_db#(hermes_router_seq_config)::set(null, $sformatf("uvm_test_top.env.agent_master_%0d.sequencer",i), "config",cfg[i]); 56 | 57 | end 58 | 59 | phase.raise_objection(this); 60 | // start the virtual sequence 61 | init_vseq(seq); 62 | //seq.set_seq_config(cfg); 63 | seq.start(null); 64 | // end the simulation a little bit latter 65 | phase.phase_done.set_drain_time(this, 100ns); 66 | phase.drop_objection(this); 67 | endtask 68 | 69 | endclass: parallel_test 70 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/random_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | simple test that injects 10 packets into a randomly selected ports 3 | */ 4 | class random_test extends base_test; 5 | `uvm_component_utils(random_test) 6 | 7 | // configure (in command line with, e,g, +uvm_set_config_int=*,repeat_sequence,3) the test to repeat the sequence 8 | int repeat_sequence; 9 | 10 | function new (string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction : new 13 | 14 | function void build_phase(uvm_phase phase); 15 | super.build_phase(phase); 16 | 17 | // randomize here the agent configuration 18 | foreach(acfg[i]) begin 19 | if( !acfg[i].randomize() with { 20 | cycle2send == 1; 21 | cycle2flit == 0; 22 | //cred_distrib == 10; 23 | } 24 | ) 25 | `uvm_error("test", "invalid agent cfg randomization"); 26 | end 27 | 28 | // change any env and agent configuration here, before sending it to the config_db 29 | 30 | if(!uvm_config_db #(uvm_bitstream_t)::get(null, "", "repeat_sequence", repeat_sequence)) 31 | repeat_sequence = 10; // defaul value 32 | 33 | // last thing to do is to the agent configuration with config_db 34 | uvm_config_db#(hermes_router_env_config)::set(null, "uvm_test_top.env", "config", env_cfg); 35 | env_h = hermes_router_env::type_id::create("env", this); 36 | endfunction 37 | 38 | 39 | task run_phase(uvm_phase phase); 40 | repeat_seq seq; 41 | hermes_router_seq_config seq_cfg; 42 | 43 | phase.raise_objection(this); 44 | 45 | repeat(repeat_sequence) 46 | begin 47 | // set the sequence configuration, to be read by the sequencer 48 | seq_cfg = hermes_router_seq_config::type_id::create("seq_cfg"); 49 | if( !seq_cfg.randomize() with { 50 | // number of packets to be simulated 51 | npackets == 1; 52 | // only small packets 53 | p_size == hermes_packet_t::SMALL; 54 | } 55 | ) 56 | `uvm_error("test", "invalid cfg randomization"); 57 | uvm_config_db#(hermes_router_seq_config)::set(null, "", "config",seq_cfg); 58 | 59 | // create the sequence and initialize it 60 | seq = repeat_seq::type_id::create("seq"); 61 | init_vseq(seq); 62 | 63 | if( !seq.randomize()) 64 | `uvm_error("test", "invalid seq randomization"); 65 | 66 | seq.start(seq.sequencer[seq_cfg.port]); 67 | end 68 | // end the simulation a little bit latter 69 | //phase.phase_done.set_drain_time(this, 100ns); 70 | phase.drop_objection(this); 71 | endtask 72 | 73 | endclass: random_test 74 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_router_env_pkg/src/hermes_router_coverage.sv: -------------------------------------------------------------------------------- 1 | class hermes_router_coverage extends uvm_subscriber #(hermes_packet_t); 2 | `uvm_component_utils(hermes_router_coverage); 3 | 4 | bit [3:0] oport, iport, x, y; 5 | bit [7:0] packet_size; 6 | 7 | 8 | // used to check if all input ports sent packets to all output ports, except in case of loopback 9 | covergroup cg_ports; 10 | cp_iport: coverpoint iport { 11 | bins port[] = {[0:4]}; // input ports. one bin per port 12 | } 13 | cp_oport: coverpoint oport { 14 | bins port[] = {[0:4]}; // output ports. one bin per port 15 | } 16 | 17 | x_io_ports: cross cp_iport, cp_oport{ 18 | // exclude invalid turns, like N-> W 19 | // example from https://www.amiq.com/consulting/2014/09/17/how-to-ignore-cross-coverage-bins-using-expressions-in-systemverilog/ 20 | function CrossQueueType createIgnoreBins(); 21 | createIgnoreBins.push_back('{hermes_pkg::NORTH,hermes_pkg::EAST}); 22 | createIgnoreBins.push_back('{hermes_pkg::NORTH,hermes_pkg::WEST}); 23 | createIgnoreBins.push_back('{hermes_pkg::SOUTH,hermes_pkg::EAST}); 24 | createIgnoreBins.push_back('{hermes_pkg::SOUTH,hermes_pkg::WEST}); 25 | endfunction 26 | ignore_bins ignore_invalid_turns = createIgnoreBins(); 27 | // exclude loopback from cross_coverage 28 | ignore_bins loopback = x_io_ports with (cp_iport == cp_oport); 29 | } 30 | endgroup: cg_ports 31 | 32 | // used to checke whether all routers in the noc received packets from this router 33 | covergroup cg_noc_addr; 34 | cp_x: coverpoint x { 35 | bins addr[] = {[0:hermes_pkg::X_MAX]}; // x noc addr. 36 | } 37 | cp_y: coverpoint y { 38 | bins addr[] = {[0:hermes_pkg::Y_MAX]}; // y noc addr 39 | } 40 | 41 | x_noc_addr: cross cp_x, cp_y; 42 | endgroup: cg_noc_addr 43 | 44 | // used to check if packets from all possible sizes were simulated 45 | covergroup cg_packet_sizes; 46 | cp_sizes: coverpoint packet_size { 47 | bins port[] = {[0:128]}; // valid packet lenghts. one bin per size 48 | } 49 | endgroup: cg_packet_sizes 50 | 51 | function void write(hermes_packet_t t); 52 | oport = t.oport; 53 | iport = t.dport; 54 | x = t.x; 55 | y = t.y; 56 | packet_size = t.payload.size(); 57 | 58 | cg_ports.sample(); 59 | cg_packet_sizes.sample(); 60 | cg_noc_addr.sample(); 61 | `uvm_info("COVERAGE", "PACKET RECEIVED !!!!", UVM_HIGH); 62 | endfunction: write 63 | 64 | function new(string name, uvm_component parent); 65 | super.new(name,parent); 66 | cg_ports = new(); 67 | cg_packet_sizes = new(); 68 | cg_noc_addr = new(); 69 | endfunction: new 70 | 71 | 72 | endclass: hermes_router_coverage -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_slave_driver.sv: -------------------------------------------------------------------------------- 1 | //class used to implement the random credit logic 2 | class credit_class; 3 | // the probability to have credit to send flits outside the router. 4 | // cred_distrib == 10 ==> 100%, i.e. the next router is always free to send flits 5 | // cred_distrib == 1 ==> 10%, i.e. the next router is always free only 10% of the time 6 | bit [3:0] cred_distrib; 7 | rand bit credit; 8 | 9 | 10 | constraint cred { 11 | // the sum of the probs must be 10 12 | credit dist { 13 | 0 := 10-cred_distrib, 14 | 1 := cred_distrib 15 | }; 16 | } 17 | 18 | // dist == 5 means 50% of the time there will be credit 19 | function new (input bit [3:0] disto = 5); 20 | cred_distrib = disto; 21 | endfunction 22 | endclass 23 | 24 | 25 | ///////////////////// 26 | // This driver generates the input credit signal in the router output ports. 27 | // It allows to change the random prob of asserting this signal. 28 | // It is only used when the agent is attached with a unconnected output port 29 | // TODO setar range de 0.0 a 1.0 30 | ///////////////////// 31 | // hermes driver for outgoing packets 32 | class hermes_slave_driver extends hermes_base_driver; 33 | `uvm_component_utils(hermes_slave_driver); 34 | 35 | // logic used to randomize credit at the output port 36 | credit_class credit; 37 | 38 | function new(string name, uvm_component parent); 39 | super.new(name, parent); 40 | endfunction : new 41 | 42 | function void build_phase(uvm_phase phase); 43 | bit [3:0] distrib; 44 | super.build_phase(phase); 45 | 46 | // print config_db 47 | //print_config(); 48 | 49 | // this should be set by the test, for each output agent 50 | if (!uvm_config_db #(bit [3:0])::get (this,"", "cred_distrib", distrib) ) 51 | `uvm_fatal("monitor", "No cred_distrib"); 52 | `uvm_info("driver", $sformatf("got cred_distrib %0d",distrib), UVM_HIGH) 53 | if ( !(distrib >= 1 && distrib <= 10)) 54 | `uvm_fatal("monitor", "cred_distrib must be between 1 and 10"); 55 | 56 | // the random distribution is set only once per driver. does not seem necessary to change it during runtime 57 | credit = new(distrib); 58 | 59 | `uvm_info("msg", "DRIVER Done!!!", UVM_HIGH) 60 | endfunction : build_phase 61 | 62 | 63 | // generates random credit signal at the output port, simulating neighbor congested routers with full buffers 64 | task run_phase(uvm_phase phase); 65 | dut_vi.credit = 0; 66 | @(negedge dut_vi.reset); 67 | forever 68 | begin 69 | if( !credit.randomize() ) 70 | `uvm_error("monitor", "invalid credit randomization"); 71 | dut_vi.credit = credit.credit; 72 | @(posedge dut_vi.clock); 73 | end 74 | endtask: run_phase 75 | 76 | endclass: hermes_slave_driver 77 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/sequential_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | this hierarchical sequence injects packets in sequential port order, starting with the port 0. 3 | */ 4 | class sequential_test extends base_test; 5 | `uvm_component_utils(sequential_test) 6 | 7 | // configure (in command line with, e,g, +uvm_set_config_int=*,repeat_sequence,3) the test to repeat the sequence 8 | int repeat_sequence; 9 | 10 | function new (string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction : new 13 | 14 | function void build_phase(uvm_phase phase); 15 | super.build_phase(phase); 16 | 17 | // randomize here the agent configuration 18 | foreach(acfg[i]) begin 19 | if( !acfg[i].randomize() with { 20 | //cycle2send == 1; 21 | cycle2flit == 0; 22 | cred_distrib == 8; 23 | } 24 | ) 25 | `uvm_error("test", "invalid agent cfg randomization"); 26 | end 27 | 28 | // change any env and agent configuration here, before sending it to the config_db 29 | 30 | if(!uvm_config_db #(uvm_bitstream_t)::get(null, "", "repeat_sequence", repeat_sequence)) 31 | repeat_sequence = 10; // defaul value 32 | 33 | // last thing to do is to the agent configuration with config_db 34 | uvm_config_db#(hermes_router_env_config)::set(null, "uvm_test_top.env", "config", env_cfg); 35 | env_h = hermes_router_env::type_id::create("env", this); 36 | endfunction 37 | 38 | 39 | task run_phase(uvm_phase phase); 40 | repeat_seq seq; 41 | hermes_router_seq_config seq_cfg; 42 | 43 | phase.raise_objection(this); 44 | 45 | for (int i = 0; i < hermes_pkg::NPORT; i++) 46 | begin 47 | repeat(repeat_sequence) 48 | begin 49 | // set the sequence configuration, to be read by the sequencer 50 | seq_cfg = hermes_router_seq_config::type_id::create("seq_cfg"); 51 | if( !seq_cfg.randomize() with { 52 | // number of packets to be simulated 53 | npackets == 1; 54 | // input port 55 | port == i; 56 | // only small packets 57 | p_size == hermes_packet_t::SMALL; 58 | } 59 | ) 60 | `uvm_error("test", "invalid cfg randomization"); 61 | uvm_config_db#(hermes_router_seq_config)::set(null, "", "config",seq_cfg); 62 | 63 | // create the sequence and initialize it 64 | seq = repeat_seq::type_id::create("seq"); 65 | init_vseq(seq); 66 | 67 | if( !seq.randomize()) 68 | `uvm_error("test", "invalid seq randomization"); 69 | 70 | seq.start(seq.sequencer[seq_cfg.port]); 71 | end 72 | end 73 | // end the simulation a little bit latter 74 | //phase.phase_done.set_drain_time(this, 100ns); 75 | phase.drop_objection(this); 76 | endtask 77 | 78 | endclass: sequential_test 79 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/repeat_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | simple test that injects 10 packets into the north port. 3 | */ 4 | class repeat_test extends base_test; 5 | `uvm_component_utils(repeat_test) 6 | 7 | function new (string name, uvm_component parent); 8 | super.new(name,parent); 9 | endfunction : new 10 | 11 | 12 | function void build_phase(uvm_phase phase); 13 | super.build_phase(phase); 14 | 15 | // randomize here the agent configuration 16 | foreach(acfg[i]) begin 17 | if( !acfg[i].randomize() ) 18 | `uvm_error("repeat_test", "invalid agent cfg randomization"); 19 | end 20 | 21 | // or disable the master drivers 22 | foreach(acfg[i]) begin 23 | acfg[i].rand_mode(0); 24 | acfg[i].master_driver_enabled = 0; 25 | end 26 | 27 | // this test uses only the north port 28 | acfg[hermes_pkg::NORTH].rand_mode(1); 29 | acfg[hermes_pkg::NORTH].master_driver_enabled = 1; 30 | if( !acfg[hermes_pkg::NORTH].randomize() with { 31 | cycle2send == 1; 32 | cycle2flit == 0; 33 | } 34 | ) 35 | `uvm_error("repeat_test", "invalid agent cfg randomization"); 36 | 37 | 38 | // change any env and agent configuration here, before sending it to the config_db 39 | 40 | // last thing to do is to the agent configuration with config_db 41 | uvm_config_db#(hermes_router_env_config)::set(null, "uvm_test_top.env", "config", env_cfg); 42 | env_h = hermes_router_env::type_id::create("env", this); 43 | endfunction 44 | 45 | 46 | task run_phase(uvm_phase phase); 47 | repeat_seq seq; 48 | hermes_router_seq_config seq_cfg; 49 | 50 | // set the sequence configuration, to be read by the sequencer 51 | seq_cfg = hermes_router_seq_config::type_id::create("seq_cfg"); 52 | if( !seq_cfg.randomize() with { 53 | // number of packets to be simulated 54 | npackets == 10; 55 | // this seq will inject packets into the NORTH port only 56 | port == hermes_pkg::NORTH; 57 | // all packets will be sent to the router 8'h11 58 | header == 8'h11; 59 | // only small packets 60 | p_size == hermes_packet_t::SMALL; 61 | } 62 | ) 63 | `uvm_error("rand", "invalid cfg randomization"); 64 | uvm_config_db#(hermes_router_seq_config)::set(null, "", "config",seq_cfg); 65 | 66 | phase.raise_objection(this); 67 | 68 | // create the sequence and initialize it 69 | seq = repeat_seq::type_id::create("seq"); 70 | init_vseq(seq); 71 | 72 | if( !seq.randomize()) 73 | `uvm_error("rand", "invalid seq randomization"); 74 | 75 | seq.start(seq.sequencer[seq_cfg.port]); 76 | 77 | // end the simulation a little bit latter 78 | //phase.phase_done.set_drain_time(this, 100ns); 79 | phase.drop_objection(this); 80 | endtask 81 | 82 | endclass: repeat_test 83 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_router_env_pkg/src/hermes_router_env.sv: -------------------------------------------------------------------------------- 1 | class hermes_router_env extends uvm_env; 2 | `uvm_component_utils(hermes_router_env); 3 | 4 | hermes_agent agent_master_h [hermes_pkg::NPORT]; 5 | hermes_agent agent_slave_h [hermes_pkg::NPORT]; 6 | hermes_router_coverage coverage_h; 7 | hermes_router_scoreboard scoreboard_h; 8 | hermes_router_env_config cfg; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction: new 13 | 14 | function void build_phase(uvm_phase phase); 15 | // build the agent and pass its parameters 16 | if (uvm_top.get_report_verbosity_level() >= UVM_HIGH) 17 | print_config(); 18 | 19 | if (!uvm_config_db #(hermes_router_env_config)::get(this, "", "config", cfg)) 20 | `uvm_fatal("env", "No cfg"); 21 | 22 | foreach (agent_master_h[i]) begin 23 | uvm_config_db #(hermes_agent_config)::set(this, $sformatf("agent_master_%0d",i), "config", cfg.agent_cfg[i]); 24 | // the following configuration sent to the agent are not supposed to be changed in the tes level, so they were separated 25 | uvm_config_db #(string) ::set(this, $sformatf("agent_master_%0d",i), "mode", "master"); 26 | uvm_config_db #(bit [3:0]) ::set(this, $sformatf("agent_master_%0d",i), "port", i); 27 | 28 | agent_master_h[i] = hermes_agent::type_id::create($sformatf("agent_master_%0d",i), this); 29 | end 30 | foreach (agent_slave_h[i]) begin 31 | uvm_config_db #(hermes_agent_config)::set(this, $sformatf("agent_slave_%0d",i), "config", cfg.agent_cfg[i]); 32 | // the following configuration sent to the agent are not supposed to be changed in the tes level, so they were separated 33 | uvm_config_db #(string) ::set(this, $sformatf("agent_slave_%0d",i), "mode", "slave"); 34 | uvm_config_db #(bit [3:0]) ::set(this, $sformatf("agent_slave_%0d",i), "port", i); 35 | 36 | agent_slave_h[i] = hermes_agent::type_id::create($sformatf("agent_slave_%0d",i), this); 37 | end 38 | 39 | if (cfg.enable_coverage == 1) 40 | coverage_h = hermes_router_coverage::type_id::create("coverage", this); 41 | scoreboard_h = hermes_router_scoreboard::type_id::create("scoreboard", this); 42 | `uvm_info("msg", "ENV Done !", UVM_HIGH) 43 | endfunction: build_phase 44 | 45 | function void connect_phase(uvm_phase phase); 46 | `uvm_info("msg", "Connecting ENV", UVM_HIGH) 47 | foreach (agent_master_h[i]) begin 48 | // connect in monitors with the sb 49 | agent_master_h[i].monitor_h.aport.connect(scoreboard_h.in_mon_ap); 50 | end 51 | foreach (agent_slave_h[i]) begin 52 | // connect out monitors with the sb 53 | agent_slave_h[i].monitor_h.aport.connect(scoreboard_h.out_mon_ap); 54 | end 55 | // conenct sb with coverage 56 | if (cfg.enable_coverage == 1) 57 | scoreboard_h.cov_ap.connect(coverage_h.analysis_export); 58 | `uvm_info("msg", "Connecting ENV Done !", UVM_HIGH) 59 | endfunction: connect_phase 60 | 61 | endclass: hermes_router_env 62 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_monitor.sv: -------------------------------------------------------------------------------- 1 | // the monitor class 2 | class hermes_monitor extends uvm_monitor; 3 | `uvm_component_utils(hermes_monitor); 4 | 5 | uvm_analysis_port #(hermes_packet_t) aport; // used to send the output packet to the sb 6 | 7 | virtual hermes_if dut_vi; 8 | bit [3:0] port; 9 | 10 | function new(string name, uvm_component parent); 11 | super.new(name,parent); 12 | endfunction: new 13 | 14 | function void build_phase(uvm_phase phase); 15 | aport = new("aport", this); 16 | 17 | // print config_db 18 | if (uvm_top.get_report_verbosity_level() >= UVM_HIGH) 19 | print_config(); 20 | 21 | if (!uvm_config_db #(bit [3:0])::get (this,"", "port", port) ) 22 | `uvm_fatal("monitor", "No port"); 23 | `uvm_info("monitor", $sformatf("PORT number: %0d",port), UVM_HIGH) 24 | 25 | if(!uvm_config_db#(virtual hermes_if)::get (this,"", "if", dut_vi)) 26 | `uvm_fatal("monitor", "No if"); 27 | 28 | `uvm_info("msg", "MONITOR Done !!!", UVM_HIGH) 29 | endfunction: build_phase 30 | 31 | /* 32 | function void end_of_elaboration(); 33 | uvm_report_info(get_full_name(),"End_of_elaboration", UVM_LOW); 34 | endfunction 35 | */ 36 | 37 | // extract packets from the output interface and send them to the scoreboard 38 | task run_phase(uvm_phase phase); 39 | hermes_packet_t tx; 40 | int i,size; 41 | @(negedge dut_vi.reset); 42 | @(negedge dut_vi.clock); 43 | 44 | forever 45 | begin 46 | tx = hermes_packet_t::type_id::create("tx"); 47 | `uvm_info("monitor", $sformatf("%s getting new transaction",get_full_name()), UVM_HIGH) 48 | // TODO ideally I would call a task from the BFM to let the monitor cleaner. however, it is not working. 49 | // I will investigate more in the future 50 | //dut_vi.get_packet(tx, port); 51 | 52 | // get the header 53 | @(negedge dut_vi.clock iff (dut_vi.credit == 1'b1 && dut_vi.avail == 1'b1) ); 54 | tx.set_header(dut_vi.data); 55 | `uvm_info("monitor", $sformatf("%s got header %H",get_full_name(),dut_vi.data), UVM_HIGH) 56 | 57 | // get the packet size from the 1st flits 58 | @(negedge dut_vi.clock iff (dut_vi.credit == 1'b1 && dut_vi.avail == 1'b1) ); 59 | size = dut_vi.data; 60 | `uvm_info("monitor", $sformatf("%s got size %0d",get_full_name(),size), UVM_HIGH) 61 | 62 | tx.payload = new[size]; 63 | // get the payload 64 | i=0; 65 | while(i 18 | #include "packet.h" 19 | 20 | SC_MODULE(switch_control){ 21 | 22 | sc_in clock; 23 | sc_in reset; 24 | sc_in h[NPORT]; 25 | sc_out ack_h[NPORT]; 26 | sc_in data[NPORT]; 27 | sc_in sender[NPORT]; 28 | sc_out free[NPORT]; 29 | sc_out mux_in; 30 | sc_out mux_out; 31 | 32 | //sinais do arbitro 33 | sc_signal ask; 34 | sc_signal > sel, prox; 35 | 36 | //sinais do controle 37 | sc_signal dirx,diry; 38 | sc_signal lx,ly,tx,ty; 39 | sc_signal source[NPORT]; 40 | sc_signal sender_ant[NPORT]; 41 | 42 | enum state {S0,S1,S2,S3,S4,S5,S6,S7}; 43 | sc_signal EA,PE; 44 | 45 | int number_pck; 46 | 47 | void controle_comb(); 48 | void controle_sequ(); 49 | void arbitro_comb(); 50 | void arbitro_sequ(); 51 | void state_sequ(); 52 | 53 | //SC_CTOR(switch_control){ 54 | SC_HAS_PROCESS(switch_control); 55 | switch_control(sc_module_name name_, regaddress address_ = 0x0000) : 56 | sc_module(name_), address(address_) 57 | { 58 | //data = new sc_in[NPORT]; 59 | 60 | SC_METHOD(controle_sequ); 61 | sensitive << reset.neg(); 62 | sensitive << clock.pos(); 63 | 64 | SC_METHOD(controle_comb); 65 | sensitive << reset; 66 | sensitive << ask; 67 | sensitive << EA; 68 | sensitive << h[EAST]; 69 | sensitive << h[WEST]; 70 | sensitive << h[NORTH]; 71 | sensitive << h[SOUTH]; 72 | sensitive << h[LOCAL]; 73 | sensitive << lx; 74 | sensitive << ly; 75 | sensitive << tx; 76 | sensitive << ty; 77 | sensitive << free[EAST]; 78 | sensitive << free[WEST]; 79 | sensitive << free[NORTH]; 80 | sensitive << free[SOUTH]; 81 | sensitive << free[LOCAL]; 82 | sensitive << dirx; 83 | sensitive << diry; 84 | 85 | SC_METHOD(arbitro_comb); 86 | sensitive << h[EAST]; 87 | sensitive << h[WEST]; 88 | sensitive << h[NORTH]; 89 | sensitive << h[SOUTH]; 90 | sensitive << h[LOCAL]; 91 | sensitive << sel; 92 | sensitive << data[EAST]; 93 | sensitive << data[WEST]; 94 | sensitive << data[NORTH]; 95 | sensitive << data[SOUTH]; 96 | sensitive << data[LOCAL]; 97 | 98 | SC_METHOD(state_sequ); 99 | sensitive << reset.neg(); 100 | sensitive << clock.neg(); 101 | 102 | } 103 | private: 104 | regaddress address; 105 | 106 | }; 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_master_driver.sv: -------------------------------------------------------------------------------- 1 | // hermes driver for incomming packets 2 | class hermes_master_driver extends hermes_base_driver; 3 | `uvm_component_utils(hermes_master_driver); 4 | 5 | bit [3:0] cycle2send; // send header after some random number of clock cycles, from 0 to 15 cycles 6 | bit [3:0] cycle2flit; // send the size after some random number of clock cycles, from 0 to 15 cycles 7 | bit enabled; // if off, this port is not supposed to send any packet. 8 | 9 | function new(string name, uvm_component parent); 10 | super.new(name, parent); 11 | endfunction : new 12 | 13 | function void build_phase(uvm_phase phase); 14 | super.build_phase(phase); 15 | 16 | // print config_db 17 | if (uvm_top.get_report_verbosity_level() >= UVM_HIGH) 18 | print_config(); 19 | 20 | if(!uvm_config_db#(bit [3:0])::get (this,"", "cycle2send", cycle2send)) 21 | `uvm_fatal("driver", "No cycle2send"); 22 | 23 | if(!uvm_config_db#(bit [3:0])::get (this,"", "cycle2flit", cycle2flit)) 24 | `uvm_fatal("driver", "No cycle2flit"); 25 | 26 | if(!uvm_config_db#(bit) ::get (this,"", "enabled", enabled)) 27 | `uvm_fatal("driver", "No enabled"); 28 | 29 | `uvm_info("msg", "DRIVER Done!!!", UVM_HIGH) 30 | endfunction : build_phase 31 | 32 | task wait_cycles(int cycles); 33 | dut_vi.avail = 1'b0; 34 | repeat (cycles) begin 35 | @(posedge dut_vi.clock); 36 | end 37 | dut_vi.avail = 1'b1; 38 | endtask 39 | 40 | task run_phase(uvm_phase phase); 41 | hermes_packet_t tx; 42 | int i; 43 | // zero the input ports at time zero 44 | dut_vi.avail=0; 45 | dut_vi.data=0; 46 | @(negedge dut_vi.reset); 47 | @(posedge dut_vi.clock); 48 | @(posedge dut_vi.clock); 49 | 50 | forever 51 | begin 52 | tx = hermes_packet_t::type_id::create("tx"); 53 | seq_item_port.get_next_item(tx); 54 | if (!enabled) 55 | `uvm_error("driver", "this driver is disabled and was not supposed to send any packet"); 56 | //dut_vi.send_packet(tx,port); 57 | //`uvm_info("driver", tx.convert2string(), UVM_MEDIUM) 58 | i=0; 59 | 60 | wait_cycles(cycle2send); 61 | dut_vi.data = tx.get_header(); 62 | // wait until there is space in the input buffer 63 | @(negedge dut_vi.clock iff dut_vi.credit == 1'b1); 64 | @(posedge dut_vi.clock); 65 | 66 | wait_cycles(cycle2flit); 67 | dut_vi.data = tx.payload.size(); 68 | @(negedge dut_vi.clock iff dut_vi.credit == 1'b1); 69 | // send payload after some random number of clock cycles, from 0 to 15 cycles 70 | i=0; 71 | while (i 18 | #include "packet.h" 19 | 20 | SC_MODULE(switch_control){ 21 | 22 | sc_in clock; 23 | sc_in reset; 24 | sc_in h[NPORT]; 25 | sc_out ack_h[NPORT]; 26 | sc_in data[NPORT]; 27 | sc_in sender[NPORT]; 28 | sc_out free[NPORT]; 29 | sc_out mux_in; 30 | sc_out mux_out; 31 | 32 | //sinais do arbitro 33 | sc_signal ask; 34 | sc_signal > sel, prox; 35 | 36 | //sinais do controle 37 | sc_signal dirx,diry; 38 | sc_signal lx,ly,tx,ty; 39 | sc_signal source[NPORT]; 40 | sc_signal sender_ant[NPORT]; 41 | 42 | enum state {S0,S1,S2,S3,S4,S5,S6,S7}; 43 | sc_signal EA,PE; 44 | 45 | 46 | int number_pck; 47 | 48 | void controle_comb(); 49 | void controle_sequ(); 50 | void arbitro_comb(); 51 | void arbitro_sequ(); 52 | void state_sequ(); 53 | 54 | //SC_CTOR(switch_control){ 55 | SC_HAS_PROCESS(switch_control); 56 | switch_control(sc_module_name name_, regaddress address_ = 0x0000) : 57 | sc_module(name_), address(address_) 58 | { 59 | //data = new sc_in[NPORT]; 60 | 61 | SC_METHOD(controle_sequ); 62 | sensitive << reset.neg(); 63 | sensitive << clock.pos(); 64 | 65 | SC_METHOD(controle_comb); 66 | sensitive << reset; 67 | sensitive << ask; 68 | sensitive << EA; 69 | sensitive << h[EAST]; 70 | sensitive << h[WEST]; 71 | sensitive << h[NORTH]; 72 | sensitive << h[SOUTH]; 73 | sensitive << h[LOCAL]; 74 | sensitive << lx; 75 | sensitive << ly; 76 | sensitive << tx; 77 | sensitive << ty; 78 | sensitive << free[EAST]; 79 | sensitive << free[WEST]; 80 | sensitive << free[NORTH]; 81 | sensitive << free[SOUTH]; 82 | sensitive << free[LOCAL]; 83 | sensitive << dirx; 84 | sensitive << diry; 85 | 86 | SC_METHOD(arbitro_comb); 87 | sensitive << h[EAST]; 88 | sensitive << h[WEST]; 89 | sensitive << h[NORTH]; 90 | sensitive << h[SOUTH]; 91 | sensitive << h[LOCAL]; 92 | sensitive << sel; 93 | sensitive << data[EAST]; 94 | sensitive << data[WEST]; 95 | sensitive << data[NORTH]; 96 | sensitive << data[SOUTH]; 97 | sensitive << data[LOCAL]; 98 | 99 | SC_METHOD(state_sequ); 100 | sensitive << reset.neg(); 101 | sensitive << clock.neg(); 102 | 103 | } 104 | private: 105 | regaddress address; 106 | 107 | }; 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /noc-router/hermes_router/syn/timing.rep: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Generated by: Genus(TM) Synthesis Solution 17.14-s037_1 3 | Generated on: Jan 26 2019 09:26:44 pm 4 | Module: RouterCC 5 | Operating conditions: _nominal_ 6 | Interconnect mode: global 7 | Area mode: physical library 8 | ============================================================ 9 | 10 | 11 | Path 1: MET (72 ps) Setup Check with Pin SwitchControl_ES_reg[2]/CP->D 12 | Group: clock 13 | Startpoint: (R) FLocal_first_reg[0]/CP 14 | Clock: (R) clock 15 | Endpoint: (R) SwitchControl_ES_reg[2]/D 16 | Clock: (F) clock 17 | 18 | Capture Launch 19 | Clock Edge:+ 1000 0 20 | Src Latency:+ 0 0 21 | Net Latency:+ 0 (I) 0 (I) 22 | Arrival:= 1000 0 23 | 24 | Setup:- 60 25 | Required Time:= 940 26 | Launch Clock:- 0 27 | Data Path:- 868 28 | Slack:= 72 29 | 30 | #-------------------------------------------------------------------------------------------------- 31 | # Timing Point Flags Arc Edge Cell Fanout Load Trans Delay Arrival 32 | # (fF) (ps) (ps) (ps) 33 | #-------------------------------------------------------------------------------------------------- 34 | FLocal_first_reg[0]/CP - - R (arrival) 184 - 0 - 0 35 | FLocal_first_reg[0]/Q - CP->Q R HS65_GSS_SDFPRQX18 9 33.8 40 101 101 36 | FLocal_g5979/Z - A->Z R HS65_GS_NAND2AX7 4 28.8 71 63 164 37 | FLocal_g5961/Z - A->Z F HS65_GS_NOR2X13 16 56.2 59 58 222 38 | FLocal_g5957/Z - S2->Z F HS65_GS_MX41X7 1 4.8 23 68 290 39 | FLocal_g5892/Z - C->Z F HS65_GS_OR4X4 6 27.2 117 109 398 40 | SwitchControl_g8097/Z - A->Z F HS65_GS_OA31X9 1 5.8 24 94 493 41 | SwitchControl_g8060/Z - E->Z R HS65_GS_AOI212X4 1 5.2 70 52 544 42 | SwitchControl_g8027/Z - D->Z F HS65_GS_NAND4ABX3 3 12.6 100 83 627 43 | SwitchControl_g8019/Z - B->Z R HS65_GS_NOR2AX3 4 17.1 156 123 750 44 | SwitchControl_g7967/Z - B->Z F HS65_GS_AOI212X4 1 6.1 63 65 815 45 | SwitchControl_g7948/Z - C->Z R HS65_GS_OAI13X5 1 5.0 59 53 868 46 | SwitchControl_ES_reg[2]/D <<< - R HS65_GS_DFPRQNX9 1 - - 0 868 47 | #-------------------------------------------------------------------------------------------------- 48 | 49 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_typedefs.sv: -------------------------------------------------------------------------------- 1 | 2 | // channel width 3 | parameter FLIT_WIDTH = 16; 4 | // # of port of a router 5 | parameter NPORT = 5; 6 | // max packet size 7 | parameter MAX_FLITS = 128; 8 | // router address 9 | parameter X_ADDR = 1; 10 | parameter Y_ADDR = 1; 11 | 12 | // NoC size . used to set the target routers 13 | parameter X_MAX = 2; 14 | parameter Y_MAX = 2; 15 | 16 | // input port hard constraint 17 | parameter EAST = 0; 18 | parameter WEST = 1; 19 | parameter NORTH = 2; 20 | parameter SOUTH = 3; 21 | parameter LOCAL = 4; 22 | 23 | typedef bit [7:0] bitstream8_t[$]; 24 | typedef bit [3:0] bitstream4_t[$]; 25 | 26 | // given a router addr h, give me the ports that can send packets to it 27 | function bitstream4_t valid_ports(input bit [7:0] h); 28 | bitstream8_t vaddrs; 29 | 30 | valid_ports = {}; 31 | for (int i = 0; i < hermes_pkg::NPORT; i++) begin 32 | vaddrs = {}; 33 | vaddrs = valid_addrs(i); 34 | // if h is in vaddrs, then i is a possible port to send packet to h 35 | if (vaddrs.sum with (item==h)) 36 | valid_ports.push_back(i); 37 | end 38 | //$display("%H --- %p\n",h, valid_ports); 39 | endfunction 40 | 41 | 42 | // create the list of valid target addresses following XY routing algorithm assuming the 'dport' incomming port 43 | function bitstream8_t valid_addrs(input bit [3:0] dport); 44 | bit [3:0] i,j; 45 | //$display("%p",valid_addrs); 46 | valid_addrs = {}; // delete all 47 | if (!(dport >= 0 && dport < hermes_pkg::NPORT)) 48 | `uvm_fatal("", "set the dport before randomization" ) 49 | for (i = 0; i <= hermes_pkg::X_MAX; i++) begin 50 | for (j = 0; j <= hermes_pkg::Y_MAX; j++) begin 51 | // exclude loopback from the local port 52 | if (dport == hermes_pkg::LOCAL) begin 53 | if (!((i == hermes_pkg::X_ADDR) && (j == hermes_pkg::Y_ADDR))) begin 54 | //$display("LOCAL TARGETS %h %0d %0d",{i,j}, i,j ); 55 | valid_addrs.push_back({i,j}); 56 | end 57 | end 58 | // exclude target address to the left hand side of the current router addr 59 | if (dport == hermes_pkg::WEST) begin 60 | if (i >= hermes_pkg::X_ADDR) begin 61 | //$display("WEST TARGETS %h %0d %0d",{i,j}, i,j ); 62 | valid_addrs.push_back({i,j}); 63 | end 64 | end 65 | // exclude target address to the right hand side of the current router addr 66 | if (dport == hermes_pkg::EAST) begin 67 | if (i <= hermes_pkg::X_ADDR) begin 68 | //$display("EAST TARGETS %h %0d %0d",{i,j}, i,j ); 69 | valid_addrs.push_back({i,j}); 70 | end 71 | end 72 | // exclude target address above the current router addr. turns are forbiden 73 | if (dport == hermes_pkg::NORTH) begin 74 | if ((i == hermes_pkg::X_ADDR) && (j <= hermes_pkg::Y_ADDR)) begin 75 | //$display("NORTH TARGETS %h %0d %0d",{i,j}, i,j ); 76 | valid_addrs.push_back({i,j}); 77 | end 78 | end 79 | // exclude target address below the current router addr. turns are forbiden 80 | if (dport == hermes_pkg::SOUTH) begin 81 | if ((i == hermes_pkg::X_ADDR) && (j >= hermes_pkg::Y_ADDR)) begin 82 | //$display("SOUTH TARGETS %h %0d %0d",{i,j}, i,j ); 83 | valid_addrs.push_back({i,j}); 84 | end 85 | end 86 | end // for j 87 | end // for i 88 | endfunction -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/seqs/src/hermes_router_seq_config.sv: -------------------------------------------------------------------------------- 1 | class hermes_router_seq_config extends uvm_object; 2 | `uvm_object_utils(hermes_router_seq_config) 3 | 4 | 5 | //========================== 6 | // seq item knobs 7 | //========================== 8 | // set the input router port where the sequence will inject its packets. default is 0 9 | rand bit [3:0] port; 10 | // set the random distribution for port 11 | bit [3:0] port_dist[hermes_pkg::NPORT] = {1,1,1,1,1}; 12 | 13 | constraint c_port { 14 | port inside { [0:hermes_pkg::NPORT-1] }; 15 | port dist { 16 | 0 := port_dist[0], 17 | 1 := port_dist[1], 18 | 2 := port_dist[2], 19 | 3 := port_dist[3], 20 | 4 := port_dist[4] 21 | }; 22 | } 23 | 24 | // set the packet size 25 | rand hermes_packet_t::packet_size_t p_size; 26 | // weights for packet size 27 | bit [4:0] w_zero=1, w_small=2, w_med=10, w_large=1; 28 | 29 | // choose random packet size with weights 30 | constraint c_p_size { 31 | p_size dist { 32 | //hermes_packet_t::ZERO := w_zero, // not supported by the router. enable only to generated invalid packets 33 | hermes_packet_t::SMALL := w_small, 34 | hermes_packet_t::MED := w_med, 35 | hermes_packet_t::LARGE := w_large 36 | }; 37 | } 38 | 39 | // target packet address 40 | rand bit [7:0] header; 41 | 42 | constraint c_header { 43 | // given the input port 'port', it returns the list of possible target address for the header 44 | header inside {hermes_pkg::valid_addrs(this.port)}; 45 | // the list of valid address depends on the input port 46 | solve port before header; 47 | } 48 | 49 | //========================== 50 | // seq knobs 51 | //========================== 52 | // set the # of packets generated by the sequence 53 | rand int npackets = 1; 54 | 55 | constraint c_packets { 56 | npackets inside {[1:200]}; 57 | npackets dist { 58 | [1:20] := 20, 59 | [21:50] := 10, 60 | [51:100] := 5, 61 | [101:200] := 1 62 | }; 63 | } 64 | 65 | 66 | function void do_copy( uvm_object rhs ); 67 | hermes_router_seq_config that; 68 | 69 | if ( ! $cast( that, rhs ) ) begin 70 | `uvm_error( get_name(), "rhs is not a hermes_router_seq_config" ) 71 | return; 72 | end 73 | 74 | super.do_copy( rhs ); 75 | this.port = that.port; 76 | this.port_dist = that.port_dist; 77 | this.p_size = that.p_size; 78 | this.w_zero = that.w_zero; 79 | this.w_small = that.w_small; 80 | this.w_med = that.w_med; 81 | this.w_large = that.w_large; 82 | this.header = that.header; 83 | this.npackets = that.npackets; 84 | endfunction: do_copy 85 | 86 | 87 | virtual function string convert2string(); 88 | string s = super.convert2string(); 89 | s = { s, $psprintf( "\n port : %0d", port) }; 90 | s = { s, $psprintf( "\n p_size : %0d", p_size) }; 91 | s = { s, $psprintf( "\n header : %H" , header) }; 92 | s = { s, $psprintf( "\n valid_addr : %p" , hermes_pkg::valid_addrs(port)) }; 93 | s = { s, $psprintf( "\n npackets : %0d", npackets) }; 94 | return s; 95 | endfunction: convert2string 96 | 97 | function new( string name = "" ); 98 | super.new( name ); 99 | endfunction: new 100 | 101 | endclass 102 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_agent.sv: -------------------------------------------------------------------------------- 1 | class hermes_agent extends uvm_agent; 2 | `uvm_component_utils(hermes_agent); 3 | 4 | packet_sequencer sequencer_h; 5 | hermes_base_driver driver_h; 6 | hermes_monitor monitor_h; 7 | hermes_agent_config cfg; 8 | string mode; // agent mode = master / slave. master mode uses the master driver and the slave mode uses the slave driver 9 | 10 | 11 | function new(string name, uvm_component parent); 12 | super.new(name,parent); 13 | endfunction: new 14 | 15 | function void build_phase(uvm_phase phase); 16 | virtual hermes_if duv_if; 17 | bit [3:0] port; 18 | //print config_db 19 | if (uvm_top.get_report_verbosity_level() >= UVM_HIGH) 20 | print_config(); 21 | 22 | if (!uvm_config_db #(hermes_agent_config)::get (this,"", "config", cfg) ) 23 | `uvm_fatal("agent", "No cfg"); 24 | 25 | if (!uvm_config_db #(virtual hermes_if)::get (this,"", "if", duv_if) ) 26 | `uvm_fatal("agent", "No agent_if"); 27 | // set the correct interface to its monitor and agent. 28 | uvm_config_db #(virtual hermes_if)::set (this,"monitor", "if", duv_if); 29 | uvm_config_db #(virtual hermes_if)::set (this,"driver", "if", duv_if); 30 | 31 | if (!uvm_config_db #(string)::get (this,"", "mode", mode) ) 32 | `uvm_fatal("agent", "No mode"); 33 | if (mode != "slave" && mode != "master") 34 | `uvm_fatal("agent", "unexpected mode value"); 35 | 36 | // port id 37 | if (!uvm_config_db #(bit [3:0])::get (this,"", "port", port) ) 38 | `uvm_fatal("agent", "No port"); 39 | `uvm_info("agent", $sformatf("PORT number: %0d",port), UVM_HIGH) 40 | // set the correct interface to its monitor and agent. 41 | uvm_config_db #(bit [3:0])::set (this,"monitor", "port", port); 42 | uvm_config_db #(bit [3:0])::set (this,"driver", "port", port); 43 | 44 | // create and set drivers 45 | if (cfg.is_active) begin 46 | // select the driver behavior depending on the agent direction 47 | if (mode == "master") begin 48 | // only the input agent has an actual driver/sequencer 49 | sequencer_h = packet_sequencer::type_id::create("sequencer", this); 50 | set_inst_override_by_type( {get_full_name(), ".driver"}, hermes_base_driver::get_type(), hermes_master_driver::get_type() ); 51 | driver_h = hermes_master_driver::type_id::create("driver", this); 52 | uvm_config_db #(bit [3:0])::set (this,"driver", "cycle2send", cfg.cycle2send); 53 | uvm_config_db #(bit [3:0])::set (this,"driver", "cycle2flit", cfg.cycle2flit); 54 | uvm_config_db #(bit) ::set (this,"driver", "enabled", cfg.master_driver_enabled); 55 | end 56 | else if (mode == "slave") begin 57 | // override the behavior of the driver to an slave agent 58 | set_inst_override_by_type( {get_full_name(), ".driver"}, hermes_base_driver::get_type(), hermes_slave_driver::get_type() ); 59 | driver_h = hermes_slave_driver::type_id::create("driver", this); 60 | uvm_config_db #(bit [3:0])::set (this,"driver", "cred_distrib", cfg.cred_distrib); 61 | end 62 | end 63 | 64 | // create and set monitors 65 | monitor_h = hermes_monitor::type_id::create("monitor", this); 66 | `uvm_info("msg", "Building Agent DONE!", UVM_HIGH) 67 | endfunction: build_phase 68 | 69 | function void connect_phase(uvm_phase phase); 70 | // the output drinver does not use sequence. so, no need to connect 71 | if (cfg.is_active && mode == "master") begin 72 | driver_h.seq_item_port.connect(sequencer_h.seq_item_export); 73 | end 74 | `uvm_info("msg", "Connecting Agent DONE!", UVM_HIGH) 75 | endfunction: connect_phase 76 | 77 | endclass: hermes_agent 78 | -------------------------------------------------------------------------------- /noc-router/hermes_router/tb/tests/src/bottleneck_test.sv: -------------------------------------------------------------------------------- 1 | /* 2 | test that injects packets in all input ports in parallel to the same target address, creating a bottleneck 3 | */ 4 | class bottleneck_test extends base_test; 5 | `uvm_component_utils(bottleneck_test) 6 | 7 | // all valid ports will send packets to this address 8 | // configure (in command line with, e,g, +uvm_set_config_int=*,target_address,1) the test to change the target router 9 | // the parameter must be a valid router address, i.e. 8'h00, 8'h01, ..., 8'h11, ..., 8'h22, 10 | bit [7:0] target_address; 11 | 12 | function new (string name, uvm_component parent); 13 | super.new(name,parent); 14 | endfunction : new 15 | 16 | function void build_phase(uvm_phase phase); 17 | bit [7:0] valid_addr []= '{8'h00, 8'h01,8'h02, 8'h10, 8'h11,8'h12, 8'h20, 8'h21,8'h22}; 18 | bit [7:0] aux[]; 19 | super.build_phase(phase); 20 | 21 | // in this test, all agents have the same behaviour 22 | foreach(acfg[i]) begin 23 | if( !acfg[i].randomize() with { 24 | cycle2send == 1; // a new packet is sent 1 clock cycle after the last one 25 | cycle2flit == 0; // a new flit is sent every cycle after the transaction starts 26 | cred_distrib == 5; // the slave ports have 50% availability 27 | } 28 | ) 29 | `uvm_error("test", "invalid agent cfg randomization"); 30 | end 31 | 32 | if(!uvm_config_db #(uvm_bitstream_t)::get(null, "", "target_address", target_address)) 33 | target_address = 8'h11; // defaul value, the central router 34 | else begin 35 | // check if the target address is valid 36 | aux = valid_addr.find(x) with (x == target_address); 37 | if (aux.size == 0 ) 38 | `uvm_fatal("test", $sformatf("invalid target address 8'h%H",target_address)); 39 | end 40 | 41 | 42 | 43 | 44 | // last thing to do is to the agent configuration with config_db 45 | uvm_config_db#(hermes_router_env_config)::set(null, "uvm_test_top.env", "config", env_cfg); 46 | env_h = hermes_router_env::type_id::create("env", this); 47 | endfunction 48 | 49 | task run_phase(uvm_phase phase); 50 | parallel_seq seq = parallel_seq::type_id::create("seq"); 51 | hermes_router_seq_config cfg[hermes_pkg::NPORT]; 52 | bit [3:0] val_ports[$]; 53 | bit [3:0] aux[$]; 54 | 55 | // get all ports that can (due to xy routing algo and the loopback design constraint) send packet to this address 56 | val_ports = hermes_pkg::valid_ports(target_address); 57 | 58 | foreach(cfg[i]) begin 59 | // check if 'i' is a valid port 60 | aux = val_ports.find(x) with (x == i); 61 | if (aux.size > 0 ) begin 62 | // only the valid seq are configured 63 | seq.enable_port[i] = 1; 64 | cfg[i] = hermes_router_seq_config::type_id::create($sformatf("seq_cfg[%0d]",i)); 65 | if( !cfg[i].randomize() with { 66 | // number of packets to be simulated per sequencer 67 | npackets == 5; 68 | port == i; 69 | // all valid ports will send packets to the same router address 70 | header == target_address; 71 | // only small packets 72 | p_size == hermes_packet_t::SMALL; 73 | } 74 | ) 75 | `uvm_error("test", "invalid cfg randomization"); 76 | // send the sequence configuration to each sequencer 77 | uvm_config_db#(hermes_router_seq_config)::set(null, $sformatf("uvm_test_top.env.agent_master_%0d.sequencer",i), "config",cfg[i]); 78 | end else 79 | // disable the sequences that will not be used 80 | seq.enable_port[i] = 0; 81 | end 82 | 83 | phase.raise_objection(this); 84 | init_vseq(seq); 85 | seq.start(null); 86 | // end the simulation a little bit latter 87 | phase.phase_done.set_drain_time(this, 100ns); 88 | phase.drop_objection(this); 89 | endtask 90 | 91 | endclass: bottleneck_test 92 | -------------------------------------------------------------------------------- /mult/tb/common/mult_neg_seq.sv: -------------------------------------------------------------------------------- 1 | class mult_neg_seq extends uvm_sequence #(mult_input_t); 2 | `uvm_object_utils(mult_neg_seq) 3 | 4 | function new(string name = ""); 5 | super.new(name); 6 | endfunction: new 7 | 8 | task body; 9 | mult_input_t tx; 10 | 11 | // a == b == -1 12 | tx = mult_input_t::type_id::create("tx"); 13 | start_item(tx); 14 | assert(tx.randomize() with {tx.A == -1; tx.B == -1;}); 15 | finish_item(tx); 16 | // a == -1, b == 1 17 | tx = mult_input_t::type_id::create("tx"); 18 | start_item(tx); 19 | assert(tx.randomize() with {tx.A == -1; tx.B == 1;}); 20 | finish_item(tx); 21 | // a == 1, b == -1 22 | tx = mult_input_t::type_id::create("tx"); 23 | start_item(tx); 24 | assert(tx.randomize() with {tx.A == 1; tx.B == -1;}); 25 | finish_item(tx); 26 | // a == 0, b == -1 27 | tx = mult_input_t::type_id::create("tx"); 28 | start_item(tx); 29 | assert(tx.randomize() with {tx.A == 0; tx.B == -1;}); 30 | finish_item(tx); 31 | // a == -1, b == 0 32 | tx = mult_input_t::type_id::create("tx"); 33 | start_item(tx); 34 | assert(tx.randomize() with {tx.A == -1; tx.B == 0;}); 35 | finish_item(tx); 36 | 37 | // a == -1 38 | repeat(10) begin 39 | tx = mult_input_t::type_id::create("tx"); 40 | start_item(tx); 41 | assert(tx.randomize() with {tx.A == -1;}); 42 | finish_item(tx); 43 | end 44 | // b == -1 45 | repeat(10) begin 46 | tx = mult_input_t::type_id::create("tx"); 47 | start_item(tx); 48 | assert(tx.randomize() with {tx.B == -1;}); 49 | finish_item(tx); 50 | end 51 | // a == neg, b== pos 52 | repeat(10) begin 53 | tx = mult_input_t::type_id::create("tx"); 54 | start_item(tx); 55 | assert(tx.randomize() with {tx.A inside {[$:-2]};}); 56 | finish_item(tx); 57 | end 58 | // a == pos, b == neg 59 | repeat(10) begin 60 | tx = mult_input_t::type_id::create("tx"); 61 | start_item(tx); 62 | assert(tx.randomize() with {tx.B inside {[$:-2]};}); 63 | finish_item(tx); 64 | end 65 | 66 | // a == 0 , b == neg 67 | repeat(10) begin 68 | tx = mult_input_t::type_id::create("tx"); 69 | start_item(tx); 70 | assert(tx.randomize() with {tx.A == 0; tx.B inside {[$:-2]};}); 71 | finish_item(tx); 72 | end 73 | // a == neg , b == 0 74 | repeat(10) begin 75 | tx = mult_input_t::type_id::create("tx"); 76 | start_item(tx); 77 | assert(tx.randomize() with {tx.A inside {[$:-2]}; tx.B == 0;}); 78 | finish_item(tx); 79 | end 80 | 81 | // a == -1 , b == neg 82 | repeat(10) begin 83 | tx = mult_input_t::type_id::create("tx"); 84 | start_item(tx); 85 | assert(tx.randomize() with {tx.A == -1; tx.B inside {[$:-2]};}); 86 | finish_item(tx); 87 | end 88 | // a == neg , b == -1 89 | repeat(10) begin 90 | tx = mult_input_t::type_id::create("tx"); 91 | start_item(tx); 92 | assert(tx.randomize() with {tx.A inside {[$:-2]}; tx.B == -1;}); 93 | finish_item(tx); 94 | end 95 | // a == b == neg 96 | repeat(10) begin 97 | tx = mult_input_t::type_id::create("tx"); 98 | start_item(tx); 99 | assert(tx.randomize() with {tx.B inside {[$:-2]}; tx.A inside {[$:-2]};}); 100 | finish_item(tx); 101 | end 102 | 103 | // a == 1 , b == neg 104 | repeat(10) begin 105 | tx = mult_input_t::type_id::create("tx"); 106 | start_item(tx); 107 | assert(tx.randomize() with {tx.A == 1; tx.B inside {[$:-2]};}); 108 | finish_item(tx); 109 | end 110 | // a == neg , b == 1 111 | repeat(10) begin 112 | tx = mult_input_t::type_id::create("tx"); 113 | start_item(tx); 114 | assert(tx.randomize() with {tx.A inside {[$:-2]}; tx.B == 1;}); 115 | finish_item(tx); 116 | end 117 | 118 | endtask: body 119 | 120 | endclass: mult_neg_seq 121 | 122 | -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/run.do: -------------------------------------------------------------------------------- 1 | #------------------------------------------------ 2 | # these are the knobs you might want to change. 3 | #------------------------------------------------ 4 | set SEED "random" 5 | set VERBOSITY "UVM_LOW" 6 | # set true to enable coverage 7 | set COVERAGE "true" 8 | # set true to simulate RTL, otherwise, simulates the netlist 9 | set RTL_SIM "true" 10 | # set true to simulate for debug, otherwise simulate for speed/regression 11 | set DEBUG_SIM "true" 12 | 13 | # lists of tests to be executed 14 | #set TEST_NAMES {parallel_test} 15 | set TEST_NAMES {repeat_test parallel_test sequential_test random_test bottleneck_test} 16 | 17 | set ::env(VIP_LIBRARY_HOME) /home/ale/repos/verif/uvm-basics/noc-router/vips 18 | set ::env(PROJECT_DIR) /home/ale/repos/verif/uvm-basics/noc-router/hermes_router 19 | #set ::env(VIP_LIBRARY_HOME) /home/ale/repos/study/uvm-basics/noc-router/vips 20 | #set ::env(PROJECT_DIR) /home/ale/repos/study/uvm-basics/noc-router/hermes_router 21 | 22 | file delete -force *~ *.ucdb vsim.dbg *.vstf *.log work *.mem *.transcript.txt certe_dump.xml *.wlf covhtmlreport VRMDATA 23 | file delete -force design.bin qwave.db dpiheader.h visualizer*.ses 24 | file delete -force veloce.med veloce.wave veloce.map tbxbindings.h modelsim.ini edsenv velrunopts.ini 25 | file delete -force sv_connect.* 26 | vlib work 27 | # interfaces 28 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(VIP_LIBRARY_HOME)/hermes_pkg -F $env(VIP_LIBRARY_HOME)/hermes_pkg/hvl.f 29 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(VIP_LIBRARY_HOME)/hermes_pkg -F $env(VIP_LIBRARY_HOME)/hermes_pkg/hdl.f 30 | 31 | # environment 32 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(VIP_LIBRARY_HOME)/hermes_router_env_pkg $env(VIP_LIBRARY_HOME)/hermes_router_env_pkg/hermes_router_env_pkg.sv 33 | 34 | # tests and seqs 35 | #vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/tb/parameters $env(PROJECT_DIR)/tb/parameters/wb2spi_parameters_pkg.sv 36 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/tb/seqs $env(PROJECT_DIR)/tb/seqs/hermes_router_seq_pkg.sv 37 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/tb/tests $env(PROJECT_DIR)/tb/tests/hermes_router_test_pkg.sv 38 | 39 | #dut 40 | if {[string equal $RTL_SIM "true"]} { 41 | vcom -suppress 2223 -suppress 2286 -F $env(PROJECT_DIR)/rtl/hdl_vhd.f 42 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/rtl -F $env(PROJECT_DIR)/rtl/hdl_v.f 43 | } else { 44 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/syn -F $env(PROJECT_DIR)/syn/hdl_v.f 45 | } 46 | 47 | #testbench 48 | vlog -sv -suppress 2223 -suppress 2286 +incdir+$env(PROJECT_DIR)/tb/testbench $env(PROJECT_DIR)/tb/testbench/top.sv 49 | 50 | if {[string equal $DEBUG_SIM "true"]} { 51 | vopt +acc top -o optimized_debug_top_tb 52 | set top optimized_debug_top_tb 53 | } else { 54 | vopt top -o optimized_batch_top_tb 55 | set top optimized_batch_top_tb 56 | } 57 | 58 | # execute all the tests in TEST_NAME 59 | for {set i 0} {$i<[llength $TEST_NAMES]} {incr i} { 60 | set test [lindex $TEST_NAMES $i] 61 | if {[string equal $RTL_SIM "true"]} { 62 | if {[string equal $DEBUG_SIM "true"]} { 63 | vsim -sv_seed $SEED +UVM_TESTNAME=$test +UVM_VERBOSITY=$VERBOSITY -permit_unmatched_virtual_intf +notimingchecks -suppress 8887 -uvmcontrol=all -msgmode both -classdebug -assertdebug +uvm_set_config_int=*,enable_transaction_viewing,1 $top 64 | } else { 65 | vsim -sv_seed $SEED +UVM_TESTNAME=$test +UVM_VERBOSITY=$VERBOSITY $top 66 | } 67 | } else { 68 | # netlist simulation 69 | vsim -sdfmax /top/dut1/CC/=../syn/src/layout/RouterCC.sdf -sv_seed $SEED +UVM_TESTNAME=$test +UVM_VERBOSITY=$VERBOSITY $top 70 | } 71 | #onbreak {resume} 72 | onfinish stop; 73 | log /* -r 74 | do shutup.do 75 | do wave_full.do 76 | run -all 77 | if {[string equal $COVERAGE "true"]} { 78 | coverage attribute -name TESTNAME -value $test 79 | coverage save ${test}.ucdb 80 | vcover merge -out hermes_router.ucdb ${test}.ucdb 81 | } 82 | } 83 | 84 | if {[string equal $COVERAGE "true"]} { 85 | vcover report hermes_router.ucdb -cvg -details 86 | } 87 | -------------------------------------------------------------------------------- /mult/dut/mult_div/mudi64.v: -------------------------------------------------------------------------------- 1 | //top module, a 64-bit signed multiplier and divider 2 | 3 | `timescale 1ns/10ps 4 | 5 | module mudi64 (result, opera1, opera2, muordi, clock, reset, start, valid); 6 | parameter full = 63; //full length of data bits 64-1 7 | parameter half = 31; //half length of data bits 32-1 8 | output [full:0] result; 9 | output valid; 10 | input [half:0] opera1; 11 | input [full:0] opera2; 12 | input muordi, clock, reset, start; 13 | reg [half:0] A, times; 14 | reg [full:0] result, B; 15 | reg valid, OPE, signA, signB, cin; 16 | reg [1:0] wait_state; 17 | wire [half:0] D, E, F, new_remainder, new_times, AA, G; 18 | wire [full:0] BB; 19 | wire cout, cout1, cout2; 20 | 21 | add32 mu_main (.sum(D), .cout(cout1), .a(A), .b(B[full:half+1]), .cin(cin)); 22 | add32 di_main_add (.sum(E), .cout(cout), .a(A), .b(B[full:half+1]), .cin(1'b0)); 23 | add32 di_main_sub (.sum(F), .cout(cout), .a(~A), .b(B[full:half+1]), .cin(1'b1)); 24 | add32 counter (.sum(new_times), .cout(cout), .a(times), .b(32'b1), .cin(1'b0)); 25 | add32 neg_A (.sum(AA), .cout(cout), .a(~A), .b(32'b0), .cin(1'b1)); 26 | add32 neg_B1 (.sum(BB[half:0]), .cout(cout2), .a(~B[half:0]), .b(32'b0), .cin(1'b1)); 27 | add32 neg_B2 (.sum(BB[full:half+1]), .cout(cout), .a(~B[full:half+1]), .b(32'b0), .cin(cout2)); 28 | add32 neg_di (.sum(G), .cout(cout), .a(~E), .b(32'b0), .cin(1'b1)); 29 | 30 | assign new_remainder = OPE ? F : E; 31 | 32 | always @(posedge clock or posedge reset) begin 33 | // $monitor("times=%d, A=%b, B=%b,%h, result=%b",times,A,B,B,result); 34 | if (reset) begin 35 | result = 0; 36 | valid =0; 37 | cin = 0; 38 | times = 0; 39 | OPE = 0; 40 | A = 0; 41 | B = 0; 42 | signA = 0; 43 | signB = 0; 44 | wait_state = 0; 45 | end 46 | else if (start==0 & wait_state==0) begin //bounce down the button 47 | result = 0; 48 | valid = 0; 49 | cin = 0; 50 | times = 0; 51 | OPE = muordi; //change all muordi to 0 or 1 can go through all process only multiplier or divider 52 | A = opera1; 53 | B = opera2; 54 | signA = A[half]; 55 | signB = muordi ? B[full] : B[half]; 56 | wait_state = 1; 57 | end 58 | else if (start==0 & wait_state==1) begin 59 | wait_state = 2; 60 | A = signA ? AA : A; 61 | B = signB ? BB : B; 62 | end 63 | else if (start==0 & wait_state==2) times = 0; 64 | else if (start) begin //bounce up the button 65 | if (~muordi) begin //mutiplier 66 | OPE = B[0]; 67 | if (times> 1; 69 | B[full-1:half] = OPE ? D : B[full-1:half]; 70 | B[full] = OPE ? cout1 : B[full]; 71 | times = new_times; 72 | end 73 | else if (times==half+1) begin 74 | result = (signA^signB) ? BB : B; 75 | valid = 1; 76 | times = new_times; 77 | // wait (~start); 78 | end 79 | else wait_state = 0; 80 | end 81 | else begin //divider 82 | B[full:half+1] = new_remainder; 83 | OPE = ~B[full]; 84 | if (timesE, N->W, S->E, and S-W turns are invalid. In addition, due to an implementation limitation, the router does not support loopbacks, i.e. send packet to the same direction of the incoming packet such as, for instance, N->N. 33 | 34 | cg_noc_addr checks whether packets were sent to all possible NoC address, i.e. from 0 to 15 lines to 0 to 15 columns. Four bits are used for lines and four bits for columns. The first address is 8'h00 and the last one is 8'hff. 35 | 36 | cg_packet_sizes checks whether packets of all lengths were sent. The minimum size is 1 and the maximum in 127 flits. 37 | 38 | ### hermes_router_scoreboard 39 | 40 | The scoreboard has two analysis ports (*in_mon_ap* and *out_mon_ap*) for receiving transactions from the monitors. The monitor of the master agent sends transactions to the in_mon_ap port and the monitor from the slave agent sends transactions to the out_mon_ap port. Both ports are attached to FIFOs. When the in_mon_ap port receives a transaction, it is temporally stored in the *input_packet_queue* until the matching packet is captured in the out_mon_ap port. 41 | 42 | The *run_phase* executes two task in parallel: get_input_data and get_output_data. The former, as mentioned before, feeds the input_packet_queue until verification. The later performs the actual packet verification. It checks whether the new transaction at out_mon_ap matches with any transaction in the input_packet_queue. The Hermes packet does not include a sequence number to ease this comparison. Thus, the entire packet is compared, all flits are compared. The next check is related to the routing algorithm. A transaction has two fields called master_port and slave_port related to the identification of the master and slave port, respectively. With these two fields as parameter, the function *check_xy_routing* returns true if this turn is valid for XY routing algorithm. 43 | 44 | By the end of the simulation, in the *extract_phase*, the scoreboard prints a summary of the simulation including information such as the number of sent/received packets, number of matches/mismatches, and the number of transactions left in the input_packet_queue. An error occurs if the number of sent/received/matches are different and if the number of mismatches / transactions left in the input_packet_queue is different from zero. 45 | -------------------------------------------------------------------------------- /uart/uart.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------- 2 | // Design Name : uart 3 | // File Name : uart.v 4 | // Function : Simple UART 5 | // Coder : Deepak Kumar Tala 6 | //----------------------------------------------------- 7 | module uart ( 8 | reset , 9 | txclk , 10 | ld_tx_data , 11 | tx_data , 12 | tx_enable , 13 | tx_out , 14 | tx_empty , 15 | rxclk , 16 | uld_rx_data , 17 | rx_data , 18 | rx_enable , 19 | rx_in , 20 | rx_empty 21 | ); 22 | // Port declarations 23 | input reset ; 24 | input txclk ; 25 | input ld_tx_data ; 26 | input [7:0] tx_data ; 27 | input tx_enable ; 28 | output tx_out ; 29 | output tx_empty ; 30 | input rxclk ; 31 | input uld_rx_data ; 32 | output [7:0] rx_data ; 33 | input rx_enable ; 34 | input rx_in ; 35 | output rx_empty ; 36 | 37 | // Internal Variables 38 | reg [7:0] tx_reg ; 39 | reg tx_empty ; 40 | reg tx_over_run ; 41 | reg [3:0] tx_cnt ; 42 | reg tx_out ; 43 | reg [7:0] rx_reg ; 44 | reg [7:0] rx_data ; 45 | reg [3:0] rx_sample_cnt ; 46 | reg [3:0] rx_cnt ; 47 | reg rx_frame_err ; 48 | reg rx_over_run ; 49 | reg rx_empty ; 50 | reg rx_d1 ; 51 | reg rx_d2 ; 52 | reg rx_busy ; 53 | 54 | // UART RX Logic 55 | always @ (posedge rxclk or posedge reset) 56 | if (reset) begin 57 | rx_reg <= 0; 58 | rx_data <= 0; 59 | rx_sample_cnt <= 0; 60 | rx_cnt <= 0; 61 | rx_frame_err <= 0; 62 | rx_over_run <= 0; 63 | rx_empty <= 1; 64 | rx_d1 <= 1; 65 | rx_d2 <= 1; 66 | rx_busy <= 0; 67 | end else begin 68 | // Synchronize the asynch signal 69 | rx_d1 <= rx_in; 70 | rx_d2 <= rx_d1; 71 | // Uload the rx data 72 | if (uld_rx_data) begin 73 | rx_data <= rx_reg; 74 | rx_empty <= 1; 75 | end 76 | // Receive data only when rx is enabled 77 | if (rx_enable) begin 78 | // Check if just received start of frame 79 | if (!rx_busy && !rx_d2) begin 80 | rx_busy <= 1; 81 | rx_sample_cnt <= 1; 82 | rx_cnt <= 0; 83 | end 84 | // Start of frame detected, Proceed with rest of data 85 | if (rx_busy) begin 86 | rx_sample_cnt <= rx_sample_cnt + 1; 87 | // Logic to sample at middle of data 88 | if (rx_sample_cnt == 7) begin 89 | if ((rx_d2 == 1) && (rx_cnt == 0)) begin 90 | rx_busy <= 0; 91 | end else begin 92 | rx_cnt <= rx_cnt + 1; 93 | // Start storing the rx data 94 | if (rx_cnt > 0 && rx_cnt < 9) begin 95 | rx_reg[rx_cnt - 1] <= rx_d2; 96 | end 97 | if (rx_cnt == 9) begin 98 | rx_busy <= 0; 99 | // Check if End of frame received correctly 100 | if (rx_d2 == 0) begin 101 | rx_frame_err <= 1; 102 | end else begin 103 | rx_empty <= 0; 104 | rx_frame_err <= 0; 105 | // Check if last rx data was not unloaded, 106 | rx_over_run <= (rx_empty) ? 0 : 1; 107 | end 108 | end 109 | end 110 | end 111 | end 112 | end 113 | if (!rx_enable) begin 114 | rx_busy <= 0; 115 | end 116 | end 117 | 118 | // UART TX Logic 119 | always @ (posedge txclk or posedge reset) 120 | if (reset) begin 121 | tx_reg <= 0; 122 | tx_empty <= 1; 123 | tx_over_run <= 0; 124 | tx_out <= 1; 125 | tx_cnt <= 0; 126 | end else begin 127 | if (ld_tx_data) begin 128 | if (!tx_empty) begin 129 | tx_over_run <= 0; 130 | end else begin 131 | tx_reg <= tx_data; 132 | tx_empty <= 0; 133 | end 134 | end 135 | if (tx_enable && !tx_empty) begin 136 | tx_cnt <= tx_cnt + 1; 137 | if (tx_cnt == 0) begin 138 | tx_out <= 0; 139 | end 140 | if (tx_cnt > 0 && tx_cnt < 9) begin 141 | tx_out <= tx_reg[tx_cnt -1]; 142 | end 143 | if (tx_cnt == 9) begin 144 | tx_out <= 1; 145 | tx_cnt <= 0; 146 | tx_empty <= 1; 147 | end 148 | end 149 | if (!tx_enable) begin 150 | tx_cnt <= 0; 151 | end 152 | end 153 | 154 | endmodule 155 | -------------------------------------------------------------------------------- /noc-router/hermes_router/sim/wave_full.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | quietly WaveActivateNextPane {} 0 3 | add wave -noupdate /top/dut1/CC/address 4 | add wave -noupdate /top/dut1/clock 5 | add wave -noupdate /top/dut1/reset 6 | add wave -noupdate -divider -height 50 INPUT 7 | add wave -noupdate /top/dut1/clock_rx 8 | add wave -noupdate -expand /top/dut1/rx 9 | add wave -noupdate -expand /top/dut1/data_in 10 | add wave -noupdate /top/dut1/credit_o 11 | add wave -noupdate -height 50 /uvm_root/uvm_test_top/env/agent_master_0/sequencer/seq_0 12 | add wave -noupdate -height 50 /uvm_root/uvm_test_top/env/agent_master_1/sequencer/seq_1 13 | add wave -noupdate -height 50 /uvm_root/uvm_test_top/env/agent_master_2/sequencer/seq_2 14 | add wave -noupdate -height 50 /uvm_root/uvm_test_top/env/agent_master_3/sequencer/seq_3 15 | add wave -noupdate -height 50 /uvm_root/uvm_test_top/env/agent_master_4/sequencer/seq_4 16 | add wave -noupdate -divider -height 50 OUTPUT 17 | add wave -noupdate /top/dut1/clock_tx 18 | add wave -noupdate -expand /top/dut1/tx 19 | add wave -noupdate -expand /top/dut1/data_out 20 | add wave -noupdate -expand /top/dut1/credit_i 21 | add wave -noupdate -divider -height 50 BUFFERS 22 | add wave -noupdate /top/dut1/CC/FEast/EA 23 | add wave -noupdate /top/dut1/CC/FEast/buf 24 | add wave -noupdate /top/dut1/CC/FEast/first 25 | add wave -noupdate /top/dut1/CC/FEast/last 26 | add wave -noupdate /top/dut1/CC/FEast/counter_flit 27 | add wave -noupdate /top/dut1/CC/FEast/tem_espaco 28 | add wave -noupdate /top/dut1/CC/FWest/EA 29 | add wave -noupdate /top/dut1/CC/FWest/buf 30 | add wave -noupdate /top/dut1/CC/FWest/first 31 | add wave -noupdate /top/dut1/CC/FWest/last 32 | add wave -noupdate /top/dut1/CC/FWest/tem_espaco 33 | add wave -noupdate /top/dut1/CC/FWest/counter_flit 34 | add wave -noupdate /top/dut1/CC/FNorth/EA 35 | add wave -noupdate /top/dut1/CC/FNorth/buf 36 | add wave -noupdate /top/dut1/CC/FNorth/first 37 | add wave -noupdate /top/dut1/CC/FNorth/last 38 | add wave -noupdate /top/dut1/CC/FNorth/tem_espaco 39 | add wave -noupdate /top/dut1/CC/FNorth/counter_flit 40 | add wave -noupdate /top/dut1/CC/FSouth/EA 41 | add wave -noupdate /top/dut1/CC/FSouth/buf 42 | add wave -noupdate /top/dut1/CC/FSouth/first 43 | add wave -noupdate /top/dut1/CC/FSouth/last 44 | add wave -noupdate /top/dut1/CC/FSouth/tem_espaco 45 | add wave -noupdate /top/dut1/CC/FSouth/counter_flit 46 | add wave -noupdate /top/dut1/CC/FLocal/EA 47 | add wave -noupdate /top/dut1/CC/FLocal/buf 48 | add wave -noupdate /top/dut1/CC/FLocal/first 49 | add wave -noupdate /top/dut1/CC/FLocal/last 50 | add wave -noupdate /top/dut1/CC/FLocal/tem_espaco 51 | add wave -noupdate /top/dut1/CC/FLocal/counter_flit 52 | add wave -noupdate -divider -height 50 SWITCH 53 | add wave -noupdate /top/dut1/CC/SwitchControl/h 54 | add wave -noupdate /top/dut1/CC/SwitchControl/ack_h 55 | add wave -noupdate /top/dut1/CC/SwitchControl/address 56 | add wave -noupdate /top/dut1/CC/SwitchControl/data 57 | add wave -noupdate /top/dut1/CC/SwitchControl/sender 58 | add wave -noupdate /top/dut1/CC/SwitchControl/free 59 | add wave -noupdate /top/dut1/CC/SwitchControl/mux_in 60 | add wave -noupdate /top/dut1/CC/SwitchControl/mux_out 61 | add wave -noupdate /top/dut1/CC/SwitchControl/ES 62 | add wave -noupdate /top/dut1/CC/SwitchControl/ask 63 | add wave -noupdate /top/dut1/CC/SwitchControl/sel 64 | add wave -noupdate /top/dut1/CC/SwitchControl/prox 65 | add wave -noupdate /top/dut1/CC/SwitchControl/incoming 66 | add wave -noupdate /top/dut1/CC/SwitchControl/header 67 | add wave -noupdate /top/dut1/CC/SwitchControl/dirx 68 | add wave -noupdate /top/dut1/CC/SwitchControl/diry 69 | add wave -noupdate /top/dut1/CC/SwitchControl/lx 70 | add wave -noupdate /top/dut1/CC/SwitchControl/ly 71 | add wave -noupdate /top/dut1/CC/SwitchControl/tx 72 | add wave -noupdate /top/dut1/CC/SwitchControl/ty 73 | add wave -noupdate /top/dut1/CC/SwitchControl/auxfree 74 | add wave -noupdate /top/dut1/CC/SwitchControl/source 75 | add wave -noupdate /top/dut1/CC/SwitchControl/sender_ant 76 | add wave -noupdate /top/dut1/CC/SwitchControl/clock 77 | add wave -noupdate /uvm_root/uvm_test_top/env/scoreboard/in_mon_ap 78 | add wave -noupdate /uvm_root/uvm_test_top/env/scoreboard/out_mon_ap 79 | TreeUpdate [SetDefaultTree] 80 | WaveRestoreCursors {{Cursor 1} {51 ns} 0} 81 | quietly wave cursor active 1 82 | configure wave -namecolwidth 266 83 | configure wave -valuecolwidth 100 84 | configure wave -justifyvalue left 85 | configure wave -signalnamewidth 0 86 | configure wave -snapdistance 10 87 | configure wave -datasetprefix 0 88 | configure wave -rowmargin 4 89 | configure wave -childrowmargin 2 90 | configure wave -gridoffset 0 91 | configure wave -gridperiod 1 92 | configure wave -griddelta 40 93 | configure wave -timeline 0 94 | configure wave -timelineunits ns 95 | update 96 | WaveRestoreZoom {0 ns} {1050 ns} 97 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_agent_config.sv: -------------------------------------------------------------------------------- 1 | // these are the agent configuration parameters that can be changed at the test level 2 | class hermes_agent_config extends uvm_object; 3 | `uvm_object_utils(hermes_agent_config) 4 | 5 | uvm_active_passive_enum is_active = UVM_ACTIVE; 6 | bit master_driver_enabled = 1; 7 | 8 | 9 | //========================== 10 | // credit_i_driver timing knobs 11 | //========================== 12 | // the probability to have credit to send flits outside the router. 13 | // cred_distrib == 10 ==> 100%, i.e. the next router is always free to send flits 14 | // cred_distrib == 1 ==> 10%, i.e. the next router is always free only 10% of the time 15 | rand bit [3:0] cred_distrib; 16 | // default distribution for credit. only values from [1:10] are allowed. 0 and [11:15] have 0% of selection 17 | bit [3:0] cred_dist[11] = {0,5,5,1,1,1,1,1,1,5,30}; 18 | 19 | constraint c_cred_distrib { 20 | // fixed distribution 21 | //cred_distrib dist { [0:2] := 10, [3:15] := 1 }; 22 | // variable distribution. TODO: there must be a better way to do it !!! 23 | cred_distrib dist { 0 := 0, 1 := cred_dist[1], 2 := cred_dist[2], 3 := cred_dist[3], 4 := cred_dist[4], 24 | 5 := cred_dist[5], 6 := cred_dist[6], 7 := cred_dist[7], 8 := cred_dist[8], 9 := cred_dist[9], 25 | 10 := cred_dist[10] 26 | }; 27 | ! (cred_distrib inside { [11:15] }); 28 | /* 29 | cred_distrib dist { 0 := cred_dist[0], 1 := cred_dist[1], 2 := cred_dist[2], 3 := cred_dist[3], 4 := cred_dist[4], 30 | 5 := cred_dist[5], 6 := cred_dist[6], 7 := cred_dist[7], 8 := cred_dist[8], 9 := cred_dist[9], 31 | 10 := cred_dist[10], 11 := cred_dist[11], 12 := cred_dist[12], 13 := cred_dist[13], 32 | 14 := cred_dist[14], 15 := cred_dist[15] 33 | }; 34 | */ 35 | } 36 | 37 | 38 | //========================== 39 | // hermes_driver timing knobs 40 | //========================== 41 | // randomize the number of cycles the driver waits to start sending the packet. used by driver 42 | rand bit [3:0] cycle2send; 43 | // used to change the random distribution of cycle2send 44 | bit [3:0] cycle2send_dist[16] = {10,10,10,1,1,1,1,1,1,1,1,1,1,1,1,1}; 45 | 46 | 47 | // randomize the number of cycles between flits. used by driver 48 | rand bit [3:0] cycle2flit; 49 | // used to change the random distribution of cycle2flit 50 | bit [3:0] cycle2flit_dist[16] = {15,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1}; 51 | 52 | // choose random # of cycles to start sending this transaction 53 | constraint c_cycle2send { 54 | // fixed distribution 55 | //cycle2send dist { [0:2] := 10, [3:15] := 1 }; 56 | // variable distribution. TODO: there must be a better way to do it !!! 57 | cycle2send dist { 0 := cycle2send_dist[0], 1 := cycle2send_dist[1], 2 := cycle2send_dist[2], 3 := cycle2send_dist[3], 4 := cycle2send_dist[4], 58 | 5 := cycle2send_dist[5], 6 := cycle2send_dist[6], 7 := cycle2send_dist[7], 8 := cycle2send_dist[8], 9 := cycle2send_dist[9], 59 | 10 := cycle2send_dist[10], 11 := cycle2send_dist[11], 12 := cycle2send_dist[12], 13 := cycle2send_dist[13], 60 | 14 := cycle2send_dist[14], 15 := cycle2send_dist[15] 61 | }; 62 | } 63 | 64 | // choose random # of cycles between flits 65 | constraint c_cycle2flit { 66 | // fixed distribution 67 | //cycle2flit dist { 0 := 15, [1:2] := 5, [3:15] := 1 }; 68 | // variable distribution. TODO: there must be a better way to do it !!! 69 | cycle2flit dist { 0 := cycle2flit_dist[0], 1 := cycle2flit_dist[1], 2 := cycle2flit_dist[2], 3 := cycle2flit_dist[3], 4 := cycle2flit_dist[4], 70 | 5 := cycle2flit_dist[5], 6 := cycle2flit_dist[6], 7 := cycle2flit_dist[7], 8 := cycle2flit_dist[8], 9 := cycle2flit_dist[9], 71 | 10 := cycle2flit_dist[10], 11 := cycle2flit_dist[11], 12 := cycle2flit_dist[12], 13 := cycle2flit_dist[13], 72 | 14 := cycle2flit_dist[14], 15 := cycle2flit_dist[15] 73 | }; 74 | } 75 | 76 | 77 | function void do_copy( uvm_object rhs ); 78 | hermes_agent_config that; 79 | 80 | if ( ! $cast( that, rhs ) ) begin 81 | `uvm_error( get_name(), "rhs is not a seq_config" ) 82 | return; 83 | end 84 | 85 | super.do_copy( rhs ); 86 | this.cred_distrib = that.cred_distrib; 87 | this.cred_dist = that.cred_dist; 88 | this.cycle2send = that.cycle2send; 89 | this.cycle2send_dist = that.cycle2send_dist; 90 | this.cycle2flit = that.cycle2flit; 91 | this.cycle2flit_dist = that.cycle2flit_dist; 92 | endfunction: do_copy 93 | 94 | 95 | virtual function string convert2string(); 96 | string s = super.convert2string(); 97 | s = { s, $psprintf( "\n cred_distrib : %0d", cred_distrib) }; 98 | s = { s, $psprintf( "\n cycle2send : %0d", cycle2send) }; 99 | s = { s, $psprintf( "\n cycle2flit : %0d", cycle2flit) }; 100 | return s; 101 | endfunction: convert2string 102 | 103 | function new( string name = "" ); 104 | super.new( name ); 105 | endfunction: new 106 | 107 | endclass : hermes_agent_config 108 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/docs/readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Introduction 3 | 4 | This doc describes the protocol dependent part of Hermes NoC, including interfaces, transactions, agents, drivers, and monitors. 5 | 6 | ## hermes_agent 7 | 8 | The agent has a sequencer, *hermes_monitor*, *hermes_agent_config*, and *hermes_base_driver*. Depending on the agent mode (slave or master), 9 | the *hermes_base_driver* is replaced by *hermes_master_driver* or *hermes_slave_driver*. The image bellow show a hermes_agent with interface to a Hermes router. 10 | 11 | ![agent](agent.png) 12 | 13 | 14 | The agent uses the following configuration parameters. 15 | 16 | | name / type | Description | GET/SET | From/To | 17 | | --- | --- | --- | --- | 18 | | config / hermes_agent_config | config | get | test | 19 | | if / hermes_if | interface | get | top | 20 | | if / hermes_if | interface | set | monitor/driver | 21 | | mode / string | slave/master | get | env | 22 | | port / int | the port attached to the agent | get | env | 23 | 24 | 25 | ### hermes_if 26 | 27 | The interface consists of the following terminals, for the master and slave port respectively. 28 | 29 | ```SystemVerilog 30 | modport datain ( 31 | input clk, avail, data, 32 | output credit 33 | ); 34 | modport dataout ( 35 | output clk, avail, data, 36 | input credit 37 | ); 38 | ``` 39 | 40 | ### hermes_packet_t 41 | 42 | A packet transaction consists of a set of 16-bits words where the first is the header, where it informs the target router address, the second is the packet size, and the rest is the payload. The transaction allows randomization of: 43 | 44 | - header: packet destination 45 | - p_size: packet size in words of 16 bits 46 | - payload: the actual content of the packet 47 | 48 | The packet size can be small, medium, or large sized and it is possible to change its random distribution. 49 | The header is constrained based on the valid path of the XY routing algorithm. The function [hermes_pkg::valid_addrs](../src/hermes_typedefs.sv) returns the set of valid network addresses according to the input port. 50 | 51 | 52 | ### hermes_agent_config 53 | 54 | It has 3 parameters used by the *hermes_master_driver*: 55 | 56 | - cycle2send: number of clock cycles waiting to send the transaction 57 | - cycle2flit: number of clock cycles waiting to send the next flit 58 | - master_driver_enabled: if it is disabled, then it is not supposed to drive incoming packets into the router. flag error if it does. 59 | 60 | and one used by the *hermes_slave_driver*: 61 | 62 | - cred_distrib: the probability of the slave port to accept an outgoing flit. 63 | 64 | The following piece of code of a test configures the NORTH agent different modes. 65 | 66 | ```SystemVerilog 67 | if( !acfg[hermes_pkg::NORTH].randomize() with { 68 | cycle2send == 1; 69 | cycle2flit == 0; 70 | } 71 | ``` 72 | 73 | When the NORTH input buffer is not full, the result is that credit is high and rx is continuous. Thus, flits are sent every cycle, 0011 (header), 0002 (size) , and bec6, 2318 (payload). 74 | 75 | ![buffer not full](master_buffer_not_full.png) 76 | 77 | However, when the buffer is full, the credit is low for few clock cycles, interrupting the transmission of the 3 flit packet 0011, 0001, cda7. 78 | 79 | ![buffer full](master_buffer_full.png) 80 | 81 | Then, if we change the agent configuration to: 82 | 83 | ```SystemVerilog 84 | if( !acfg[hermes_pkg::NORTH].randomize() with { 85 | cycle2send == 1; 86 | cycle2flit == 1; 87 | cred_distrib == 3; 88 | } 89 | ``` 90 | 91 | In the master port we are going to see a flit sent every 2 clock cycles. 92 | 93 | ![cycles2flit](master_cycles2flit.png) 94 | 95 | And in the slave port we see low credit most of the time, delaying the packet transmission. 96 | 97 | ![low credit](slave_low_credit.png) 98 | 99 | ### hermes_monitor 100 | 101 | The monitor is always on, and has no distinct attribute or configuration other than the usual interface configuration. 102 | 103 | ### hermes_base_driver 104 | 105 | The agent has a hermes_base_driver attribute. During *build_phase*, where the *mode* parameter is read, this driver is either converted to a *hermes_master_driver* or *hermes_slave_driver*. 106 | 107 | ### hermes_master_driver 108 | 109 | It receives a transaction and sends it to the DUT via a master port. Its behaviour is affected by the *cycle2send*, *cycle2flit*, and *enable* agent parameters. 110 | 111 | ### hermes_slave_driver 112 | 113 | Its only goal is to generate the credit to slave ports. The probability of high credit is determined by the *cred_distrib* agent parameter. -------------------------------------------------------------------------------- /noc-router/vips/sc/router_cc.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // DISTRIBUTED HEMPS - version 5.0 4 | // 5 | // Research group: GAPH-PUCRS - contact fernando.moraes@pucrs.br 6 | // 7 | // Distribution: September 2013 8 | // 9 | // Source name: router_cc.h 10 | // 11 | // Brief description: Signals and methods of router_cc 12 | // 13 | //--------------------------------------------------------------------------------------- 14 | 15 | #ifndef _switch_cc_h 16 | #define _switch_cc_h 17 | 18 | #include 19 | #include "packet.h" 20 | #include "queue.h" 21 | #include "switchcontrol.h" 22 | 23 | SC_MODULE(router_cc){ 24 | 25 | sc_in clock; 26 | sc_in reset_n; 27 | 28 | sc_in clock_rx[NPORT]; 29 | sc_in rx[NPORT]; 30 | sc_out credit_o[NPORT]; 31 | sc_out data_out[NPORT]; 32 | 33 | sc_out clock_tx[NPORT]; 34 | sc_out tx[NPORT]; 35 | sc_in credit_i[NPORT]; 36 | sc_in data_in[NPORT]; 37 | 38 | sc_signal sgn_h[NPORT]; 39 | sc_signal sgn_ack_h[NPORT]; 40 | sc_signal sgn_data_av[NPORT]; 41 | sc_signal sgn_sender[NPORT]; 42 | sc_signal sgn_data_ack[NPORT]; 43 | sc_signal incoming; 44 | sc_signal data[NPORT]; 45 | 46 | sc_signal mux_in, mux_out; 47 | sc_signal header; 48 | sc_signal free[NPORT]; 49 | 50 | //Traffic monitor 51 | sc_in > tick_counter; 52 | unsigned char SM_traffic_monitor[NPORT]; 53 | unsigned int target_router[NPORT]; 54 | unsigned int header_time[NPORT]; 55 | unsigned short bandwidth_allocation[NPORT]; 56 | unsigned short payload[NPORT]; 57 | unsigned short payload_counter[NPORT]; 58 | unsigned int service[NPORT]; 59 | unsigned int task_id[NPORT]; 60 | unsigned int consumer_id[NPORT]; 61 | void traffic_monitor(); 62 | 63 | 64 | // interface do Fila 65 | fila *myQueue[NPORT]; 66 | 67 | switch_control *mySwitchControl; 68 | 69 | int total_flits; 70 | int wire_EAST; 71 | int wire_WEST; 72 | int wire_NORTH; 73 | int wire_SOUTH; 74 | int wire_LOCAL; 75 | 76 | int aux; 77 | int fluxo_0; 78 | int fluxo_1; 79 | int fluxo_2; 80 | int fluxo_3; 81 | int fluxo_4; 82 | int fluxo_5; 83 | 84 | void upd_header(); 85 | void upd_dataout(); 86 | void upd_dataack(); 87 | void upd_tx(); 88 | void upd_ackh(); 89 | void upd_sgndataack(); 90 | void upd_dataav(); 91 | void upd_h(); 92 | void upd_rx(); 93 | void upd_clock_rx(); 94 | void upd_sender(); 95 | void upd_sgnackrx(); 96 | void upd_sgn_credit_o(); 97 | void upd_clock_tx(); 98 | 99 | SC_HAS_PROCESS(router_cc); 100 | router_cc(sc_module_name name_, regaddress address_ = 0x0000) : 101 | sc_module(name_), address(address_) 102 | { 103 | char temp[20]; 104 | 105 | unsigned int i; 106 | 107 | for(i=0; iclock(clock); 112 | myQueue[i]->reset_n(reset_n); 113 | myQueue[i]->data_in(data_in[i]); 114 | myQueue[i]->rx(rx[i]); 115 | myQueue[i]->credit_o(credit_o[i]); 116 | myQueue[i]->h(sgn_h[i]); 117 | myQueue[i]->ack_h(sgn_ack_h[i]); 118 | myQueue[i]->data_av(sgn_data_av[i]); 119 | myQueue[i]->data(data[i]); 120 | myQueue[i]->data_ack(sgn_data_ack[i]); 121 | myQueue[i]->sender(sgn_sender[i]); 122 | } 123 | 124 | mySwitchControl = new switch_control("novoswitchcontrol",address); 125 | mySwitchControl->clock(clock); 126 | mySwitchControl->reset(reset_n); 127 | for(i=0; idata[i](data[i]); 129 | mySwitchControl->h[i](sgn_h[i]); 130 | mySwitchControl->ack_h[i](sgn_ack_h[i]); 131 | mySwitchControl->sender[i](sgn_sender[i]); 132 | mySwitchControl->free[i](free[i]); 133 | } 134 | mySwitchControl->mux_in(mux_in); 135 | mySwitchControl->mux_out(mux_out); 136 | 137 | SC_METHOD(upd_header); 138 | sensitive << incoming; 139 | sensitive << data[EAST]; 140 | sensitive << data[WEST]; 141 | sensitive << data[NORTH]; 142 | sensitive << data[SOUTH]; 143 | sensitive << data[LOCAL]; 144 | 145 | SC_METHOD(upd_dataout); 146 | sensitive << free[EAST]; 147 | sensitive << free[WEST]; 148 | sensitive << free[NORTH]; 149 | sensitive << free[SOUTH]; 150 | sensitive << free[LOCAL]; 151 | sensitive << data[EAST]; 152 | sensitive << data[WEST]; 153 | sensitive << data[NORTH]; 154 | sensitive << data[SOUTH]; 155 | sensitive << data[LOCAL]; 156 | sensitive << mux_out; 157 | 158 | SC_METHOD(upd_dataack); 159 | sensitive << credit_i[EAST]; 160 | sensitive << credit_i[WEST]; 161 | sensitive << credit_i[NORTH]; 162 | sensitive << credit_i[SOUTH]; 163 | sensitive << credit_i[LOCAL]; 164 | sensitive << mux_in; 165 | sensitive << sgn_data_av[EAST]; 166 | sensitive << sgn_data_av[WEST]; 167 | sensitive << sgn_data_av[NORTH]; 168 | sensitive << sgn_data_av[SOUTH]; 169 | sensitive << sgn_data_av[LOCAL]; 170 | 171 | SC_METHOD(upd_tx); 172 | sensitive << free[EAST]; 173 | sensitive << free[WEST]; 174 | sensitive << free[NORTH]; 175 | sensitive << free[SOUTH]; 176 | sensitive << free[LOCAL]; 177 | sensitive << sgn_data_av[EAST]; 178 | sensitive << sgn_data_av[WEST]; 179 | sensitive << sgn_data_av[NORTH]; 180 | sensitive << sgn_data_av[SOUTH]; 181 | sensitive << sgn_data_av[LOCAL]; 182 | sensitive << mux_out; 183 | 184 | SC_METHOD(traffic_monitor); 185 | sensitive << clock; 186 | sensitive << reset_n; 187 | 188 | SC_METHOD(upd_clock_tx); 189 | sensitive << clock.pos(); 190 | sensitive << reset_n; 191 | 192 | 193 | } 194 | private: 195 | regaddress address; 196 | }; 197 | 198 | #endif 199 | -------------------------------------------------------------------------------- /mult/dut/booth_mult2/Booth_Multiplier.v: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Copyright 2010-2012 by Michael A. Morris, dba M. A. Morris & Associates 4 | // 5 | // All rights reserved. The source code contained herein is publicly released 6 | // under the terms and conditions of the GNU Lesser Public License. No part of 7 | // this source code may be reproduced or transmitted in any form or by any 8 | // means, electronic or mechanical, including photocopying, recording, or any 9 | // information storage and retrieval system in violation of the license under 10 | // which the source code is released. 11 | // 12 | // The souce code contained herein is free; it may be redistributed and/or 13 | // modified in accordance with the terms of the GNU Lesser General Public 14 | // License as published by the Free Software Foundation; either version 2.1 of 15 | // the GNU Lesser General Public License, or any later version. 16 | // 17 | // The souce code contained herein is freely released WITHOUT ANY WARRANTY; 18 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 19 | // PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for 20 | // more details.) 21 | // 22 | // A copy of the GNU Lesser General Public License should have been received 23 | // along with the source code contained herein; if not, a copy can be obtained 24 | // by writing to: 25 | // 26 | // Free Software Foundation, Inc. 27 | // 51 Franklin Street, Fifth Floor 28 | // Boston, MA 02110-1301 USA 29 | // 30 | // Further, no use of this source code is permitted in any form or means 31 | // without inclusion of this banner prominently in any derived works. 32 | // 33 | // Michael A. Morris 34 | // Huntsville, AL 35 | // 36 | /////////////////////////////////////////////////////////////////////////////// 37 | 38 | `timescale 1ns / 1ps 39 | 40 | /////////////////////////////////////////////////////////////////////////////// 41 | // Company: M. A. Morris & Associates 42 | // Engineer: Michael A. Morris 43 | // 44 | // Create Date: 19:48:02 07/10/2010 45 | // Design Name: Booth Multiplier 46 | // Module Name: Booth_Multiplier.v 47 | // Project Name: Booth_Multiplier 48 | // Target Devices: Spartan-3AN 49 | // Tool versions: Xilinx ISE 10.1 SP3 50 | // 51 | // Description: 52 | // 53 | // This module implements a parameterized multiplier which uses the Booth 54 | // algorithm for its implementation. The implementation is based on the 55 | // algorithm described in "Computer Organization", Hamacher et al, McGraw- 56 | // Hill Book Company, New York, NY, 1978, ISBN: 0-07-025681-0. 57 | // 58 | // Dependencies: 59 | // 60 | // Revision: 61 | // 62 | // 0.01 10G10 MAM File Created 63 | // 64 | // Additional Comments: 65 | // 66 | /////////////////////////////////////////////////////////////////////////////// 67 | 68 | module Booth_Multiplier #( 69 | parameter pN = 4 // Width = 2**pN: multiplicand & multiplier 70 | )( 71 | input Rst, // Reset 72 | input Clk, // Clock 73 | 74 | input Ld, // Load Registers and Start Multiplier 75 | input [(2**pN - 1):0] M, // Multiplicand 76 | input [(2**pN - 1):0] R, // Multiplier 77 | output reg Valid, // Product Valid 78 | output reg [(2**(pN+1) - 1):0] P // Product <= M * R 79 | ); 80 | 81 | /////////////////////////////////////////////////////////////////////////////// 82 | // 83 | // Local Parameters 84 | // 85 | 86 | /////////////////////////////////////////////////////////////////////////////// 87 | // 88 | // Declarations 89 | // 90 | 91 | reg [2**pN:0] A; // Multiplicand w/ sign guard bit 92 | reg [ pN:0] Cntr; // Operation Counter 93 | reg [2**pN:0] S; // Adder w/ sign guard bit 94 | 95 | reg [(2**(pN+1) + 1):0] Prod; // Double length product w/ guard bits 96 | 97 | /////////////////////////////////////////////////////////////////////////////// 98 | // 99 | // Implementation 100 | // 101 | 102 | always @(posedge Clk) 103 | begin 104 | if(Rst) 105 | Cntr <= #1 0; 106 | else if(Ld) 107 | Cntr <= #1 2**pN; 108 | else if(|Cntr) 109 | Cntr <= #1 (Cntr - 1); 110 | end 111 | 112 | // Multiplicand Register 113 | // includes an additional bit to guard sign bit in the event the 114 | // most negative value is provided as the multiplicand. 115 | 116 | always @(posedge Clk) 117 | begin 118 | if(Rst) 119 | A <= #1 0; 120 | else if(Ld) 121 | A <= #1 {M[2**pN - 1], M}; 122 | end 123 | 124 | // Compute Upper Partial Product: (2**pN + 1) bits in width 125 | 126 | always @(*) 127 | begin 128 | case(Prod[1:0]) 129 | 2'b01 : S <= Prod[(2**(pN+1) + 1):(2**pN + 1)] + A; 130 | 2'b10 : S <= Prod[(2**(pN+1) + 1):(2**pN + 1)] - A; 131 | default : S <= Prod[(2**(pN+1) + 1):(2**pN + 1)]; 132 | endcase 133 | end 134 | 135 | // Register Partial products and shift rigth arithmetically. 136 | // Product register has guard bits on both ends. 137 | 138 | always @(posedge Clk) 139 | begin 140 | if(Rst) 141 | Prod <= #1 0; 142 | else if(Ld) 143 | Prod <= #1 {R, 1'b0}; 144 | else if(|Cntr) 145 | Prod <= #1 {S[2**pN], S, Prod[2**pN:1]}; // Arithmetic Shift Right 146 | end 147 | 148 | // Assign the product less the two guard bits to the output port 149 | 150 | always @(posedge Clk) 151 | begin 152 | if(Rst) 153 | P <= #1 0; 154 | else if(Cntr == 1) 155 | P <= #1 {S[2**pN], S, Prod[2**pN:2]}; 156 | end 157 | 158 | // Count the number of shifts 159 | // This implementation does not use any optimizations to perform multiple 160 | // bit shifts to skip over runs of 1s or 0s. 161 | 162 | always @(posedge Clk) 163 | begin 164 | if(Rst) 165 | Valid <= #1 0; 166 | else 167 | Valid <= #1 (Cntr == 1); 168 | end 169 | 170 | endmodule 171 | -------------------------------------------------------------------------------- /noc-router/hermes_router/docs/readme.md: -------------------------------------------------------------------------------- 1 | # Hermes Network-on-Chip Router Testbench 2 | 3 | The DUT is the NoC router presented in the paper [HERMES: an infrastructure for low area overhead packet-switching networks on chip](https://www.sciencedirect.com/science/article/pii/S0167926004000185). The DUT is the central router illustrated in Fig below, with an 8-bit network address set in design time, 16-bit wide data channels, five master ports for incoming packets, five slave ports for outgoing packets. Although only the central router is simulated, it mimics the existence of a 3x3 NoC used just for routing address purposes. 4 | 5 | ![Hermes router DUT!!!](router.png) 6 | 7 | 8 | This UVM-based router TB is illustrated in the Fig below. It has one environment with 10 agents (5 slaves and 5 master agents) each one attached to a different router port. It has several different types of randomization and constraints to generate valid packet headers and to randomize the time the packets and the flits are injected into the router. It uses virtual and hierarchical sequences to coordinate various sequences in parallel. It has a scoreboard and different coverage points/crosses. config_db, represented in the figure with dashed lines, distributes parameters to the environment and to its 10 agents. The agent (slave or master) is configured with factory override, changing the behavior of the driver. config_db is also used to pass parameters from tests to sequences. 9 | 10 | ![Hermes router TB in UVM!!!](tb.png) 11 | 12 | 13 | ## The Testbench Architecture 14 | 15 | This router TB is organized in three main modules: 16 | - [**hermes_router**](../): the router design where the RTL, netlist, top, simulation scripts, tests and sequences are located; 17 | - [**hermes_pkg**](../../vips/hermes_pkg/docs): contains the protocol dependent part of the testbench, i.e. the agent, both slave/master drivers, the monitor, interface, agent configuration class, and main design parameters; 18 | - [**hermes_router_env_pkg**](../../vips/hermes_router_env_pkg/docs): contains the router environment, which instantiates 5 slave and 5 master agents. It also contains the coverage module, the scoreboard, and the environment configuration class. 19 | 20 | ## Running the Tests 21 | 22 | > $ git clone https://github.com/amamory/uvm-basics.git 23 | 24 | > $ cd uvm-basics/noc-router/hermes_router/sim 25 | 26 | > $ vsim -c -do run.do 27 | 28 | ## The Testbench Simulation Knobs 29 | 30 | The [run.do](../sim/run.do) file has few parameter to change the type of simulation. 31 | 32 | ``` 33 | set SEED "random" 34 | set VERBOSITY "UVM_HIGH" 35 | # set true to enable coverage 36 | set COVERAGE "true" 37 | # set true to simulate RTL, otherwise, simulates the netlist 38 | set RTL_SIM "true" 39 | # set true to simulate for debug, otherwise simulate for speed/regression 40 | set DEBUG_SIM "true" 41 | ``` 42 | 43 | ## Existing Sequences 44 | 45 | There are 2 sequences named *repeat_seq* and *parallel_seq*. repeat_seq sends N transaction items into a single port sequentially. In this sequence, just the payload content is randomized. The rest of the transaction parameters are defined by the sequence configuration. parallel_seq is a virtual sequence that coordinates the parallel execution of repeat_seq sequences. parallel_seq has an additional parameter (*enable_port*) to set which sequences are enabled for parallel execution. The default is to have all sequences enabled. 46 | 47 | 48 | ## Existing Tests 49 | 50 | There are 3 types of configurations: environment ([hermes_router_env_config](../../vips/hermes_router_env_pkg/src/hermes_router_env_config.sv)), agent ([hermes_agent_config](../../vips/hermes_pkg/src/hermes_agent_config.sv)), and sequence ([hermes_router_seq_config](../tb/seqs/src/hermes_router_seq_config.sv)) configurations. Each test in *build_phase* must set the environment and the agent configuration accordinly. There is only one environment configuration and five agent configurations, where one agent configuration is set to each port direction (N, S, W, E, Local). The Sequence configuration is set in *run_phase*. Then this configuration is sent to its sequencer, and the sequence is started. Check the [repeat_test](../tb/tests/src/repeat_test.sv) for an example. 51 | 52 | This is a list of existing tests: 53 | 54 | | name | Description | test param | 55 | | --- | --- | --- | 56 | | | | | 57 | | base_test | the base test class for all tests. it does not implement run_phase| none | 58 | | repeat_test | injects 10 packets into the north port | repeat_sequence | 59 | | random_test | injects 10 packets into a randomly selected ports | none | 60 | | sequential_test | injects packets in sequential port order, starting with the port 0. | repeat_sequence | 61 | | parallel_test | uses a virtual sequence to inject packets in all input ports in parallel | none | 62 | | bottleneck_test | uses a virtual sequence to inject packets in all input ports in parallel to the same target address, creating a bottleneck | target_address | 63 | 64 | 65 | ## Creating New Tests 66 | 67 | The easiest way is to derive new tests based on the existing ones. Then, just tweak the configuration knobs according to the goal of this new test. See the tests available [here](../tb/tests/src) and the sequences [here](../tb/seqs/src). 68 | 69 | ## Stuff to be done 70 | 71 | This router TB is functional but there are more features I want to implement, in order of importance, such as: 72 | - Document the TB architecture, tests, sequences, checks, and coverage. Perhaps using Markdown and ReadTheDocs. *DONE !* 73 | - Set tests with plusargs, making the tests more configurable without recompilation and also reducing the number of tests. *DONE !, Although it would be possible to use more of this capability* 74 | - Include SV assertions in the DUT 75 | - netlist simulation with SDF annotation - *DONE !* 76 | - Design a Power Aware Simulation using Unified Power Format (UPF) 77 | - Describe sequences for error injection 78 | - Include a fault injection method with UVM and/or using formal methods, such as 79 | [How Formal Reduces Fault Analysis for ISO 26262](https://www.mentor.com/products/fv/resources/overview/how-formal-reduces-fault-analysis-for-iso-26262-82758134-85e7-4753-92f4-6f90e36e7d96) 80 | - More open-ended task would be to keep studying SV and UVM usage methods to improve the reuse for this testbench. 81 | -------------------------------------------------------------------------------- /noc-router/vips/hermes_pkg/src/hermes_packet_t.sv: -------------------------------------------------------------------------------- 1 | import hermes_pkg::*; 2 | 3 | class hermes_packet_t extends uvm_sequence_item; 4 | `uvm_object_utils(hermes_packet_t) 5 | 6 | parameter half_flit = hermes_pkg::FLIT_WIDTH/2; 7 | parameter quarter_flit = hermes_pkg::FLIT_WIDTH/4; 8 | 9 | // to ease randomization of packet size 10 | //typedef enum {ZERO, SMALL, MED, LARGE} packet_size_t; 11 | typedef enum {SMALL, MED, LARGE} packet_size_t; // zero is not supported by the router. enable only to generated invalid packets 12 | rand packet_size_t p_size; 13 | // weights for packet size 14 | //bit [4:0] w_zero=1, w_small=2, w_med=10, w_large=1; 15 | bit [4:0] w_small=20, w_med=5, w_large=1; 16 | 17 | // packet payload and size (payload.size()) 18 | // TODO optimize according to https://verificationacademy.com/forums/systemverilog/randomizing-dynamic-array-size 19 | rand bit [hermes_pkg::FLIT_WIDTH-1:0] payload[]; 20 | // packet header - only 7 : 0 is used, y is 3: 0 and x is 7: 4 21 | rand bit [quarter_flit-1:0] x, y; 22 | 23 | rand bit [7:0] header; 24 | 25 | /* 26 | // randomize the number of cycles the driver waits to start sending the packet. used by driver 27 | rand bit [3:0] cycle2send; 28 | // used to change the random distribution of cycle2send 29 | bit [3:0] cycle2send_dist[16] = {10,10,10,1,1,1,1,1,1,1,1,1,1,1,1,1}; 30 | 31 | 32 | // randomize the number of cycles between flits. used by driver 33 | rand bit [3:0] cycle2flit; 34 | // used to change the random distribution of cycle2flit 35 | bit [3:0] cycle2flit_dist[16] = {15,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1}; 36 | */ 37 | 38 | // output port where the packet was captured 39 | bit [3:0] oport; 40 | 41 | // driver port where the packet was inserted 42 | bit [3:0] dport; 43 | 44 | // choose random packet size with weights 45 | constraint c_p_size { 46 | p_size dist { 47 | //ZERO := w_zero, // not supported by the router. enable only to generated invalid packets 48 | SMALL := w_small, 49 | MED := w_med, 50 | LARGE := w_large 51 | }; 52 | } 53 | 54 | /* 55 | // choose random # of cycles to start sending this transaction 56 | constraint c_cycle2send { 57 | // fixed distribution 58 | //cycle2send dist { [0:2] := 10, [3:15] := 1 }; 59 | // variable distribution. TODO: there must be a better way to do it !!! 60 | cycle2send dist { 0 := cycle2send_dist[0], 1 := cycle2send_dist[1], 2 := cycle2send_dist[2], 3 := cycle2send_dist[3], 4 := cycle2send_dist[4], 61 | 5 := cycle2send_dist[5], 6 := cycle2send_dist[6], 7 := cycle2send_dist[7], 8 := cycle2send_dist[8], 9 := cycle2send_dist[9], 62 | 10 := cycle2send_dist[10], 11 := cycle2send_dist[11], 12 := cycle2send_dist[12], 13 := cycle2send_dist[13], 63 | 14 := cycle2send_dist[14], 15 := cycle2send_dist[15] 64 | }; 65 | } 66 | 67 | // choose random # of cycles between flits 68 | constraint c_cycle2flit { 69 | // fixed distribution 70 | //cycle2flit dist { 0 := 15, [1:2] := 5, [3:15] := 1 }; 71 | // variable distribution. TODO: there must be a better way to do it !!! 72 | cycle2flit dist { 0 := cycle2flit_dist[0], 1 := cycle2flit_dist[1], 2 := cycle2flit_dist[2], 3 := cycle2flit_dist[3], 4 := cycle2flit_dist[4], 73 | 5 := cycle2flit_dist[5], 6 := cycle2flit_dist[6], 7 := cycle2flit_dist[7], 8 := cycle2flit_dist[8], 9 := cycle2flit_dist[9], 74 | 10 := cycle2flit_dist[10], 11 := cycle2flit_dist[11], 12 := cycle2flit_dist[12], 13 := cycle2flit_dist[13], 75 | 14 := cycle2flit_dist[14], 15 := cycle2flit_dist[15] 76 | }; 77 | } 78 | */ 79 | 80 | // max packet size in flits 81 | constraint c_size { 82 | //if (p_size == ZERO){ 83 | // payload.size() == 0; 84 | //}else 85 | if (p_size == SMALL){ 86 | payload.size() >= 1; payload.size() <= 3; 87 | 88 | }else if (p_size == LARGE){ 89 | payload.size() >= 100; payload.size() <= 128; 90 | } else{ 91 | payload.size() >= 4; payload.size() <= 99; 92 | } 93 | } 94 | 95 | constraint c_header { 96 | // given the input port 'dport', it returns the list of possible target address for the header 97 | header inside {hermes_pkg::valid_addrs(this.dport)}; 98 | x == header[7:4]; 99 | y == header[3:0]; 100 | solve dport before header; 101 | solve header before x; 102 | solve header before y; 103 | } 104 | 105 | 106 | function void set_header(input bit [hermes_pkg::FLIT_WIDTH-1:0] h ); 107 | y = h[quarter_flit-1:0]; 108 | x = h[half_flit-1 : quarter_flit]; 109 | endfunction: set_header 110 | 111 | function bit [hermes_pkg::FLIT_WIDTH-1:0] get_header(); 112 | return {8'b0,x, y}; 113 | endfunction: get_header 114 | 115 | function new(string name = ""); 116 | super.new(name); 117 | // when the transaction is input, them oport=-1 118 | // otherwise, when the transaction is output, them dport=-1 119 | dport = -1; 120 | oport = -1; 121 | 122 | endfunction: new 123 | 124 | 125 | 126 | virtual function bit do_compare( uvm_object rhs, uvm_comparer comparer ); 127 | hermes_packet_t that; 128 | if ( ! $cast( that, rhs ) ) return 0; 129 | 130 | return ( super.do_compare( rhs, comparer ) && 131 | this.x == that.x && 132 | this.y == that.y && 133 | this.payload.size() == that.payload.size() && 134 | this.payload == that.payload ); 135 | endfunction: do_compare 136 | 137 | virtual function void do_copy( uvm_object rhs ); 138 | hermes_packet_t that; 139 | 140 | if ( ! $cast( that, rhs ) ) begin 141 | `uvm_error( get_name(), "rhs is not a hermes_packet_t" ) 142 | return; 143 | end 144 | 145 | super.do_copy( rhs ); 146 | this.x = that.x; 147 | this.y = that.y; 148 | this.dport = that.dport; 149 | this.oport = that.oport; 150 | this.payload = that.payload; 151 | endfunction: do_copy 152 | 153 | virtual function string convert2string(); 154 | string s = super.convert2string(); 155 | s = { s, $psprintf( "\nx : %0d", x) }; 156 | s = { s, $psprintf( "\ny : %0d", y) }; 157 | s = { s, $psprintf( "\nip : %0d", dport) }; 158 | s = { s, $psprintf( "\nop : %0d", oport) }; 159 | s = { s, $psprintf( "\nsize : %0d", payload.size()) }; 160 | s = { s, $psprintf( "\npayload : ") }; 161 | foreach(payload[i]) begin 162 | s = { s, $psprintf( "\n\t%H ",payload[i])}; 163 | end 164 | return s; 165 | endfunction: convert2string 166 | 167 | function void do_record(uvm_recorder recorder); 168 | super.do_record(recorder); 169 | 170 | `uvm_record_attribute(recorder.tr_handle, "x",x); 171 | `uvm_record_attribute(recorder.tr_handle, "y",y); 172 | `uvm_record_attribute(recorder.tr_handle, "ip",dport); 173 | `uvm_record_attribute(recorder.tr_handle, "op",oport); 174 | `uvm_record_attribute(recorder.tr_handle, "size",payload.size()); 175 | //`uvm_record_attribute(recorder.tr_handle, "payload",payload); 176 | endfunction 177 | 178 | endclass: hermes_packet_t 179 | 180 | 181 | /* 182 | `uvm_object_utils_begin( jelly_bean_transaction ) 183 | `uvm_field_enum( flavor_e, flavor, UVM_ALL_ON ) 184 | `uvm_field_enum( color_e, color, UVM_ALL_ON ) 185 | `uvm_field_int ( sugar_free, UVM_ALL_ON ) 186 | `uvm_field_int ( sour, UVM_ALL_ON ) 187 | `uvm_field_enum( taste_e, taste, UVM_ALL_ON ) 188 | `uvm_object_utils_end 189 | */ 190 | typedef uvm_sequencer #(hermes_packet_t) packet_sequencer; 191 | 192 | --------------------------------------------------------------------------------