Skip to content

Commit 44cda50

Browse files
committed
fix read-buffered signed/fixedpoint fields
1 parent 9e067e0 commit 44cda50

File tree

5 files changed

+89
-24
lines changed

5 files changed

+89
-24
lines changed

src/peakrdl_regblock_vhdl/field_logic/hw_write.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import TYPE_CHECKING, List
22

33
from .bases import NextStateConditional, NextStateUnconditional
4+
from ..utils import get_vhdl_type
45

56
if TYPE_CHECKING:
67
from systemrdl.node import FieldNode
@@ -23,7 +24,12 @@ def is_match(self, field: 'FieldNode') -> bool:
2324
def get_assignments(self, field: 'FieldNode') -> List[str]:
2425
hwmask = field.get_property('hwmask')
2526
hwenable = field.get_property('hwenable')
26-
I = str(self.exp.hwif.get_input_identifier(field))
27+
I = self.exp.hwif.get_input_identifier(field)
28+
vhdl_type = get_vhdl_type(field)
29+
if field.width == 1 and vhdl_type != "std_logic":
30+
I = f"to_std_logic({I})"
31+
if field.width > 1 and vhdl_type != "std_logic_vector":
32+
I = f"to_std_logic_vector({I})"
2733
R = self.exp.field_logic.get_storage_identifier(field)
2834
if hwmask is not None:
2935
M = self.exp.dereferencer.get_value(hwmask)
@@ -32,7 +38,7 @@ def get_assignments(self, field: 'FieldNode') -> List[str]:
3238
E = self.exp.dereferencer.get_value(hwenable)
3339
next_val = f"({I} and {E}) or ({R} and not {E})"
3440
else:
35-
next_val = I
41+
next_val = str(I)
3642

