mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
First TB for scoreboard implementation
This commit is contained in:
parent
390182d0c4
commit
e66a683e8d
7 changed files with 329 additions and 66 deletions
|
@ -112,27 +112,27 @@ The field functional unit can be of the following types:
|
|||
|
||||
#### Interface
|
||||
|
||||
| **Signal** | **Direction** | **Description** | **Category** |
|
||||
|-----------------------|---------------|----------------------------------------------------------------------------------|------------------------|
|
||||
| flush_i | Input | Flush Scoreboard | Control |
|
||||
| full_o | Output | Scoreboard is full | Control |
|
||||
| rd_clobber_o | Output | Used destination registers, includes the FU that is going to write this register | To issue/read operands |
|
||||
| rs1_i | Input | Check the scoreboard for a valid register at that address | From read operands |
|
||||
| rs2_i | Input | Check the scoreboard for a valid register at that address | From read operands |
|
||||
| rs1_o | Output | Data for rs1 | To read operands |
|
||||
| rs1_valid_o | Output | Data for rs1 is valid | To read operands |
|
||||
| rs2_o | Output | Data for rs2 | To read operands |
|
||||
| rs2_valid_o | Output | Data for rs2 is valid | To read operands |
|
||||
| commit_instr_o | Output | Instruction to commit | To WB stage |
|
||||
| commit_ready_i | Input | Commit unit is ready | To WB stage |
|
||||
| decoded_instr_i | Input | Decoded instruction entering scoreboard | From ID |
|
||||
| decoded_instr_valid_i | Input | Decoded instruction entering scoreboard is valid | From ID |
|
||||
| issue_instr_o | Output | Instruction to issue stage | To Issue |
|
||||
| issue_instr_valid_o | Output | Instruction to issue stage is valid | To Issue |
|
||||
| issue_ready_i | Input | Issue stage is ready to accept a new instruction | From Issue |
|
||||
| pc_i | Input | PC at which to write back the data | From WB |
|
||||
| wdata_i | Input | Write data from WB | From WB |
|
||||
| wb_valid_i | Input | Data from WB stage is valid | From WB |
|
||||
| **Signal** | **Direction** | **Description** | **Category** |
|
||||
|-----------------------|---------------|-----------------------------------------------------------------------------------|------------------------|
|
||||
| flush_i | Input | Flush Scoreboard | Control |
|
||||
| full_o | Output | Scoreboard is full | Control |
|
||||
| rd_clobber_o | Output | Used destination registers, includes the FU that is going to write this register | To issue/read operands |
|
||||
| rs1_i | Input | Check the scoreboard for a valid register at that address | From read operands |
|
||||
| rs2_i | Input | Check the scoreboard for a valid register at that address | From read operands |
|
||||
| rs1_o | Output | Data for rs1 | To read operands |
|
||||
| rs1_valid_o | Output | Data for rs1 is valid | To read operands |
|
||||
| rs2_o | Output | Data for rs2 | To read operands |
|
||||
| rs2_valid_o | Output | Data for rs2 is valid | To read operands |
|
||||
| commit_instr_o | Output | Instruction to commit | To WB stage |
|
||||
| commit_ack_i | Input | Commit unit acknowledges instruction, it mus immediately begin with processing it | To WB stage |
|
||||
| decoded_instr_i | Input | Decoded instruction entering scoreboard | From ID |
|
||||
| decoded_instr_valid_i | Input | Decoded instruction entering scoreboard is valid | From ID |
|
||||
| issue_instr_o | Output | Instruction to issue stage | To Issue |
|
||||
| issue_instr_valid_o | Output | Instruction to issue stage is valid | To Issue |
|
||||
| issue_ack_i | Input | Issue stage is acknowledging instruction, it must immediately begin processing | From Issue |
|
||||
| pc_i | Input | PC at which to write back the data | From WB |
|
||||
| wdata_i | Input | Write data from WB | From WB |
|
||||
| wb_valid_i | Input | Data from WB stage is valid | From WB |
|
||||
|
||||
### Issue
|
||||
|
||||
|
|
|
@ -12,3 +12,14 @@ Synthesized @ 0.4 ns, typical case, UMC65:
|
|||
| **Total** | **45568 (~32 kGE)** | **32441 (~23 kGE)** | **16088 (~ 11 kGE)** |
|
||||
|
||||
|
||||
## ALU
|
||||
|
||||
| **Type** | **1.6 ns, worst case, UMC65** |
|
||||
|---------------|-------------------------------|
|
||||
| Sequential | 0 |
|
||||
| Combinatorial | 9019 |
|
||||
| Buffer | 582 |
|
||||
| **Total** | **9019 (~6.4 kGE)** |
|
||||
|
||||
|
||||
w
|
116
scoreboard.sv
116
scoreboard.sv
|
@ -30,7 +30,7 @@ module scoreboard #(
|
|||
|
||||
// advertise instruction to commit stage, if ready_i is asserted advance the commit pointer
|
||||
output dtype commit_instr_o,
|
||||
input logic commit_ready_i,
|
||||
input logic commit_ack_i,
|
||||
|
||||
// instruction to put on top of scoreboard e.g.: top pointer
|
||||
// we can always put this instruction to the top unless we signal with asserted full_o
|
||||
|
@ -40,7 +40,7 @@ module scoreboard #(
|
|||
// instruction to issue logic, if issue_instr_valid and issue_ready is asserted, advance the issue pointer
|
||||
output dtype issue_instr_o,
|
||||
output logic issue_instr_valid_o,
|
||||
input logic issue_ready_i,
|
||||
input logic issue_ack_i,
|
||||
|
||||
// write-back port
|
||||
input logic[63:0] pc_i, // PC at which to write the result back
|
||||
|
@ -51,16 +51,18 @@ localparam BITS_ENTRIES = $clog2(NR_ENTRIES);
|
|||
|
||||
dtype [NR_ENTRIES-1:0] mem;
|
||||
logic [BITS_ENTRIES-1:0] issue_pointer_n, issue_pointer_q, // points to the instruction currently in issue
|
||||
commit_pointer_n, commit_pointer_q, // points to the instruction currently in commit
|
||||
top_pointer_n, top_pointer_q; // points to the top of the scoreboard, an empty slot
|
||||
commit_pointer_n, commit_pointer_q, commit_pointer_qq, // points to the instruction currently in commit
|
||||
top_pointer_n, top_pointer_q, top_pointer_qq; // points to the top of the scoreboard, an empty slot, top pointer two cycles ago
|
||||
|
||||
logic pointer_overflow;
|
||||
logic empty;
|
||||
|
||||
logic reset_condition;
|
||||
// full and empty signaling: signal that we are not able to take new instructions
|
||||
// track pointer overflow
|
||||
assign pointer_overflow = (commit_pointer_q <= top_pointer_q) ? 1'b0 : 1'b1;
|
||||
assign full_o = (pointer_overflow) ? (commit_pointer_q == top_pointer_q) : 1'b0;
|
||||
// && top_pointer_q >= top_pointer_qq
|
||||
assign reset_condition = top_pointer_q == top_pointer_qq;
|
||||
assign pointer_overflow = (top_pointer_q <= commit_pointer_q && ~reset_condition) ? 1'b1 : 1'b0;
|
||||
assign full_o = (reset_condition) ? 1'b0 : (commit_pointer_q == top_pointer_q);
|
||||
assign empty = (pointer_overflow) ? 1'b0 : (commit_pointer_q == top_pointer_q);
|
||||
|
||||
// rd_clobber output: output currently clobbered destination registers
|
||||
|
@ -169,6 +171,7 @@ end
|
|||
// issue instruction: advance the issue pointer
|
||||
always_comb begin : issue_instruction
|
||||
|
||||
|
||||
// provide a combinatorial path in case the scoreboard is empty
|
||||
if (empty) begin
|
||||
issue_instr_o = decoded_instr_i;
|
||||
|
@ -176,12 +179,27 @@ always_comb begin : issue_instruction
|
|||
// if not empty go to scoreboard and get the instruction at the issue pointer
|
||||
end else begin
|
||||
issue_instr_o = mem[$unsigned(issue_pointer_q)];
|
||||
issue_instr_valid_o = 1'b1;
|
||||
// we have not reached the top of the buffer
|
||||
// issue pointer has overflowed
|
||||
if (issue_pointer_q < commit_pointer_q) begin
|
||||
if (issue_pointer_q <= top_pointer_q)
|
||||
issue_instr_valid_o = 1'b1;
|
||||
else
|
||||
issue_instr_valid_o = 1'b0;
|
||||
end else begin // issue pointer has not overflowed
|
||||
if (pointer_overflow)
|
||||
issue_instr_valid_o = 1'b1;
|
||||
else if (issue_pointer_q <= top_pointer_q)
|
||||
issue_instr_valid_o = 1'b1;
|
||||
else
|
||||
issue_instr_valid_o = 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
// default assignment: issue didn't read
|
||||
issue_pointer_n = issue_pointer_q;
|
||||
// advance pointer if the issue logic was ready
|
||||
if (issue_ready_i) begin
|
||||
if (issue_ack_i) begin
|
||||
issue_pointer_n = issue_pointer_q + 1;
|
||||
end
|
||||
|
||||
|
@ -193,7 +211,7 @@ always_comb begin: commit_instruction
|
|||
// we can always safely output the instruction at which the commit pointer points
|
||||
// since the scoreboard entry has a valid bit which the commit stage needs to check anyway
|
||||
commit_instr_o = mem[commit_pointer_q];
|
||||
if (commit_ready_i) begin
|
||||
if (commit_ack_i) begin
|
||||
commit_pointer_n = commit_pointer_q + 1;
|
||||
end
|
||||
end
|
||||
|
@ -201,20 +219,80 @@ end
|
|||
// sequential process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : sequential
|
||||
if(~rst_ni) begin
|
||||
issue_pointer_q <= '{default: 0};
|
||||
commit_pointer_q <= '{default: 0};
|
||||
top_pointer_q <= '{default: 0};
|
||||
issue_pointer_q <= '{default: 0};
|
||||
commit_pointer_q <= '{default: 0};
|
||||
top_pointer_q <= '{default: 0};
|
||||
top_pointer_qq <= '{default: 0};
|
||||
end else if (flush_i) begin // reset pointers on flush
|
||||
issue_pointer_q <= '{default: 0};
|
||||
commit_pointer_q <= '{default: 0};
|
||||
top_pointer_q <= '{default: 0};
|
||||
top_pointer_qq <= '{default: 0};
|
||||
end else begin
|
||||
issue_pointer_q <= issue_pointer_n;
|
||||
commit_pointer_q <= commit_pointer_n;
|
||||
top_pointer_q <= top_pointer_n;
|
||||
issue_pointer_q <= issue_pointer_n;
|
||||
commit_pointer_q <= commit_pointer_n;
|
||||
top_pointer_q <= top_pointer_n;
|
||||
if (decoded_instr_valid_i) // only advance if we decoded instruction
|
||||
top_pointer_qq <= top_pointer_q;
|
||||
end
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
`ifndef verilator
|
||||
assert (NR_ENTRIES == 2**$clog2(NR_ENTRIES)) else $error("Scoreboard size needs to be a power of two.");
|
||||
// there should never be more than one instruction writing the same destination register (except x0)
|
||||
initial begin
|
||||
assert (NR_ENTRIES == 2**$clog2(NR_ENTRIES)) else $fatal("Scoreboard size needs to be a power of two.");
|
||||
end
|
||||
|
||||
// assert that zero is never set
|
||||
assert property (
|
||||
@(posedge clk_i) rst_ni |-> (rd_clobber_o[0] == NONE))
|
||||
else $error ("RD 0 should not bet set");
|
||||
// assert that we never acknowledge a commit if the instruction is not valid
|
||||
assert property (
|
||||
@(posedge clk_i) (rst_ni && commit_ack_i |-> commit_instr_o.valid))
|
||||
else $error ("Commit acknowledged but instruction is not valid");
|
||||
// assert that we never give an issue ack signal if the instruction is not valid
|
||||
assert property (
|
||||
@(posedge clk_i) (rst_ni && issue_ack_i |-> issue_instr_valid_o))
|
||||
else $error ("Issue acknowledged but instruction is not valid");
|
||||
|
||||
// there should never be more than one instruction writing the same destination register (except x0)
|
||||
// assert strict pointer ordering
|
||||
|
||||
// print scoreboard
|
||||
// initial begin
|
||||
// automatic string pointer = "";
|
||||
// static integer f = $fopen("scoreboard.txt", "w");
|
||||
|
||||
// forever begin
|
||||
// wait(rst_ni == 1'b1);
|
||||
// @(posedge clk_i)
|
||||
// $fwrite(f, $time);
|
||||
// $fwrite(f, "\n");
|
||||
// $fwrite(f, "._________________________.\n");
|
||||
// for (int i = 0; i < NR_ENTRIES; i++) begin
|
||||
// if (i == commit_pointer_q && i == issue_pointer_q && i == top_pointer_q)
|
||||
// pointer = " <- top, issue, commit pointer";
|
||||
// else if (i == commit_pointer_q && i == issue_pointer_q)
|
||||
// pointer = " <- issue, commit pointer";
|
||||
// else if (i == top_pointer_q && i == issue_pointer_q)
|
||||
// pointer = " <- top, issue pointer";
|
||||
// else if (i == top_pointer_q && i == commit_pointer_q)
|
||||
// pointer = " <- top, commit pointer";
|
||||
// else if (i == top_pointer_q)
|
||||
// pointer = " <- top pointer";
|
||||
// else if (i == commit_pointer_q)
|
||||
// pointer = " <- commit pointer";
|
||||
// else if (i == issue_pointer_q)
|
||||
// pointer = " <- issue pointer";
|
||||
// else
|
||||
// pointer = "";
|
||||
// $fwrite(f, "|_________________________| %s\n", pointer);
|
||||
// end
|
||||
// $fwrite(f, "\n");
|
||||
// end
|
||||
// $fclose(f);
|
||||
// end
|
||||
`endif
|
||||
`endif
|
||||
endmodule
|
||||
endmodule
|
||||
|
|
|
@ -9,37 +9,39 @@
|
|||
// Guard statement proposed by "Easier UVM" (doulos)
|
||||
`ifndef SCOREBOARD_IF__SV
|
||||
`define SCOREBOARD_IF_SV
|
||||
|
||||
import ariane_pkg::*;
|
||||
|
||||
interface scoreboard_if (input clk);
|
||||
wire rst;
|
||||
wire full;
|
||||
wire flush;
|
||||
wire [31:0][7:0] rd_clobber;
|
||||
wire [31:0][$bits(fu_t)-1:0] rd_clobber;
|
||||
wire [4:0] rs1_address;
|
||||
wire [63:0] rs1;
|
||||
wire rs1_valid;
|
||||
wire [4:0] rs2_address;
|
||||
wire [63:0] rs2;
|
||||
wire rs2_valid;
|
||||
wire commitnstr;
|
||||
wire commit_ready;
|
||||
wire decodednstr;
|
||||
wire decodednstr_valid;
|
||||
wire issuenstr;
|
||||
wire issuenstr_valid;
|
||||
wire issue_ready;
|
||||
scoreboard_entry commit_instr;
|
||||
wire commit_ack;
|
||||
scoreboard_entry decoded_instr;
|
||||
wire decoded_instr_valid;
|
||||
scoreboard_entry issue_instr;
|
||||
wire issue_instr_valid;
|
||||
wire issue_ack;
|
||||
wire [63:0] pc;
|
||||
wire [63:0] wdata;
|
||||
wire wb_valid;
|
||||
|
||||
// Scoreboard interface configured as master
|
||||
clocking mck @(posedge clk);
|
||||
output rst, flush, rs1_address, rs2_address, commit_ready, decodednstr, decodednstr_valid, issue_ready, pc, wdata, wb_valid;
|
||||
input full, rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commitnstr, issuenstr, issuenstr_valid;
|
||||
output flush, rs1_address, rs2_address, commit_ack, decoded_instr, decoded_instr_valid, issue_ack, pc, wdata, wb_valid;
|
||||
input full, rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commit_instr, issue_instr, issue_instr_valid;
|
||||
endclocking
|
||||
// Scoreboard interface configured in passive mode (-> monitor)
|
||||
clocking pck @(posedge clk);
|
||||
input rst, flush, rs1_address, rs2_address, commit_ready, decodednstr, decodednstr_valid, issue_ready, pc, wdata, wb_valid,
|
||||
full, rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commitnstr, issuenstr, issuenstr_valid;
|
||||
input flush, rs1_address, rs2_address, commit_ack, decoded_instr, decoded_instr_valid, issue_ack, pc, wdata, wb_valid,
|
||||
full, rd_clobber, rs1, rs1_valid, rs2, rs2_valid, commit_instr, issue_instr, issue_instr_valid;
|
||||
endclocking
|
||||
|
||||
modport master (clocking mck);
|
||||
|
|
26
tb/alu_tb.sv
26
tb/alu_tb.sv
|
@ -34,32 +34,32 @@ module alu_tb;
|
|||
.is_equal_result_o ( ),
|
||||
.adder_result_ext_o ( ),
|
||||
.adder_result_o ( ),
|
||||
.multdiv_en_i ( 1'b0 ),
|
||||
.multdiv_en_i ( 1'b0 ),
|
||||
.multdiv_operand_b_i ( 65'b0 ),
|
||||
.multdiv_operand_a_i ( 65'b0 )
|
||||
.multdiv_operand_a_i ( 65'b0 )
|
||||
);
|
||||
|
||||
initial begin
|
||||
// register the alu itnerface
|
||||
uvm_config_db #(virtual fu_if)::set(null, "uvm_test_top", "fu_vif", alu_if);
|
||||
// register the ALU interface
|
||||
uvm_config_db #(virtual fu_if)::set(null, "uvm_test_top", "fu_vif", alu_if);
|
||||
end
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
rstn_i = 1'b0;
|
||||
repeat(8) begin
|
||||
#10ns clk = ~clk;
|
||||
end
|
||||
rstn_i = 1'b1;
|
||||
forever begin
|
||||
#10ns clk = ~clk;
|
||||
end
|
||||
rstn_i = 1'b0;
|
||||
repeat(8)
|
||||
#10ns clk = ~clk;
|
||||
|
||||
rstn_i = 1'b1;
|
||||
|
||||
forever
|
||||
#10ns clk = ~clk;
|
||||
end
|
||||
|
||||
initial begin
|
||||
// print the topology
|
||||
uvm_top.enable_print_topology = 1;
|
||||
// Start UVM test
|
||||
// Start UVM test
|
||||
run_test();
|
||||
end
|
||||
endmodule
|
||||
|
|
145
tb/scoreboard_tb.sv
Executable file
145
tb/scoreboard_tb.sv
Executable file
|
@ -0,0 +1,145 @@
|
|||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 10/04/2017
|
||||
// Description: Top level testbench module. Instantiates the top level DUT, configures
|
||||
// the virtual interfaces and starts the test passed by +UVM_TEST+
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// TODO, test register read and clobber interface
|
||||
module scoreboard_tb;
|
||||
|
||||
import uvm_pkg::*;
|
||||
import ariane_pkg::*;
|
||||
|
||||
logic rst_ni, clk;
|
||||
scoreboard_entry scoreboard_queue[$];
|
||||
scoreboard_entry temp_scoreboard_entry;
|
||||
scoreboard_entry comp;
|
||||
|
||||
integer unsigned pc = 0;
|
||||
|
||||
scoreboard_if scoreboard_if (clk);
|
||||
|
||||
scoreboard dut (
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.full_o ( scoreboard_if.full ),
|
||||
.flush_i ( scoreboard_if.flush ),
|
||||
.rd_clobber_o ( scoreboard_if.rd_clobber ),
|
||||
.rs1_i ( scoreboard_if.rs1_address ),
|
||||
.rs1_o ( scoreboard_if.rs1 ),
|
||||
.rs1_valid_o ( scoreboard_if.rs1_valid ),
|
||||
.rs2_i ( scoreboard_if.rs2_address ),
|
||||
.rs2_o ( scoreboard_if.rs2 ),
|
||||
.rs2_valid_o ( scoreboard_if.rs2_valid ),
|
||||
.commit_instr_o ( scoreboard_if.commit_instr ),
|
||||
.commit_ack_i ( scoreboard_if.commit_ack ),
|
||||
.decoded_instr_i ( scoreboard_if.decoded_instr ),
|
||||
.decoded_instr_valid_i( scoreboard_if.decoded_instr_valid ),
|
||||
.issue_instr_o ( scoreboard_if.issue_instr ),
|
||||
.issue_instr_valid_o ( scoreboard_if.issue_instr_valid ),
|
||||
.issue_ack_i ( scoreboard_if.issue_ack ),
|
||||
.pc_i ( scoreboard_if.pc ),
|
||||
.wdata_i ( scoreboard_if.wdata ),
|
||||
.wb_valid_i ( scoreboard_if.wb_valid )
|
||||
);
|
||||
|
||||
function automatic scoreboard_entry randomize_scoreboard();
|
||||
exception exception = { 64'h55, 63'h0, 1'b0};
|
||||
scoreboard_entry entry = {
|
||||
pc, ALU, ADD, 5'h5, 5'h5, 5'h5, 64'h0, 1'b0, 1'b0, exception
|
||||
};
|
||||
pc++;
|
||||
return entry;
|
||||
endfunction : randomize_scoreboard
|
||||
|
||||
initial begin
|
||||
// register the scoreboard interface
|
||||
// uvm_config_db #(virtual scoreboard_if)::set(null, "uvm_test_top", "scoreboard_vif", scoreboard_if);
|
||||
end
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
rst_ni = 1'b0;
|
||||
repeat(8)
|
||||
#10ns clk = ~clk;
|
||||
|
||||
rst_ni = 1'b1;
|
||||
forever
|
||||
#10ns clk = ~clk;
|
||||
end
|
||||
|
||||
// push new decoded instructions
|
||||
initial begin
|
||||
wait(rst_ni == 1'b1);
|
||||
// load the scoreboard until it is full
|
||||
forever begin
|
||||
|
||||
@(scoreboard_if.mck);
|
||||
// if we are not full load another instruction
|
||||
if (scoreboard_if.full == 1'b0) begin
|
||||
temp_scoreboard_entry = randomize_scoreboard();
|
||||
scoreboard_queue.push_back(temp_scoreboard_entry);
|
||||
|
||||
scoreboard_if.mck.decoded_instr <= temp_scoreboard_entry;
|
||||
scoreboard_if.mck.decoded_instr_valid <= 1'b1;
|
||||
end else begin
|
||||
scoreboard_if.mck.decoded_instr_valid <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
scoreboard_entry issue_instruction;
|
||||
// pull e.g. issue instructions
|
||||
initial begin
|
||||
wait(rst_ni == 1'b1);
|
||||
forever begin
|
||||
|
||||
@(scoreboard_if.mck);
|
||||
scoreboard_if.mck.wb_valid <= 1'b0;
|
||||
// if we are not full then load another instruction
|
||||
if (scoreboard_if.issue_instr_valid == 1'b1) begin
|
||||
scoreboard_if.mck.issue_ack <= 1'b1;
|
||||
issue_instruction <= scoreboard_if.mck.issue_instr;
|
||||
@(scoreboard_if.mck)
|
||||
scoreboard_if.mck.issue_ack <= 1'b0;
|
||||
|
||||
// generate a delay between 1 and 3 cycles for WB
|
||||
repeat ($urandom_range(0,3)) @(scoreboard_if.mck);
|
||||
scoreboard_if.mck.pc <= issue_instruction.pc;
|
||||
scoreboard_if.mck.wdata <= 64'h7777;
|
||||
scoreboard_if.mck.wb_valid <= 1'b1;
|
||||
end else begin
|
||||
scoreboard_if.mck.issue_ack <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
// commit instructions
|
||||
initial begin
|
||||
wait(rst_ni == 1'b1);
|
||||
forever begin
|
||||
repeat ($urandom_range(1,3)) @(scoreboard_if.mck);
|
||||
if (scoreboard_if.mck.commit_instr.valid == 1'b1) begin
|
||||
scoreboard_if.mck.commit_ack <= 1'b1;
|
||||
@(scoreboard_if.mck);
|
||||
scoreboard_if.mck.commit_ack <= 1'b0;
|
||||
repeat ($urandom_range(0,3)) @(scoreboard_if.mck);
|
||||
end else
|
||||
scoreboard_if.mck.commit_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
// commit checker e.g.: monitor
|
||||
initial begin
|
||||
wait(rst_ni == 1'b1);
|
||||
|
||||
forever begin
|
||||
@(scoreboard_if.pck);
|
||||
if (scoreboard_if.pck.commit_ack == 1'b1) begin
|
||||
comp = scoreboard_queue.pop_front();
|
||||
assert (comp.pc === scoreboard_if.pck.commit_instr.pc) else $error($sformatf("Mismatch: Expected: %0h Got: %0h", comp.pc, scoreboard_if.pck.commit_instr.pc));
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
27
tb/test/scoreboard_lib_pkg.sv
Executable file
27
tb/test/scoreboard_lib_pkg.sv
Executable file
|
@ -0,0 +1,27 @@
|
|||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 12/20/2016
|
||||
// Description: This package contains all test related functionality.
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
|
||||
package scoreboard_lib_pkg;
|
||||
// Standard UVM import & include:
|
||||
import uvm_pkg::*;
|
||||
`include "uvm_macros.svh"
|
||||
// Import the memory interface agent
|
||||
import scoreboard_if_agent_pkg::*;
|
||||
// import alu_env_pkg::*;
|
||||
// import alu_sequence_pkg::*;
|
||||
// Test based includes like base test class and specializations of it
|
||||
// ----------------
|
||||
// Base test class
|
||||
// ----------------
|
||||
// `include "alu_test_base.svh"
|
||||
// -------------------
|
||||
// Child test classes
|
||||
// -------------------
|
||||
// plain randomized test
|
||||
// `include "alu_test.svh"
|
||||
|
||||
endpackage
|
Loading…
Add table
Add a link
Reference in a new issue