finish counters
This commit is contained in:
@@ -217,17 +217,17 @@ asserted if the counter value is greater or equal to the threshold.
|
|||||||
|
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
If true, threshold is the counter's maximum count value. (2^width - 1)
|
If true, threshold is the counter's maximum count value. (2^width - 1)
|
||||||
|
|
||||||
integer
|
integer
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
Specify a static threshold value.
|
Specify a static threshold value.
|
||||||
|
|
||||||
reference
|
reference
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
Specify a dynamic threshold value.
|
Specify a dynamic threshold value.
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ property defines the signal's width.
|
|||||||
|
|
||||||
overflow
|
overflow
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
If true, infers an output signal ``hwif_out..overflow`` that is asserted when
|
If true, infers an output signal ``hwif_out..overflow`` that is asserted when
|
||||||
the counter is about to wrap.
|
the counter is about to wrap.
|
||||||
@@ -323,17 +323,17 @@ asserted if the counter value is less than or equal to the threshold.
|
|||||||
|
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
If true, threshold is 0.
|
If true, threshold is 0.
|
||||||
|
|
||||||
integer
|
integer
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
Specify a static threshold value.
|
Specify a static threshold value.
|
||||||
|
|
||||||
reference
|
reference
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
Specify a dynamic threshold value.
|
Specify a dynamic threshold value.
|
||||||
|
|
||||||
@@ -357,7 +357,7 @@ property defines the signal's width.
|
|||||||
|
|
||||||
underflow
|
underflow
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|EX|
|
|OK|
|
||||||
|
|
||||||
If true, infers an output signal ``hwif_out..underflow`` that is asserted when
|
If true, infers an output signal ``hwif_out..underflow`` that is asserted when
|
||||||
the counter is about to wrap.
|
the counter is about to wrap.
|
||||||
|
|||||||
@@ -177,3 +177,16 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
self.add_content(
|
self.add_content(
|
||||||
f"assign {output_identifier} = {value};"
|
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};"
|
||||||
|
)
|
||||||
|
|||||||
@@ -291,6 +291,9 @@ class Hwif:
|
|||||||
|
|
||||||
|
|
||||||
def get_implied_prop_output_identifier(self, field: FieldNode, prop: str) -> str:
|
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)
|
path = get_indexed_path(self.top_node, field)
|
||||||
return "hwif_out." + path + "." + prop
|
return "hwif_out." + path + "." + prop
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ addrmap top {
|
|||||||
decrvalue=1;
|
decrvalue=1;
|
||||||
} down[11:8] = 0x4;
|
} down[11:8] = 0x4;
|
||||||
field {
|
field {
|
||||||
sw=r; hw=na; counter;
|
sw=r; hw=r; counter;
|
||||||
incrvalue=1;
|
incrvalue=1;
|
||||||
decrvalue=1;
|
decrvalue=1;
|
||||||
|
overflow; underflow;
|
||||||
} updown[15:12] = 0;
|
} updown[15:12] = 0;
|
||||||
|
|
||||||
field {
|
field {
|
||||||
|
|||||||
@@ -49,6 +49,61 @@
|
|||||||
cb.hwif_in.simple.updown.incr <= '0;
|
cb.hwif_in.simple.updown.incr <= '0;
|
||||||
cpuif.assert_read('h0, 'h0000, 'hF000);
|
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
|
// up/down via sw
|
||||||
cpuif.assert_read('h0, 'h00000, 'hF0000);
|
cpuif.assert_read('h0, 'h00000, 'hF0000);
|
||||||
repeat(3) cpuif.write('h0, 'h4000_0000); // incr
|
repeat(3) cpuif.write('h0, 'h4000_0000); // incr
|
||||||
@@ -89,5 +144,4 @@
|
|||||||
cpuif.assert_read('h0, 'h8000000, 'hF000000);
|
cpuif.assert_read('h0, 'h8000000, 'hF000000);
|
||||||
repeat(2) cpuif.write('h0, 'h8000_0000 + (2'h3 << 28)); // - 3
|
repeat(2) cpuif.write('h0, 'h8000_0000 + (2'h3 << 28)); // - 3
|
||||||
cpuif.assert_read('h0, 'h2000000, 'hF000000);
|
cpuif.assert_read('h0, 'h2000000, 'hF000000);
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
0
test/test_counter_threshold/__init__.py
Normal file
0
test/test_counter_threshold/__init__.py
Normal file
36
test/test_counter_threshold/regblock.rdl
Normal file
36
test/test_counter_threshold/regblock.rdl
Normal file
@@ -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;
|
||||||
|
};
|
||||||
115
test/test_counter_threshold/tb_template.sv
Normal file
115
test/test_counter_threshold/tb_template.sv
Normal file
@@ -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 %}
|
||||||
5
test/test_counter_threshold/testcase.py
Normal file
5
test/test_counter_threshold/testcase.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from ..lib.regblock_testcase import RegblockTestCase
|
||||||
|
|
||||||
|
class Test(RegblockTestCase):
|
||||||
|
def test_dut(self):
|
||||||
|
self.run_test()
|
||||||
Reference in New Issue
Block a user