3743
return [
3844
f"next_c := {next_val};",
@@ -44,7 +50,12 @@ class _QualifiedWrite(NextStateConditional):
4450
def get_assignments(self, field: 'FieldNode') -> List[str]:
4551
hwmask = field.get_property('hwmask')
4652
hwenable = field.get_property('hwenable')
47-
I = str(self.exp.hwif.get_input_identifier(field))
53+
I = self.exp.hwif.get_input_identifier(field)
54+
vhdl_type = get_vhdl_type(field)
55+
if field.width == 1 and vhdl_type != "std_logic":
56+
I = f"to_std_logic({I})"
57+
if field.width > 1 and vhdl_type != "std_logic_vector":
58+
I = f"to_std_logic_vector({I})"
4859
R = self.exp.field_logic.get_storage_identifier(field)
4960
if hwmask is not None:
5061
M = self.exp.dereferencer.get_value(hwmask)
@@ -53,7 +64,7 @@ def get_assignments(self, field: 'FieldNode') -> List[str]:
5364
E = self.exp.dereferencer.get_value(hwenable)
5465
next_val = f"({I} and {E}) or ({R} and not {E})"
5566
else:
56-
next_val = I
67+
next_val = str(I)
5768

5869
return [
5970
f"next_c := {next_val};",

src/peakrdl_regblock_vhdl/read_buffering/implementation_generator.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from systemrdl.node import RegNode
55

66
from ..forloop_generator import RDLForLoopGenerator
7+
from ..utils import do_bitswap, get_vhdl_type
8+
from ..vhdl_int import VhdlInt
79

810
if TYPE_CHECKING:
911
from . import ReadBuffering
@@ -42,13 +44,23 @@ def get_assignments(self, node: RegNode) -> str:
4244
s.append(f"{data}({field.low-1} downto {bidx}) <= (others => '0');")
4345

4446
value = self.exp.dereferencer.get_value(field)
47+
if self.exp.hwif.has_value_input(field) and not field.implements_storage:
48+
# the value is a hwif input, which may not be a std_logic_vector, convert it
49+
if get_vhdl_type(field) != "std_logic_vector":
50+
value = f"to_std_logic_vector({value})"
51+
elif field.implements_storage:
52+
# the value is in field storage, which may be a std_logic
53+
if field.width == 1:
54+
value = f"to_std_logic_vector({value})"
55+
elif isinstance(value, VhdlInt):
56+
# the value is a constant, ensure it's not reduced to a std_logic
57+
value.allow_std_logic = False
58+
4559
if field.msb < field.lsb:
4660
# Field gets bitswapped since it is in [low:high] orientation
47-
value = f"bitswap({value})"
48-
if field.high == field.low:
49-
s.append(f"{data}({field.high}) <= {value};")
50-
else:
51-
s.append(f"{data}({field.high} downto {field.low}) <= {value};")
61+
value = do_bitswap(value)
62+
63+
s.append(f"{data}({field.high} downto {field.low}) <= {value};")
5264

5365
bidx = field.high + 1
5466

src/peakrdl_regblock_vhdl/readback/generators.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,19 @@ def process_buffered_reg_with_bypass(self, node: RegNode, regwidth: int, accessw
224224
# insert padding before
225225
self.add_content(f"readback_array({self.current_offset_str})({field.low - 1} downto {bidx}) <= (others => '0');")
226226

227+
value = self.exp.dereferencer.get_value(field)
228+
if self.exp.hwif.has_value_input(field) and not field.implements_storage:
229+
# the value is a hwif input, which may not be a std_logic_vector, convert it
230+
if get_vhdl_type(field) != "std_logic_vector":
231+
value = f"to_std_logic_vector({value})"
232+
elif field.implements_storage:
233+
# the value is in field storage, which may be a std_logic
234+
if field.width == 1:
235+
value = f"to_std_logic_vector({value})"
236+
elif isinstance(value, VhdlInt):
237+
# the value is a constant, ensure it's not reduced to a std_logic
238+
value.allow_std_logic = False
239+
227240
if field.high >= accesswidth:
228241
# field gets truncated
229242
r_low = field.low
@@ -237,22 +250,19 @@ def process_buffered_reg_with_bypass(self, node: RegNode, regwidth: int, accessw
237250
f_low = field.width - 1 - f_low
238251
f_high = field.width - 1 - f_high
239252
f_low, f_high = f_high, f_low
240-
value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low, reduce=False))
253+
value = do_slice(value, f_high, f_low, reduce=False)
254+
value = do_bitswap(value)
241255
else:
242-
value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low, reduce=False)
256+
value = do_slice(value, f_high, f_low, reduce=False)
243257

244258
self.add_content(f"readback_array({self.current_offset_str})({r_high} downto {r_low}) <= {value} when {rd_strb} else (others => '0');")
245259
bidx = accesswidth
246260
else:
247261
# field fits in subword
248-
value = self.exp.dereferencer.get_value(field)
249262
if field.msb < field.lsb:
250263
# Field gets bitswapped since it is in [low:high] orientation
251264
value = do_bitswap(value)
252265

253-
if field.width == 1:
254-
# convert from std_logic to std_logic_vector
255-
value = f"to_std_logic_vector({value})"
256266
self.add_content(f"readback_array({self.current_offset_str})({field.high} downto {field.low}) <= {value} when {rd_strb} else (others => '0');")
257267
bidx = field.high + 1
258268

tests/test_read_buffer/regblock.rdl

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,6 @@ addrmap top {
129129
//--------------------------------------------------------------------------
130130

131131
regfile {
132-
reg {
133-
field {} rst = 0;
134-
} reset;
135-
136132
reg {
137133
regwidth = 128;
138134
buffer_reads;
@@ -144,4 +140,29 @@ addrmap top {
144140
field {} f4[1];
145141
} fields;
146142
} regfile_array[2];
143+
144+
//--------------------------------------------------------------------------
145+
// signed/fixed-point
146+
//--------------------------------------------------------------------------
147+
148+
reg {
149+
regwidth = 32;
150+
buffer_reads;
151+
default sw = r;
152+
default hw = w;
153+
154+
// ensure the various VHDL types (signed, ufixed, etc.) work with
155+
// multi- and single-bit fields, as well as different field access types
156+
157+
// first word is treated separately to implement a read pass-through
158+
field {is_signed; sw=rw; } f1[1];
159+
field {is_signed; } f2[1];
160+
field {is_signed; } f3[6];
161+
162+
field {fracwidth=1; sw=rw; we; } f4[8] = 111;
163+
field {fracwidth=1; hw=r; } f5[8] = 222;
164+
field {is_signed; } f6[1];
165+
field {fracwidth=1; sw=rw; wel; } f7[1] = 0;
166+
field {fracwidth=1; hw=r; } f8[1] = 1;
167+
} reg_fp;
147168
};

tests/test_write_buffer/regblock.rdl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,30 @@ addrmap top {
117117
//--------------------------------------------------------------------------
118118

119119
regfile {
120-
reg {
121-
field {} rst = 0;
122-
} reset;
123-
124120
reg {
125121
regwidth = 128;
126122
buffer_writes;
127-
default sw = w;
123+
default sw = rw;
128124
default hw = r;
129125
field {} f1[16] = 0;
130126
field {} f2[32] = 0;
131127
field {} f3[64] = 0;
132128
field {} f4[1] = 0;
133129
} fields;
134130
} regfile_array[2];
131+
132+
//--------------------------------------------------------------------------
133+
// signed/fixed-point
134+
//--------------------------------------------------------------------------
135+
136+
reg {
137+
regwidth = 32;
138+
buffer_writes;
139+
default sw = rw;
140+
default hw = r;
141+
field {is_signed; } f1[8] = 111;
142+
field {fracwidth=1; } f2[8] = 222;
143+
field {is_signed; } f3[1] = 0;
144+
field {fracwidth=1; } f4[1] = 1;
145+
} reg_fp;
135146
};

0 commit comments

Comments
 (0)