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 = {}
if alias:
owning_addrmap, full_path, path, path_underscored =\
_, _, path, path_underscored =\
Field.create_underscored_path_static(obj)
else:
owning_addrmap, full_path, path, path_underscored =\
@ -264,42 +264,46 @@ class Field(Component):
# Determine saturation values
if isinstance(self.obj.get_property('incrsaturate'), bool):
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
else:
incr_sat_value = False
overflow_value = 2**self.obj.width-1
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
if isinstance(self.obj.get_property('decrsaturate'), bool):
if self.obj.get_property('decrsaturate'):
decr_sat_value = 0
decr_sat_value = f"{self.obj.width}'d0"
underflow_value = decr_sat_value
else:
decr_sat_value = False
underflow_value = 0
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
# Determine threshold values
if isinstance(self.obj.get_property('incrthreshold'), bool):
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:
incr_thr_value = False
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 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:
decr_thr_value = False
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
# 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 "
"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
# 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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'incr_width': incr_width,
'decr_width': decr_width,
'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'],
{'path': self.path_underscored,
'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 "\
"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
def __process_reset_signal(reset_signal):

View File

@ -281,28 +281,28 @@ counter:
// might be tied to 0.
always_comb
begin
{path}_next{genvars} = {path}_q{genvars};
{path}_next{genvars} = {path}_q{genvars};
if ({path}_incr{genvars} && {path}_decr{genvars})
begin
if (!{path}_incr_sat{genvars} && !{path}_decr_sat{genvars})
begin
{path}_next{genvars} += {path}_incr_val{genvars};
{path}_next{genvars} -= {path}_decr_val{genvars};
{path}_next{genvars} += {{{incr_zero_pad}{path}_incr_val{genvars}}};
{path}_next{genvars} -= {{{decr_zero_pad}{path}_decr_val{genvars}}};
end
end
else if ({path}_incr{genvars})
begin
if (!{path}_incr_sat{genvars})
<<INDENT>>
{path}_next{genvars} += {path}_incr_val{genvars};
{path}_next{genvars} += {{{incr_zero_pad}{path}_incr_val{genvars}}};
<<UNINDENT>>
end
else if ({path}_decr{genvars})
begin
if (!{path}_decr_sat{genvars})
<<INDENT>>
{path}_next{genvars} += {path}_decr_val{genvars};
{path}_next{genvars} -= {{{decr_zero_pad}{path}_decr_val{genvars}}};
<<UNINDENT>>
end
end
@ -359,7 +359,7 @@ counter_incr_sat:
// Determine whether the counter is saturated
// The signal is tied if the counter is not saturating
// 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:
- name: '{path}_incr_sat'
signal_type: 'logic'
@ -375,7 +375,7 @@ counter_incr_sat_tied:
signal_type: 'logic'
counter_decr_sat:
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:
- name: '{path}_decr_sat'
signal_type: 'logic'
@ -391,13 +391,13 @@ counter_thr_comment:
// Define threshold signals (similar to overflow, but for a user specified value)
counter_incr_thr:
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:
- name: '{path}_incr_thr'
signal_type: 'logic'
counter_decr_thr:
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:
- name: '{path}_decr_thr'
signal_type: 'logic'
@ -405,7 +405,7 @@ counter_overflow:
rtl: |-
// 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};
signals:
- name: '{path}_overflow_int'
@ -417,8 +417,8 @@ counter_underflow:
rtl: |-
// 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{genvars} = {path}_incr{genvars} && {path}_underflow_int{genvars};
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}_decr{genvars} && {path}_underflow_int{genvars};
signals:
- name: '{path}_underflow_int'
signal_type: 'logic'