Fix bug with dynamic saturate values and fix Lint warnings

Two categories Lint warnings occured:
    - Width mismatches, since integers are 32-bit wide according to the
      SV LRM.
    - Constant saturate values, because values could get larger than
      32-bit and smaller than 0.
This commit is contained in:
Dennis Potter 2021-11-06 17:36:45 -07:00
parent 5d3fd14144
commit 8fbf800c4f
Signed by: Dennis
GPG Key ID: 186A8AD440942BAF
2 changed files with 65 additions and 33 deletions

View File

@ -87,7 +87,7 @@ class Field(Component):
access_rtl = {} access_rtl = {}
if alias: if alias:
owning_addrmap, full_path, path, path_underscored =\ _, _, path, path_underscored =\
Field.create_underscored_path_static(obj) Field.create_underscored_path_static(obj)
else: else:
owning_addrmap, full_path, path, path_underscored =\ owning_addrmap, full_path, path, path_underscored =\
@ -264,42 +264,46 @@ class Field(Component):
# Determine saturation values # Determine saturation values
if isinstance(self.obj.get_property('incrsaturate'), bool): if isinstance(self.obj.get_property('incrsaturate'), bool):
if self.obj.get_property('incrsaturate'): if self.obj.get_property('incrsaturate'):
incr_sat_value = 2**self.obj.width-1 incr_sat_value = f"{self.obj.width}'d{2**self.obj.width-1}"
overflow_value = incr_sat_value overflow_value = incr_sat_value
else: else:
incr_sat_value = False incr_sat_value = False
overflow_value = 2**self.obj.width-1 overflow_value = 2**self.obj.width-1
else: else:
incr_sat_value = self.obj.get_property('incrsaturate') incr_sat_value = self.get_signal_name(
self.obj.get_property('incrsaturate'))
overflow_value = incr_sat_value overflow_value = incr_sat_value
if isinstance(self.obj.get_property('decrsaturate'), bool): if isinstance(self.obj.get_property('decrsaturate'), bool):
if self.obj.get_property('decrsaturate'): if self.obj.get_property('decrsaturate'):
decr_sat_value = 0 decr_sat_value = f"{self.obj.width}'d0"
underflow_value = decr_sat_value underflow_value = decr_sat_value
else: else:
decr_sat_value = False decr_sat_value = False
underflow_value = 0 underflow_value = 0
else: else:
decr_sat_value = self.obj.get_property('decrsaturate') decr_sat_value = self.get_signal_name(
self.obj.get_property('decrsaturate'))
underflow_value = decr_sat_value underflow_value = decr_sat_value
# Determine threshold values # Determine threshold values
if isinstance(self.obj.get_property('incrthreshold'), bool): if isinstance(self.obj.get_property('incrthreshold'), bool):
if self.obj.get_property('incrthreshold'): if self.obj.get_property('incrthreshold'):
incr_thr_value = 2**self.obj.width-1 incr_thr_value = f"{self.obj.width}'d{2**self.obj.width-1}"
else: else:
incr_thr_value = False incr_thr_value = False
else: else:
incr_thr_value = self.obj.get_property('incrthreshold') incr_thr_value = self.get_signal_name(
self.obj.get_property('incrthreshold'))
if isinstance(self.obj.get_property('decrthreshold'), bool): if isinstance(self.obj.get_property('decrthreshold'), bool):
if self.obj.get_property('decrthreshold'): if self.obj.get_property('decrthreshold'):
decr_thr_value = 2**self.obj.width-1 decr_thr_value = f"{self.obj.width}'d{2**self.obj.width-1}"
else: else:
decr_thr_value = False decr_thr_value = False
else: else:
decr_thr_value = self.obj.get_property('decrthreshold') decr_thr_value = self.get_signal_name(
self.obj.get_property('decrthreshold'))
# Determine with what value the counter is incremented # Determine with what value the counter is incremented
# According to the spec, the incrvalue/decrvalue default to '1' # According to the spec, the incrvalue/decrvalue default to '1'
@ -428,6 +432,20 @@ class Field(Component):
"defined. This is not legal and the decrwidth property " "defined. This is not legal and the decrwidth property "
"will be ignored!") "will be ignored!")
# Calculate the number of bits that need to be padded with 0s
if remaining_width := self.obj.width - incr_width:
incr_zero_pad = f"{remaining_width}'b0, "
incr_sat_zero_pad = f"{remaining_width+1}'b0, "
else:
incr_zero_pad = ""
incr_sat_zero_pad = "1'b0"
if remaining_width := self.obj.width - decr_width:
decr_zero_pad = f"{remaining_width}'b0, "
decr_sat_zero_pad = f"{remaining_width+1}'b0, "
else:
decr_zero_pad = ''
decr_sat_zero_pad = "1'b0"
# If no input is defined for the decrement value, define # If no input is defined for the decrement value, define
# an internal signal. It is possible that this is tied to 0. # an internal signal. It is possible that this is tied to 0.
@ -551,9 +569,10 @@ class Field(Component):
Field.templ_dict['counter_incr_sat'], Field.templ_dict['counter_incr_sat'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'sat_value': incr_sat_value, 'sat_value': incr_sat_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': decr_sat_zero_pad,
} }
) )
) )
@ -573,9 +592,10 @@ class Field(Component):
Field.templ_dict['counter_decr_sat'], Field.templ_dict['counter_decr_sat'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'sat_value': decr_sat_value, 'sat_value': decr_sat_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': decr_sat_zero_pad,
} }
) )
) )
@ -590,9 +610,10 @@ class Field(Component):
Field.templ_dict['counter_incr_thr'], Field.templ_dict['counter_incr_thr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'thr_value': incr_thr_value, 'thr_value': incr_thr_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': incr_sat_zero_pad,
} }
) )
) )
@ -603,9 +624,10 @@ class Field(Component):
Field.templ_dict['counter_decr_thr'], Field.templ_dict['counter_decr_thr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'thr_value': decr_thr_value, 'thr_value': decr_thr_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': decr_sat_zero_pad,
} }
) )
) )
@ -617,9 +639,10 @@ class Field(Component):
Field.templ_dict['counter_overflow'], Field.templ_dict['counter_overflow'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'overflow_value': overflow_value, 'overflow_value': overflow_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': decr_sat_zero_pad,
} }
) )
) )
@ -630,9 +653,10 @@ class Field(Component):
Field.templ_dict['counter_underflow'], Field.templ_dict['counter_underflow'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'underflow_value': underflow_value, 'underflow_value': underflow_value,
'width_plus_1': self.obj.width + 1,
'incr_sat_zero_pad': incr_sat_zero_pad,
'decr_sat_zero_pad': decr_sat_zero_pad,
} }
) )
) )
@ -643,6 +667,8 @@ class Field(Component):
Field.templ_dict['counter'], Field.templ_dict['counter'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'incr_zero_pad': incr_zero_pad,
'decr_zero_pad': decr_zero_pad,
} }
) )
) )
@ -1467,6 +1493,12 @@ class Field(Component):
"field. Note that explicit connecting this "\ "field. Note that explicit connecting this "\
"is not required if a field_reset was defined.") "is not required if a field_reset was defined.")
if self.obj.get_property('counter') \
and self.obj.get_property("reset") is None:
self.logger.warning("Field is a counter but has no reset. "\
"This should probably be fixed since this "\
"will result in undefined behavior in simulations.")
@staticmethod @staticmethod
def __process_reset_signal(reset_signal): def __process_reset_signal(reset_signal):

