From 3dee0904671a5c3df030ef603a02c947da8828a5 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Sat, 11 Dec 2021 23:37:00 -0800 Subject: [PATCH] finish counters --- doc/props/field.rst | 16 +-- peakrdl/regblock/field_logic/generators.py | 13 +++ peakrdl/regblock/hwif.py | 5 +- test/test_counter_basics/regblock.rdl | 3 +- test/test_counter_basics/tb_template.sv | 56 +++++++++- test/test_counter_threshold/__init__.py | 0 test/test_counter_threshold/regblock.rdl | 36 +++++++ test/test_counter_threshold/tb_template.sv | 115 +++++++++++++++++++++ test/test_counter_threshold/testcase.py | 5 + 9 files changed, 238 insertions(+), 11 deletions(-) create mode 100644 test/test_counter_threshold/__init__.py create mode 100644 test/test_counter_threshold/regblock.rdl create mode 100644 test/test_counter_threshold/tb_template.sv create mode 100644 test/test_counter_threshold/testcase.py diff --git a/doc/props/field.rst b/doc/props/field.rst index f4a0ca3..7b15333 100644 --- a/doc/props/field.rst +++ b/doc/props/field.rst @@ -217,17 +217,17 @@ asserted if the counter value is greater or equal to the threshold. boolean - |EX| + |OK| If true, threshold is the counter's maximum count value. (2^width - 1) integer - |EX| + |OK| Specify a static threshold value. reference - |EX| + |OK| Specify a dynamic threshold value. @@ -252,7 +252,7 @@ property defines the signal's width. overflow ^^^^^^^^ -|EX| +|OK| If true, infers an output signal ``hwif_out..overflow`` that is asserted when the counter is about to wrap. @@ -323,17 +323,17 @@ asserted if the counter value is less than or equal to the threshold. boolean - |EX| + |OK| If true, threshold is 0. integer - |EX| + |OK| Specify a static threshold value. reference - |EX| + |OK| Specify a dynamic threshold value. @@ -357,7 +357,7 @@ property defines the signal's width. underflow ^^^^^^^^^ -|EX| +|OK| If true, infers an output signal ``hwif_out..underflow`` that is asserted when the counter is about to wrap. diff --git a/peakrdl/regblock/field_logic/generators.py b/peakrdl/regblock/field_logic/generators.py index 5781667..7716880 100644 --- a/peakrdl/regblock/field_logic/generators.py +++ b/peakrdl/regblock/field_logic/generators.py @@ -177,3 +177,16 @@ class FieldLogicGenerator(RDLForLoopGenerator): self.add_content( f"assign {output_identifier} = {value};" ) + + if node.get_property('overflow'): + output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "overflow") + value = self.field_logic.get_field_combo_identifier(node, 'overflow') + self.add_content( + f"assign {output_identifier} = {value};" + ) + if node.get_property('underflow'): + output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "underflow") + value = self.field_logic.get_field_combo_identifier(node, 'underflow') + self.add_content( + f"assign {output_identifier} = {value};" + ) diff --git a/peakrdl/regblock/hwif.py b/peakrdl/regblock/hwif.py index 62e1edd..017b68b 100644 --- a/peakrdl/regblock/hwif.py +++ b/peakrdl/regblock/hwif.py @@ -291,6 +291,9 @@ class Hwif: def get_implied_prop_output_identifier(self, field: FieldNode, prop: str) -> str: - assert prop in {"anded", "ored", "xored", "swmod", "swacc"} + assert prop in { + "anded", "ored", "xored", "swmod", "swacc", + "incrthreshold", "decrthreshold", "overflow", "underflow" + } path = get_indexed_path(self.top_node, field) return "hwif_out." + path + "." + prop diff --git a/test/test_counter_basics/regblock.rdl b/test/test_counter_basics/regblock.rdl index 47e55d5..b8cb0c1 100644 --- a/test/test_counter_basics/regblock.rdl +++ b/test/test_counter_basics/regblock.rdl @@ -12,9 +12,10 @@ addrmap top { decrvalue=1; } down[11:8] = 0x4; field { - sw=r; hw=na; counter; + sw=r; hw=r; counter; incrvalue=1; decrvalue=1; + overflow; underflow; } updown[15:12] = 0; field { diff --git a/test/test_counter_basics/tb_template.sv b/test/test_counter_basics/tb_template.sv index 55fa61c..0629271 100644 --- a/test/test_counter_basics/tb_template.sv +++ b/test/test_counter_basics/tb_template.sv @@ -49,6 +49,61 @@ cb.hwif_in.simple.updown.incr <= '0; cpuif.assert_read('h0, 'h0000, 'hF000); + // up/down external underflow + fork + begin + ##0; + forever begin + assert(cb.hwif_out.simple.updown.value == 0); + if(cb.hwif_out.simple.updown.underflow) break; + @cb; + end + @cb; + forever begin + assert(cb.hwif_out.simple.updown.value == 15); + assert(cb.hwif_out.simple.updown.underflow == 0); + @cb; + end + end + + begin + repeat(2) @cb; + cb.hwif_in.simple.updown.decr <= '1; + @cb; + cb.hwif_in.simple.updown.decr <= '0; + repeat(2) @cb; + end + join_any + disable fork; + + // up/down external overflow + fork + begin + ##0; + forever begin + assert(cb.hwif_out.simple.updown.value == 15); + if(cb.hwif_out.simple.updown.overflow) break; + @cb; + end + @cb; + forever begin + assert(cb.hwif_out.simple.updown.value == 0); + assert(cb.hwif_out.simple.updown.overflow == 0); + @cb; + end + end + + begin + repeat(2) @cb; + cb.hwif_in.simple.updown.incr <= '1; + @cb; + cb.hwif_in.simple.updown.incr <= '0; + repeat(2) @cb; + end + join_any + disable fork; + + // up/down via sw cpuif.assert_read('h0, 'h00000, 'hF0000); repeat(3) cpuif.write('h0, 'h4000_0000); // incr @@ -89,5 +144,4 @@ cpuif.assert_read('h0, 'h8000000, 'hF000000); repeat(2) cpuif.write('h0, 'h8000_0000 + (2'h3 << 28)); // - 3 cpuif.assert_read('h0, 'h2000000, 'hF000000); - {% endblock %} diff --git a/test/test_counter_threshold/__init__.py b/test/test_counter_threshold/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_counter_threshold/regblock.rdl b/test/test_counter_threshold/regblock.rdl new file mode 100644 index 0000000..4c5e8f8 --- /dev/null +++ b/test/test_counter_threshold/regblock.rdl @@ -0,0 +1,36 @@ +addrmap top { + reg { + field { + sw=r; hw=r; counter; + incrthreshold; + decrthreshold; + } count[4] = 0; + } threshold_via_bool @ 0x0; + + + reg { + field { + sw=r; hw=r; counter; + incrthreshold = 10; + decrthreshold = 5; + } count[4] = 0; + } threshold_via_const @ 0x4; + + + reg { + field { + sw=r; hw=r; counter; + } count[4] = 0; + } threshold_via_ref @ 0x8; + + reg { + field { + sw=rw; hw=na; + } min[4] = 0x4; + field { + sw=rw; hw=na; + } max[4] = 0xB; + } threshold_control @ 0xC; + threshold_via_ref.count -> decrthreshold = threshold_control.min; + threshold_via_ref.count -> incrthreshold = threshold_control.max; +}; diff --git a/test/test_counter_threshold/tb_template.sv b/test/test_counter_threshold/tb_template.sv new file mode 100644 index 0000000..145bc6e --- /dev/null +++ b/test/test_counter_threshold/tb_template.sv @@ -0,0 +1,115 @@ +{% extends "lib/tb_base.sv" %} + +{% block seq %} + {% sv_line_anchor %} + ##1; + cb.rst <= '0; + ##1; + + //-------------------------------------------------------------------------- + // Test incrthreshold = true; incrthreshold = true; + //-------------------------------------------------------------------------- + cpuif.assert_read('h0, 'h0); + + fork + begin + forever begin + @cb; + if(cb.hwif_out.threshold_via_bool.count.value == 0) + assert(cb.hwif_out.threshold_via_bool.count.decrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_bool.count.decrthreshold == 1'b0); + + if(cb.hwif_out.threshold_via_bool.count.value == 15) + assert(cb.hwif_out.threshold_via_bool.count.incrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_bool.count.incrthreshold == 1'b0); + end + end + + begin + @cb; + cb.hwif_in.threshold_via_bool.count.incr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_bool.count.incr <= '0; + cb.hwif_in.threshold_via_bool.count.decr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_bool.count.decr <= '0; + @cb; + @cb; + end + join_any + disable fork; + + //-------------------------------------------------------------------------- + // Test incrthreshold = 10; incrthreshold = 5; + //-------------------------------------------------------------------------- + cpuif.assert_read('h4, 'h0); + + fork + begin + forever begin + @cb; + if(cb.hwif_out.threshold_via_const.count.value <= 5) + assert(cb.hwif_out.threshold_via_const.count.decrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_const.count.decrthreshold == 1'b0); + + if(cb.hwif_out.threshold_via_const.count.value >= 10) + assert(cb.hwif_out.threshold_via_const.count.incrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_const.count.incrthreshold == 1'b0); + end + end + + begin + @cb; + cb.hwif_in.threshold_via_const.count.incr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_const.count.incr <= '0; + cb.hwif_in.threshold_via_const.count.decr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_const.count.decr <= '0; + @cb; + @cb; + end + join_any + disable fork; + + //-------------------------------------------------------------------------- + // Test incrthreshold = ref; incrthreshold =ref; + //-------------------------------------------------------------------------- + cpuif.assert_read('h8, 'h0); + + fork + begin + forever begin + @cb; + if(cb.hwif_out.threshold_via_ref.count.value <= 4) + assert(cb.hwif_out.threshold_via_ref.count.decrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_ref.count.decrthreshold == 1'b0); + + if(cb.hwif_out.threshold_via_ref.count.value >= 11) + assert(cb.hwif_out.threshold_via_ref.count.incrthreshold == 1'b1); + else + assert(cb.hwif_out.threshold_via_ref.count.incrthreshold == 1'b0); + end + end + + begin + @cb; + cb.hwif_in.threshold_via_ref.count.incr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_ref.count.incr <= '0; + cb.hwif_in.threshold_via_ref.count.decr <= '1; + repeat(32) @cb; + cb.hwif_in.threshold_via_ref.count.decr <= '0; + @cb; + @cb; + end + join_any + disable fork; + + +{% endblock %} diff --git a/test/test_counter_threshold/testcase.py b/test/test_counter_threshold/testcase.py new file mode 100644 index 0000000..b458d3c --- /dev/null +++ b/test/test_counter_threshold/testcase.py @@ -0,0 +1,5 @@ +from ..lib.regblock_testcase import RegblockTestCase + +class Test(RegblockTestCase): + def test_dut(self): + self.run_test()