forked from everactive/bathtub
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main' into pages
- Loading branch information
Showing
17 changed files
with
5,468 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
https://edaplayground.com/x/Prp5 | ||
|
||
Bathtub is described in my paper "Gherkin Implementation in SystemVerilog Brings Agile Behavior-Driven Development to UVM" at DVCon U.S. 2024. | ||
The purpose of this playground is to validate the code samples included in the paper. | ||
It's a very minimal test bench for a simple ALU. | ||
The test runs and passes. | ||
|
||
File `testbench.sv` is just that, the test bench. | ||
It contains: | ||
* Test class `bathtub_test` as included in the paper | ||
* Environment class `alu_env` as briefly described in the paper | ||
* Virtual sequencer `alu_sequencer` as mentioned in the paper | ||
* Virtual sequence base class `alu_base_vsequence` as mentioned in the paper | ||
|
||
File `alu_division.feature` is the Gherkin feature file featured in the paper. | ||
|
||
File `alu_step_definition.svh` contains all four step definitions required for the feature file, two of which are included in the paper. | ||
|
||
--- | ||
https://github.com/williaml33moore/bathtub/commit/c666c807ca38988f1370ca9f4591161104a126a0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# This Gherkin feature file's name is alu_division.feature | ||
|
||
Feature: Arithmetic Logic Unit division operations | ||
|
||
The arithmetic logic unit performs integer division. | ||
|
||
Scenario: In integer division, the remainder is discarded | ||
Given operand A is 15 and operand B is 4 | ||
When the ALU performs the division operation | ||
Then the result should be 3 | ||
And the DIV_BY_ZERO flag should be clear | ||
|
||
Scenario: Attempting to divide by zero results in an error | ||
Given operand A is 10 and operand B is 0 | ||
When the ALU performs the division operation | ||
Then the DIV_BY_ZERO flag should be raised | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
`ifndef ALU_STEP_DEFINITION_SVH | ||
`define ALU_STEP_DEFINITION_SVH | ||
|
||
import bathtub_pkg::*; | ||
|
||
class set_operand_A_and_B_vseq extends alu_base_vsequence implements bathtub_pkg::step_definition_interface; | ||
`Given("operand A is %d and operand B is %d") | ||
int operand_A, operand_B; | ||
`uvm_object_utils(set_operand_A_and_B_vseq) | ||
function new (string name="set_operand_A_and_B_vseq"); | ||
super.new(name); | ||
endfunction : new | ||
virtual task body(); | ||
// Extract the parameters | ||
`step_parameter_get_args_begin() | ||
operand_A = `step_parameter_get_next_arg_as(int); | ||
operand_B = `step_parameter_get_next_arg_as(int); | ||
`step_parameter_get_args_end | ||
// Do the actual work using the API in the base sequence | ||
super.set_operand_A(operand_A); | ||
super.set_operand_B(operand_B); | ||
endtask : body | ||
endclass : set_operand_A_and_B_vseq | ||
|
||
|
||
|
||
class check_DIV_BY_ZERO_flag_vseq extends alu_base_vsequence implements bathtub_pkg::step_definition_interface; | ||
`Then("the DIV_BY_ZERO flag should be %s") | ||
string flag_arg; | ||
bit expected_flag; | ||
bit actual_flag; | ||
`uvm_object_utils(check_DIV_BY_ZERO_flag_vseq) | ||
function new (string name="check_DIV_BY_ZERO_flag_vseq"); | ||
super.new(name); | ||
endfunction : new | ||
virtual task body(); | ||
// Extract the parameter | ||
`step_parameter_get_args_begin() | ||
flag_arg = `step_parameter_get_next_arg_as(string); | ||
`step_parameter_get_args_end | ||
case (flag_arg) // convert the string to a bit value | ||
"raised", "asserted" : expected_flag = 1; | ||
"clear", "deasserted" : expected_flag = 0; | ||
default: `uvm_error("UNEXPECTED ARG", flag_arg) | ||
endcase | ||
super.get_div_by_zero_flag(actual_flag); | ||
check_DIV_BY_ZERO_flag : assert (expected_flag === actual_flag) else | ||
`uvm_error("MISMATCH", $sformatf("expected %b; actual %b", expected_flag, actual_flag)) | ||
endtask : body | ||
endclass : check_DIV_BY_ZERO_flag_vseq | ||
|
||
|
||
class do_division_operation_vseq extends alu_base_vsequence implements bathtub_pkg::step_definition_interface; | ||
`When("the ALU performs the division operation") | ||
int operation; | ||
`uvm_object_utils(do_division_operation_vseq) | ||
function new (string name="do_division_operation_vseq"); | ||
super.new(name); | ||
endfunction : new | ||
virtual task body(); | ||
operation = DIVIDE; | ||
super.do_operation(operation); | ||
endtask : body | ||
endclass : do_division_operation_vseq | ||
|
||
|
||
class check_result_vseq extends alu_base_vsequence implements bathtub_pkg::step_definition_interface; | ||
`Then("the result should be %d") | ||
int expected_result; | ||
int actual_result; | ||
`uvm_object_utils(check_result_vseq) | ||
function new (string name="check_DIV_BY_ZERO_flag_vseq"); | ||
super.new(name); | ||
endfunction : new | ||
virtual task body(); | ||
// Extract the parameter | ||
`step_parameter_get_args_begin() | ||
expected_result = `step_parameter_get_next_arg_as(int); | ||
`step_parameter_get_args_end | ||
super.get_result(actual_result); | ||
check_result : assert (expected_result === actual_result) else | ||
`uvm_error("MISMATCH", $sformatf("expected %0d; actual %0d", expected_result, actual_result)) | ||
endtask : body | ||
endclass : check_result_vseq | ||
|
||
`endif // ALU_STEP_DEFINITION_SVH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
|
||
`ifndef BATHTUB_MACROS_SV | ||
`define BATHTUB_MACROS_SV | ||
|
||
`ifdef EDAPG | ||
`undef BATHTUB__MULTILINE_MACRO_IS_OK | ||
`else | ||
`define BATHTUB__MULTILINE_MACRO_IS_OK | ||
`endif | ||
|
||
`define Given(e) `__register_step_def(bathtub_pkg::Given, e) | ||
|
||
`define When(e) `__register_step_def(bathtub_pkg::When, e) | ||
|
||
`define Then(e) `__register_step_def(bathtub_pkg::Then, e) | ||
|
||
`ifdef BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
`define __register_step_def(k, e) static bathtub_pkg::step_static_attributes_interface __step_static_attributes = bathtub_pkg::step_nature::register_step(k, e, get_type());\ | ||
bathtub_pkg::step_attributes_interface __step_attributes;\ | ||
virtual function bathtub_pkg::step_static_attributes_interface get_step_static_attributes();\ | ||
return __step_static_attributes;\ | ||
endfunction : get_step_static_attributes\ | ||
virtual function bathtub_pkg::step_attributes_interface get_step_attributes();\ | ||
return __step_attributes;\ | ||
endfunction : get_step_attributes\ | ||
virtual function void set_step_attributes(bathtub_pkg::step_attributes_interface step_attributes);\ | ||
this.__step_attributes = step_attributes;\ | ||
endfunction : set_step_attributes\ | ||
virtual function bathtub_pkg::feature_sequence_interface get_current_feature_sequence();\ | ||
return this.__step_attributes.get_current_feature_sequence();\ | ||
endfunction : get_current_feature_sequence\ | ||
virtual function void set_current_feature_sequence(bathtub_pkg::feature_sequence_interface seq);\ | ||
this.__step_attributes.set_current_feature_sequence(seq);\ | ||
endfunction : set_current_feature_sequence\ | ||
virtual function bathtub_pkg::scenario_sequence_interface get_current_scenario_sequence();\ | ||
return this.__step_attributes.get_current_scenario_sequence();\ | ||
endfunction : get_current_scenario_sequence\ | ||
virtual function void set_current_scenario_sequence(bathtub_pkg::scenario_sequence_interface seq);\ | ||
this.__step_attributes.set_current_scenario_sequence(seq);\ | ||
endfunction : set_current_scenario_sequence | ||
|
||
`else // BATHTUB__MULTILINE_MACRO_IS_OK | ||
`define __register_step_def(k, e) static bathtub_pkg::step_static_attributes_interface __step_static_attributes = bathtub_pkg::step_nature::register_step(k, e, get_type()); bathtub_pkg::step_attributes_interface __step_attributes; virtual function bathtub_pkg::step_static_attributes_interface get_step_static_attributes(); return __step_static_attributes; endfunction : get_step_static_attributes virtual function bathtub_pkg::step_attributes_interface get_step_attributes(); return __step_attributes; endfunction : get_step_attributes virtual function void set_step_attributes(bathtub_pkg::step_attributes_interface step_attributes); this.__step_attributes = step_attributes; endfunction : set_step_attributes virtual function bathtub_pkg::feature_sequence_interface get_current_feature_sequence(); return this.__step_attributes.get_current_feature_sequence(); endfunction : get_current_feature_sequence virtual function void set_current_feature_sequence(bathtub_pkg::feature_sequence_interface seq); this.__step_attributes.set_current_feature_sequence(seq); endfunction : set_current_feature_sequence virtual function bathtub_pkg::scenario_sequence_interface get_current_scenario_sequence(); return this.__step_attributes.get_current_scenario_sequence(); endfunction : get_current_scenario_sequence virtual function void set_current_scenario_sequence(bathtub_pkg::scenario_sequence_interface seq); this.__step_attributes.set_current_scenario_sequence(seq); endfunction : set_current_scenario_sequence | ||
`endif // BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
`ifdef BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
`define virtual_step_definition(e) virtual function bathtub_pkg::step_static_attributes_interface get_step_static_attributes();\ | ||
return null;\ | ||
endfunction : get_step_static_attributes\ | ||
virtual function bathtub_pkg::step_attributes_interface get_step_attributes();\ | ||
return null;\ | ||
endfunction : get_step_attributes\ | ||
virtual function void set_step_attributes(bathtub_pkg::step_attributes_interface step_attributes);\ | ||
endfunction : set_step_attributes\ | ||
virtual function bathtub_pkg::feature_sequence_interface get_current_feature_sequence();\ | ||
return null;\ | ||
endfunction : get_current_feature_sequence\ | ||
virtual function void set_current_feature_sequence(bathtub_pkg::feature_sequence_interface seq);\ | ||
endfunction : set_current_feature_sequence\ | ||
virtual function bathtub_pkg::scenario_sequence_interface get_current_scenario_sequence();\ | ||
return null;\ | ||
endfunction : get_current_scenario_sequence\ | ||
virtual function void set_current_scenario_sequence(bathtub_pkg::scenario_sequence_interface seq);\ | ||
endfunction : set_current_scenario_sequence | ||
|
||
`else // BATHTUB__MULTILINE_MACRO_IS_OK | ||
`define virtual_step_definition(e) virtual function bathtub_pkg::step_static_attributes_interface get_step_static_attributes(); return null; endfunction : get_step_static_attributes virtual function bathtub_pkg::step_attributes_interface get_step_attributes(); return null; endfunction : get_step_attributes virtual function void set_step_attributes(bathtub_pkg::step_attributes_interface step_attributes); endfunction : set_step_attributes virtual function bathtub_pkg::feature_sequence_interface get_current_feature_sequence(); return null; endfunction : get_current_feature_sequence virtual function void set_current_feature_sequence(bathtub_pkg::feature_sequence_interface seq); endfunction : set_current_feature_sequence virtual function bathtub_pkg::scenario_sequence_interface get_current_scenario_sequence(); return null; endfunction : get_current_scenario_sequence virtual function void set_current_scenario_sequence(bathtub_pkg::scenario_sequence_interface seq); endfunction : set_current_scenario_sequence | ||
`endif // BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
|
||
|
||
`ifdef BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
`define step_parameter_get_args_begin(f=get_step_attributes().get_expression())\ | ||
begin : step_parameter_get_args\ | ||
step_parameters __step_params;\ | ||
int __next = 0;\ | ||
__step_params = step_parameters::create_new("__step_params", get_step_attributes().get_text(), f); | ||
|
||
`else // BATHTUB__MULTILINE_MACRO_IS_OK | ||
`define step_parameter_get_args_begin(f=get_step_attributes().get_expression()) begin : step_parameter_get_args step_parameters __step_params; int __next = 0; __step_params = step_parameters::create_new("__step_params", get_step_attributes().get_text(), f); | ||
`endif // BATHTUB__MULTILINE_MACRO_IS_OK | ||
|
||
`define step_parameter_get_arg_object(i) __step_params.get_arg(i) | ||
|
||
`define step_parameter_get_arg_as(i, t) `step_parameter_get_arg_object(i).as_``t() | ||
|
||
`define step_parameter_get_next_arg_object `step_parameter_get_arg_object(__next++) | ||
|
||
`define step_parameter_get_next_arg_as(t) `step_parameter_get_next_arg_object.as_``t() | ||
|
||
`define step_parameter_num_args __step_params.num_args() | ||
|
||
`define step_parameter_get_args_end end : step_parameter_get_args | ||
|
||
`define get_scope_name(d) ($sformatf("%m")) // TODO - Extract the last segment | ||
|
||
`endif // BATHTUB_MACROS_SV |
Oops, something went wrong.