Add singlepulse support
This commit is contained in:
@@ -17,7 +17,7 @@ See ``onread``
|
|||||||
|
|
||||||
singlepulse
|
singlepulse
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|NO|
|
|OK|
|
||||||
|
|
||||||
sw
|
sw
|
||||||
^^^
|
^^^
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from systemrdl.rdltypes import PropertyReference, PrecedenceType
|
|||||||
from .bases import AssignmentPrecedence, NextStateConditional
|
from .bases import AssignmentPrecedence, NextStateConditional
|
||||||
from . import sw_onread
|
from . import sw_onread
|
||||||
from . import sw_onwrite
|
from . import sw_onwrite
|
||||||
|
from . import sw_singlepulse
|
||||||
from . import hw_write
|
from . import hw_write
|
||||||
from . import hw_set_clr
|
from . import hw_set_clr
|
||||||
|
|
||||||
@@ -189,6 +190,8 @@ class FieldLogic:
|
|||||||
self.add_sw_conditional(sw_onwrite.WriteSet(self.exp), AssignmentPrecedence.SW_ONWRITE)
|
self.add_sw_conditional(sw_onwrite.WriteSet(self.exp), AssignmentPrecedence.SW_ONWRITE)
|
||||||
self.add_sw_conditional(sw_onwrite.Write(self.exp), AssignmentPrecedence.SW_ONWRITE)
|
self.add_sw_conditional(sw_onwrite.Write(self.exp), AssignmentPrecedence.SW_ONWRITE)
|
||||||
|
|
||||||
|
self.add_sw_conditional(sw_singlepulse.Singlepulse(self.exp), AssignmentPrecedence.SW_SINGLEPULSE)
|
||||||
|
|
||||||
self.add_hw_conditional(hw_write.AlwaysWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
self.add_hw_conditional(hw_write.AlwaysWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
||||||
self.add_hw_conditional(hw_write.WELWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
self.add_hw_conditional(hw_write.WELWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
||||||
self.add_hw_conditional(hw_write.WEWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
self.add_hw_conditional(hw_write.WEWrite(self.exp), AssignmentPrecedence.HW_WRITE)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class AssignmentPrecedence(enum.IntEnum):
|
|||||||
# Software access assignment groups
|
# Software access assignment groups
|
||||||
SW_ONREAD = 5000
|
SW_ONREAD = 5000
|
||||||
SW_ONWRITE = 4000
|
SW_ONWRITE = 4000
|
||||||
|
SW_SINGLEPULSE = 3000
|
||||||
|
|
||||||
# Hardware access assignment groups
|
# Hardware access assignment groups
|
||||||
HW_WRITE = 3000
|
HW_WRITE = 3000
|
||||||
|
|||||||
23
peakrdl/regblock/field_logic/sw_singlepulse.py
Normal file
23
peakrdl/regblock/field_logic/sw_singlepulse.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from typing import TYPE_CHECKING, List
|
||||||
|
|
||||||
|
from .bases import NextStateConditional
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from systemrdl.node import FieldNode
|
||||||
|
|
||||||
|
class Singlepulse(NextStateConditional):
|
||||||
|
comment = "singlepulse clears back to 0"
|
||||||
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
|
return field.get_property('singlepulse')
|
||||||
|
|
||||||
|
def get_predicate(self, field: 'FieldNode') -> str:
|
||||||
|
# TODO: make exporter promote this to an "else"?
|
||||||
|
# Be mindful of sw/hw precedence. this would have to come last regardless
|
||||||
|
return "1"
|
||||||
|
|
||||||
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
|
field_path = self.get_field_path(field)
|
||||||
|
return [
|
||||||
|
f"field_combo.{field_path}.next = '0;",
|
||||||
|
f"field_combo.{field_path}.load_next = '1;",
|
||||||
|
]
|
||||||
0
test/test_singlepulse/__init__.py
Normal file
0
test/test_singlepulse/__init__.py
Normal file
8
test/test_singlepulse/regblock.rdl
Normal file
8
test/test_singlepulse/regblock.rdl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
addrmap top {
|
||||||
|
reg {
|
||||||
|
field {
|
||||||
|
sw=rw; hw=r;
|
||||||
|
singlepulse;
|
||||||
|
} f[0:0] = 0;
|
||||||
|
} r1;
|
||||||
|
};
|
||||||
56
test/test_singlepulse/tb_template.sv
Normal file
56
test/test_singlepulse/tb_template.sv
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{% extends "lib/templates/tb_base.sv" %}
|
||||||
|
|
||||||
|
{% block seq %}
|
||||||
|
{% sv_line_anchor %}
|
||||||
|
int event_count;
|
||||||
|
|
||||||
|
##1;
|
||||||
|
cb.rst <= '0;
|
||||||
|
##1;
|
||||||
|
|
||||||
|
// No pulse if writing zero
|
||||||
|
event_count = 0;
|
||||||
|
fork
|
||||||
|
begin
|
||||||
|
##0;
|
||||||
|
forever begin
|
||||||
|
@cb;
|
||||||
|
if(cb.hwif_out.r1.f.value) begin
|
||||||
|
event_count++;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
cpuif.write('h0, 'h0);
|
||||||
|
repeat(5) @cb;
|
||||||
|
end
|
||||||
|
join_any
|
||||||
|
disable fork;
|
||||||
|
assert(event_count == 0) else $error("Observed excess singlepulse events: %0d", event_count);
|
||||||
|
|
||||||
|
// single pulse
|
||||||
|
event_count = 0;
|
||||||
|
fork
|
||||||
|
begin
|
||||||
|
##0;
|
||||||
|
forever begin
|
||||||
|
@cb;
|
||||||
|
if(cb.hwif_out.r1.f.value) begin
|
||||||
|
event_count++;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
cpuif.write('h0, 'h1);
|
||||||
|
repeat(5) @cb;
|
||||||
|
end
|
||||||
|
join_any
|
||||||
|
disable fork;
|
||||||
|
assert(event_count == 1) else $error("Observed incorrect number of singlepulse events: %0d", event_count);
|
||||||
|
|
||||||
|
// auto-clears
|
||||||
|
cpuif.assert_read('h0, 'h0);
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
5
test/test_singlepulse/testcase.py
Normal file
5
test/test_singlepulse/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