View File

@ -281,28 +281,28 @@ counter:
// might be tied to 0. // might be tied to 0.
always_comb always_comb
begin begin
{path}_next{genvars} = {path}_q{genvars}; {path}_next{genvars} = {path}_q{genvars};
if ({path}_incr{genvars} && {path}_decr{genvars}) if ({path}_incr{genvars} && {path}_decr{genvars})
begin begin
if (!{path}_incr_sat{genvars} && !{path}_decr_sat{genvars}) if (!{path}_incr_sat{genvars} && !{path}_decr_sat{genvars})
begin begin
{path}_next{genvars} += {path}_incr_val{genvars}; {path}_next{genvars} += {{{incr_zero_pad}{path}_incr_val{genvars}}};
{path}_next{genvars} -= {path}_decr_val{genvars}; {path}_next{genvars} -= {{{decr_zero_pad}{path}_decr_val{genvars}}};
end end
end end
else if ({path}_incr{genvars}) else if ({path}_incr{genvars})
begin begin
if (!{path}_incr_sat{genvars}) if (!{path}_incr_sat{genvars})
<<INDENT>> <<INDENT>>
{path}_next{genvars} += {path}_incr_val{genvars}; {path}_next{genvars} += {{{incr_zero_pad}{path}_incr_val{genvars}}};
<<UNINDENT>> <<UNINDENT>>
end end
else if ({path}_decr{genvars}) else if ({path}_decr{genvars})
begin begin
if (!{path}_decr_sat{genvars}) if (!{path}_decr_sat{genvars})
<<INDENT>> <<INDENT>>
{path}_next{genvars} += {path}_decr_val{genvars}; {path}_next{genvars} -= {{{decr_zero_pad}{path}_decr_val{genvars}}};
<<UNINDENT>> <<UNINDENT>>
end end
end end
@ -359,7 +359,7 @@ counter_incr_sat:
// Determine whether the counter is saturated // Determine whether the counter is saturated
// The signal is tied if the counter is not saturating // The signal is tied if the counter is not saturating
// in the respective direction // in the respective direction
assign {path}_incr_sat{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {sat_value}; assign {path}_incr_sat{genvars} = {{1'b0, {path}_q{genvars}}} + ({{{width_plus_1}{{{path}_incr}}}} & {{{incr_sat_zero_pad}{path}_incr_val}}) - ({{{width_plus_1}{{{path}_decr}}}} & {{{decr_sat_zero_pad}{path}_decr_val}}) > {{1'b0, {sat_value}}};
signals: signals:
- name: '{path}_incr_sat' - name: '{path}_incr_sat'
signal_type: 'logic' signal_type: 'logic'
@ -375,7 +375,7 @@ counter_incr_sat_tied:
signal_type: 'logic' signal_type: 'logic'
counter_decr_sat: counter_decr_sat:
rtl: |- rtl: |-
assign {path}_decr_sat{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {sat_value}; assign {path}_decr_sat{genvars} = {{1'b0, {path}_q{genvars}}} + ({{{width_plus_1}{{{path}_incr}}}} & {{{incr_sat_zero_pad}{path}_incr_val}}) < {{1'b0, {sat_value}}} + ({{{width_plus_1}{{{path}_decr}}}} & {{{decr_sat_zero_pad}{path}_decr_val}});
signals: signals:
- name: '{path}_decr_sat' - name: '{path}_decr_sat'
signal_type: 'logic' signal_type: 'logic'
@ -391,13 +391,13 @@ counter_thr_comment:
// Define threshold signals (similar to overflow, but for a user specified value) // Define threshold signals (similar to overflow, but for a user specified value)
counter_incr_thr: counter_incr_thr:
rtl: |- rtl: |-
assign {path}_incr_thr{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {thr_value}; assign {path}_incr_thr{genvars} = {{1'b0, {path}_q{genvars}}} + ({{{width_plus_1}{{{path}_incr}}}} & {{{incr_sat_zero_pad}{path}_incr_val}}) - ({{{width_plus_1}{{{path}_decr}}}} & {{{decr_sat_zero_pad}{path}_decr_val}}) >= {{1'b0, {thr_value}}};
output_ports: output_ports:
- name: '{path}_incr_thr' - name: '{path}_incr_thr'
signal_type: 'logic' signal_type: 'logic'
counter_decr_thr: counter_decr_thr:
rtl: |- rtl: |-
assign {path}_decr_thr{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {thr_value}; assign {path}_decr_thr{genvars} = {{1'b0, {path}_q{genvars}}} + ({{{width_plus_1}{{{path}_incr}}}} & {{{incr_sat_zero_pad}{path}_incr_val}}) <= {{1'b0, {sat_value}}} + ({{{width_plus_1}{{{path}_decr}}}} & {{{decr_sat_zero_pad}{path}_decr_val}}) ;
output_ports: output_ports:
- name: '{path}_decr_thr' - name: '{path}_decr_thr'
signal_type: 'logic' signal_type: 'logic'
@ -405,7 +405,7 @@ counter_overflow:
rtl: |- rtl: |-
// Logic to determine occurance of an overflow // Logic to determine occurance of an overflow
assign {path}_overflow_int{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {overflow_value}; assign {path}_overflow_int{genvars} = {{1'b0, {path}_q{genvars}}} + ({{{width_plus_1}{{{path}_incr}}}} & {{{incr_sat_zero_pad}{path}_incr_val}}) - ({{{width_plus_1}{{{path}_decr}}}} & {{{decr_sat_zero_pad}{path}_decr_val}}) > {{1'b0, {overflow_value}}};
assign {path}_overflow{genvars} = {path}_incr{genvars} && {path}_overflow_int{genvars}; assign {path}_overflow{genvars} = {path}_incr{genvars} && {path}_overflow_int{genvars};
signals: signals:
- name: '{path}_overflow_int' - name: '{path}_overflow_int'
@ -417,8 +417,8 @@ counter_underflow:
rtl: |- rtl: |-
// Logic to determine occurance of an underflow // Logic to determine occurance of an underflow
assign {path}_underflow_int{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) - ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) > {underflow_value}; assign {path}_underflow_int{genvars} = {path}_q{genvars} + ({{{incr_width}{{{path}_incr}}}} & {path}_incr_val) > {underflow_value} + ({{{decr_width}{{{path}_decr}}}} & {path}_decr_val) ;
assign {path}_underflow{genvars} = {path}_incr{genvars} && {path}_underflow_int{genvars}; assign {path}_underflow{genvars} = {path}_decr{genvars} && {path}_underflow_int{genvars};
signals: signals:
- name: '{path}_underflow_int' - name: '{path}_underflow_int'
signal_type: 'logic' signal_type: 'logic'