diff --git a/docs/dev_notes/Validation Needed b/docs/dev_notes/Validation Needed index c30fed6..6fc6317 100644 --- a/docs/dev_notes/Validation Needed +++ b/docs/dev_notes/Validation Needed @@ -102,10 +102,6 @@ X Signals marked as field_reset or cpuif_reset need to have activehigh/activelow X incrvalue/decrvalue needs to be the same or narrower than counter itself -! singlepulse and next properties cannot both be used. - Both are hard overrides of the field's next value. - singlepulse is basically an alias for next=0 that takes lowest priority - ! counter field that saturates should not set overflow counter; incrsaturate; overflow; counter; decrsaturate; underflow; @@ -117,6 +113,7 @@ X incrvalue/decrvalue needs to be the same or narrower than counter itself ! incrwidth/decrwidth must be between 1 and the width of the counter +X field shall be hw writable if "next" is assigned. ================================================================================ Things that need validation by this exporter diff --git a/docs/props/field.rst b/docs/props/field.rst index 273e431..a2a6e20 100644 --- a/docs/props/field.rst +++ b/docs/props/field.rst @@ -45,7 +45,7 @@ operation. {signal: [ {name: 'clk', wave: 'p....'}, - {name: 'hwif_in..value', wave: 'x.=x.', data: ['D']}, + {name: 'hwif_in..next', wave: 'x.=x.', data: ['D']}, {name: 'hwif_out..swacc', wave: '0.10.'} ]} @@ -106,7 +106,10 @@ hw Controls hardware access to the field. If readable, enables output signal ``hwif_out..value``. If writable, enables -input ``hwif_in..value``. +input ``hwif_in..next``. + +Hardware-writable fields can optionally define the ``next`` property which replaces +the inferred ``hwif_in..next`` input with an alternate reference. hwclr/hwset @@ -140,7 +143,7 @@ If true, infers the existence of input signal: ``hwif_in..we``, ``hwif_in..wel`` {signal: [ {name: 'clk', wave: 'p....'}, - {name: 'hwif_in..value', wave: 'x.=x.', data: ['D']}, + {name: 'hwif_in..next', wave: 'x.=x.', data: ['D']}, {name: 'hwif_in..we', wave: '0.10.',}, {name: 'hwif_in..wel', wave: '1.01.',}, {name: '', wave: 'x..=.', data: ['D']} @@ -390,10 +393,33 @@ the counter is about to wrap. Interrupt Properties -------------------- +intr +^^^^ + +level (default) + |NO| + +posedge + |NO| + +negedge + |NO| + +bothedge + |NO| + +nonsticky + |NO| + + enable ^^^^^^ |NO| +mask +^^^^ +|NO| + haltenable ^^^^^^^^^^ |NO| @@ -402,14 +428,6 @@ haltmask ^^^^^^^^ |NO| -intr -^^^^ -|NO| - -mask -^^^^ -|NO| - sticky ^^^^^^ |NO| @@ -430,7 +448,10 @@ encode next ^^^^ -|NO| +|OK| + +If assigned, replaces the inferred ``hwif_in..next`` input with an explicit reference. + paritycheck ^^^^^^^^^^^ diff --git a/peakrdl/regblock/hwif/__init__.py b/peakrdl/regblock/hwif/__init__.py index 026e4de..a75fb37 100644 --- a/peakrdl/regblock/hwif/__init__.py +++ b/peakrdl/regblock/hwif/__init__.py @@ -132,8 +132,13 @@ class Hwif: raises an exception if obj is invalid """ if isinstance(obj, FieldNode): + next_value = obj.get_property('next') + if next_value is not None: + # 'next' property replaces the inferred input signal + return self.exp.dereferencer.get_value(next_value) + # Otherwise, use inferred path = get_indexed_path(self.top_node, obj) - return "hwif_in." + path + ".value" + return "hwif_in." + path + ".next" elif isinstance(obj, SignalNode): if obj.get_path() in self.out_of_hier_signals: return obj.inst_name diff --git a/peakrdl/regblock/hwif/generators.py b/peakrdl/regblock/hwif/generators.py index 902d547..37342e9 100644 --- a/peakrdl/regblock/hwif/generators.py +++ b/peakrdl/regblock/hwif/generators.py @@ -30,9 +30,10 @@ class InputStructGenerator_Hier(RDLFlatStructGenerator): type_name = self.get_typdef_name(node) self.push_struct(type_name, node.inst_name) - # Provide input to field's value if it is writable by hw - if node.is_hw_writable: - self.add_member("value", node.width) + # Provide input to field's next value if it is writable by hw, and it + # was not overridden by the 'next' property + if node.is_hw_writable and node.get_property('next') is None: + self.add_member("next", node.width) # Generate implied inputs for prop_name in ["we", "wel", "swwe", "swwel", "hwclr", "hwset"]: diff --git a/test/test_field_types/tb_template.sv b/test/test_field_types/tb_template.sv index e54f631..159c115 100644 --- a/test/test_field_types/tb_template.sv +++ b/test/test_field_types/tb_template.sv @@ -15,13 +15,13 @@ cpuif.assert_read('h0, 11); assert(cb.hwif_out.r1.f.value == 11); - cb.hwif_in.r1.f.value <= 9; + cb.hwif_in.r1.f.next <= 9; cpuif.assert_read('h0, 11); assert(cb.hwif_out.r1.f.value == 11); - cb.hwif_in.r1.f.value <= 12; + cb.hwif_in.r1.f.next <= 12; cb.hwif_in.r1.f.we <= 1; @cb; - cb.hwif_in.r1.f.value <= 0; + cb.hwif_in.r1.f.next <= 0; cb.hwif_in.r1.f.we <= 0; cpuif.assert_read('h0, 12); assert(cb.hwif_out.r1.f.value == 12); @@ -42,12 +42,12 @@ cpuif.write('h2, 31); cpuif.assert_read('h2, 31); - cb.hwif_in.r3.f.value <= 29; + cb.hwif_in.r3.f.next <= 29; cpuif.assert_read('h2, 31); - cb.hwif_in.r3.f.value <= 32; + cb.hwif_in.r3.f.next <= 32; cb.hwif_in.r3.f.wel <= 0; @cb; - cb.hwif_in.r3.f.value <= 0; + cb.hwif_in.r3.f.next <= 0; cb.hwif_in.r3.f.wel <= 1; cpuif.assert_read('h2, 32); @@ -66,13 +66,13 @@ cpuif.assert_read('h4, 50); assert(cb.hwif_out.r5.f.value == 50); - cb.hwif_in.r5.f.value <= 9; + cb.hwif_in.r5.f.next <= 9; cpuif.assert_read('h4, 50); assert(cb.hwif_out.r5.f.value == 50); - cb.hwif_in.r5.f.value <= 52; + cb.hwif_in.r5.f.next <= 52; cb.hwif_in.r5.f.we <= 1; @cb; - cb.hwif_in.r5.f.value <= 0; + cb.hwif_in.r5.f.next <= 0; cb.hwif_in.r5.f.we <= 0; cpuif.assert_read('h4, 52); assert(cb.hwif_out.r5.f.value == 52); @@ -88,7 +88,7 @@ // r7 - sw=r; hw=w; // Wire/Bus - hardware assigns value cpuif.assert_read('h6, 0); - cb.hwif_in.r7.f.value <= 70; + cb.hwif_in.r7.f.next <= 70; cpuif.assert_read('h6, 70); cpuif.write('h6, 71); cpuif.assert_read('h6, 70); @@ -108,13 +108,13 @@ cpuif.assert_read('h8, 0); assert(cb.hwif_out.r9.f.value == 91); - cb.hwif_in.r9.f.value <= 89; + cb.hwif_in.r9.f.next <= 89; cpuif.assert_read('h8, 0); assert(cb.hwif_out.r9.f.value == 91); - cb.hwif_in.r9.f.value <= 92; + cb.hwif_in.r9.f.next <= 92; cb.hwif_in.r9.f.we <= 1; @cb; - cb.hwif_in.r9.f.value <= 0; + cb.hwif_in.r9.f.next <= 0; cb.hwif_in.r9.f.we <= 0; cpuif.assert_read('h8, 0); assert(cb.hwif_out.r9.f.value == 92); diff --git a/test/test_hw_access/regblock.rdl b/test/test_hw_access/regblock.rdl index 365dccd..8784840 100644 --- a/test/test_hw_access/regblock.rdl +++ b/test/test_hw_access/regblock.rdl @@ -60,4 +60,14 @@ addrmap top { } f[7:0] = 0x44; } r4; r4.f->wel = hw_ctrl.hw_wel; + + reg { + signal {} f_next_value[8]; + signal {} f_we; + field { + sw=rw; hw=w; + next = f_next_value; + we = f_we; + } f[7:0] = 0x55; + } r5; }; diff --git a/test/test_hw_access/tb_template.sv b/test/test_hw_access/tb_template.sv index 4e190f8..d2cca1d 100644 --- a/test/test_hw_access/tb_template.sv +++ b/test/test_hw_access/tb_template.sv @@ -16,7 +16,7 @@ cpuif.write('h0, 'h00_F0); // test hwenable + we - cb.hwif_in.r1.f.value <= 'hAB; + cb.hwif_in.r1.f.next <= 'hAB; cb.hwif_in.r1.f.we <= '1; @cb; cb.hwif_in.r1.f.we <= '0; @@ -40,7 +40,7 @@ cpuif.write('h0, 'hF0_00); // test hwmask + we - cb.hwif_in.r2.f.value <= 'hAB; + cb.hwif_in.r2.f.next <= 'hAB; cb.hwif_in.r2.f.we <= '1; @cb; cb.hwif_in.r2.f.we <= '0; @@ -72,7 +72,7 @@ cpuif.assert_read('hC, 'h0F); // test hwenable + we via reference - cb.hwif_in.r3.f.value <= 'hAA; + cb.hwif_in.r3.f.next <= 'hAA; // toggle hwenable = 0F, we=1 cpuif.write('h0, 'h4_00_0F); cpuif.write('h0, 'h0_00_00); @@ -80,15 +80,26 @@ //--------------------------------- // test wel via reference - cb.hwif_in.r4.f.value <= 'hBB; + cb.hwif_in.r4.f.next <= 'hBB; // toggle wel cpuif.write('h0, 'h10_00_00); cpuif.write('h0, 'h00_00_00); cpuif.assert_read('h10, 'hBB); - cb.hwif_in.r4.f.value <= 'hCC; + cb.hwif_in.r4.f.next <= 'hCC; // toggle wel cpuif.write('h0, 'h10_00_00); cpuif.write('h0, 'h00_00_00); cpuif.assert_read('h10, 'hCC); + + //--------------------------------- + // test we and next via reference + cb.hwif_in.r5.f_next_value <= 'h54; + cpuif.assert_read('h14, 'h55); + cb.hwif_in.r5.f_next_value <= 'h56; + cb.hwif_in.r5.f_we <= '1; + @cb; + cb.hwif_in.r5.f_next_value <= '0; + cb.hwif_in.r5.f_we <= '0; + cpuif.assert_read('h14, 'h56); {% endblock %} diff --git a/test/test_swacc_swmod/tb_template.sv b/test/test_swacc_swmod/tb_template.sv index d5b926c..d7801c6 100644 --- a/test/test_swacc_swmod/tb_template.sv +++ b/test/test_swacc_swmod/tb_template.sv @@ -14,7 +14,7 @@ // Verify that hwif gets sampled at the same cycle as swacc strobe counter = 'h10; - cb.hwif_in.r1.f.value <= counter; + cb.hwif_in.r1.f.next <= counter; @cb; event_count = 0; fork @@ -22,7 +22,7 @@ ##0; forever begin counter++; - cb.hwif_in.r1.f.value <= counter; + cb.hwif_in.r1.f.next <= counter; @cb; if(cb.hwif_out.r1.f.swacc) begin latched_data = counter;