[go: up one dir, main page]

Skip to content

Commit

Permalink
Add flattened bus mode for AXI fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jvanstraten committed Sep 4, 2019
1 parent 29151b9 commit 389dd1b
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 44 deletions.
53 changes: 47 additions & 6 deletions tests/integration/test_axi_field.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""Primitive constant field tests."""
"""AXI field tests."""

from unittest import TestCase
from ..testbench import RegisterFileTestbench

class TestPrimitiveConstantFields(TestCase):
"""Primitive constant field tests"""
class TestAxiFields(TestCase):
"""AXI field tests"""

def test_fields(self):
"""test constant fields"""
def test_normal(self):
"""test normal AXI field"""
rft = RegisterFileTestbench({
'metadata': {'name': 'test'},
'fields': [
Expand Down Expand Up @@ -64,8 +64,49 @@ def write_cb(resp):
with self.assertRaisesRegex(ValueError, 'decode'):
objs.bus.write(0, 0)

def test_flattened(self):
"""test flattened AXI field"""
rft = RegisterFileTestbench({
'metadata': {'name': 'test'},
'fields': [
{
'address': '0x--',
'name': 'a',
'behavior': 'axi',
'bus-flatten': True,
'flatten': True
},
]})
self.assertEqual(rft.ports, (
'bus',
'f_a_araddr',
'f_a_arprot',
'f_a_arready',
'f_a_arvalid',
'f_a_awaddr',
'f_a_awprot',
'f_a_awready',
'f_a_awvalid',
'f_a_bready',
'f_a_bresp',
'f_a_bvalid',
'f_a_rdata',
'f_a_rready',
'f_a_rresp',
'f_a_rvalid',
'f_a_uirq',
'f_a_wdata',
'f_a_wready',
'f_a_wstrb',
'f_a_wvalid',
))
with rft as objs:
# This should probably be tested beyond just compiling. On the
# other hand, What Could Possibly Go Wrong? (TM)
pass

def test_errors(self):
"""test constant field config errors"""
"""test AXI field config errors"""
msg = ('AXI fields must be 32 or 64 bits wide')
with self.assertRaisesRegex(Exception, msg):
RegisterFileTestbench({
Expand Down
15 changes: 13 additions & 2 deletions vhdmmio/config/behavior/axi.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,29 @@ class Axi(Configurable):

@choice
def mode():
"""Configures the supported bus access modes."""
"""This key configures the supported bus access modes."""
yield 'read-write', 'both read and write accesses are supported.'
yield 'read-only', 'only read accesses are supported.'
yield 'write-only', 'only write accesses are supported.'

@choice
def interrupt_internal():
"""Configures driving an internal signal high when the
"""This key configures driving an internal signal high when the
`vhdmmio`-specific interrupt signal associated with the outgoing AXI4L
stream is asserted. This internal signal can then be tied to an
internal interrupt to propagate the flag."""
yield None, 'the feature is disabled.'
yield (re.compile(r'[a-zA-Z][a-zA-Z0-9_]*'),
'an internal signal with the given name is created (if '
'necessary) and driven by the incoming interrupt signal.')

@choice
def bus_flatten():
"""This key specifies whether records or flattened signals are desired
for the bus interface. Note that `flatten` (defined
[here](interfaceconfig.md#flatten)) should also be set to `yes` to make
this work."""
yield (False, 'the bus is not flattened; the records from '
'`vhdmmio_pkg.vhd` are used.')
yield (True, 'the bus is flattened; the standard AXI4-lite signal '
'names are used.')
26 changes: 24 additions & 2 deletions vhdmmio/vhdl/behavior/axi.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,30 @@ def generate(self):
tple['width'] = bus_width

# Generate I/Os.
tple['m2s'] = self.add_output('o', typ=Axi4Lite('m2s', bus_width))
tple['s2m'] = self.add_input('i', typ=Axi4Lite('s2m', bus_width))
if self.behavior.cfg.bus_flatten:
tple['awvalid'] = self.add_output('awvalid')
tple['awready'] = self.add_input('awready')
tple['awaddr'] = self.add_output('awaddr', 32)
tple['awprot'] = self.add_output('awprot', 3)
tple['wvalid'] = self.add_output('wvalid')
tple['wready'] = self.add_input('wready')
tple['wdata'] = self.add_output('wdata', bus_width)
tple['wstrb'] = self.add_output('wstrb', bus_width // 8)
tple['bvalid'] = self.add_input('bvalid')
tple['bready'] = self.add_output('bready')
tple['bresp'] = self.add_input('bresp', 2)
tple['arvalid'] = self.add_output('arvalid')
tple['arready'] = self.add_input('arready')
tple['araddr'] = self.add_output('araddr', 32)
tple['arprot'] = self.add_output('arprot', 3)
tple['rvalid'] = self.add_input('rvalid')
tple['rready'] = self.add_output('rready')
tple['rdata'] = self.add_input('rdata', bus_width)
tple['rresp'] = self.add_input('rresp', 2)
tple['uirq'] = self.add_input('uirq')
else:
tple['m2s'] = self.add_output('o', typ=Axi4Lite('m2s', bus_width))
tple['s2m'] = self.add_input('i', typ=Axi4Lite('s2m', bus_width))

# Generate internal state.
state_name = 'f_%s_r' % self.field_descriptor.name
Expand Down
132 changes: 98 additions & 34 deletions vhdmmio/vhdl/behavior/axi.template.vhd
Original file line number Diff line number Diff line change
@@ -1,33 +1,66 @@
|$block PRE
|@ Complete the AXI stream handshakes that occurred in the previous cycle for
|@ field $fd.name$.
|$if b.bus.can_write()
|if $s2m[i]$.aw.ready = '1' then
| $state[i]$.aw.valid := '0';
|end if;
|if $s2m[i]$.w.ready = '1' then
| $state[i]$.w.valid := '0';
|end if;
|if $state[i]$.b.valid = '0' then
| $state[i]$.b := $s2m[i]$.b;
|end if;
|$endif
|$if b.bus.can_read()
|if $s2m[i]$.ar.ready = '1' then
| $state[i]$.ar.valid := '0';
|end if;
|if $state[i]$.r.valid = '0' then
| $state[i]$.r := $s2m[i]$.r;
|end if;
|$if b.cfg.bus_flatten
|$if b.bus.can_write()
|if $awready$ = '1' then
| $state[i]$.aw.valid := '0';
|end if;
|if $wready$ = '1' then
| $state[i]$.w.valid := '0';
|end if;
|if $state[i]$.b.valid = '0' then
| $state[i]$.b.valid := $bvalid$;
| $state[i]$.b.resp := $bresp$;
|end if;
|$endif
|$if b.bus.can_read()
|if $arready$ = '1' then
| $state[i]$.ar.valid := '0';
|end if;
|if $state[i]$.r.valid = '0' then
| $state[i]$.r.valid := $rvalid$;
| $state[i]$.r.data := $rdata$;
| $state[i]$.r.resp := $rresp$;
|end if;
|$endif
|$else
|$if b.bus.can_write()
|if $s2m[i]$.aw.ready = '1' then
| $state[i]$.aw.valid := '0';
|end if;
|if $s2m[i]$.w.ready = '1' then
| $state[i]$.w.valid := '0';
|end if;
|if $state[i]$.b.valid = '0' then
| $state[i]$.b := $s2m[i]$.b;
|end if;
|$endif
|$if b.bus.can_read()
|if $s2m[i]$.ar.ready = '1' then
| $state[i]$.ar.valid := '0';
|end if;
|if $state[i]$.r.valid = '0' then
| $state[i]$.r := $s2m[i]$.r;
|end if;
|$endif
|$endif
|
|$if b.interrupt_internal is not None
|@ Connect the incoming interrupt signal for field $fd.name$
|@ to the associated internal signal.
|$if b.interrupt_internal.width is None
|$b.interrupt_internal.drive_name$ := $s2m[i]$.u.irq;
|$if b.cfg.bus_flatten
|$b.interrupt_internal.drive_name$ := $uirq$;
|$else
|$b.interrupt_internal.drive_name$ := $s2m[i]$.u.irq;
|$endif
|$else
|$b.interrupt_internal.drive_name$($i$) := $s2m[i]$.u.irq;
|$if b.cfg.bus_flatten
|$b.interrupt_internal.drive_name$($i$) := $uirq$;
|$else
|$b.interrupt_internal.drive_name$($i$) := $s2m[i]$.u.irq;
|$endif
|$endif
|$endif
|$endblock
Expand Down Expand Up @@ -105,20 +138,51 @@
|end if;
|
|@ Assign output ports for field $fd.name$.
|$if b.bus.can_write()
|$m2s[i]$.aw <= $state[i]$.aw;
|$m2s[i]$.w <= $state[i]$.w;
|$m2s[i]$.b.ready <= not $state[i]$.b.valid;
|$else
|$m2s[i]$.aw <= AXI4LA_RESET;
|$m2s[i]$.w <= AXI4LW$width$_RESET;
|$m2s[i]$.b <= AXI4LH_RESET;
|$endif
|$if b.bus.can_read()
|$m2s[i]$.ar <= $state[i]$.ar;
|$m2s[i]$.r.ready <= not $state[i]$.r.valid;
|$if b.cfg.bus_flatten
|$if b.bus.can_write()
|$awvalid$ <= $state[i]$.aw.valid;
|$awaddr$ <= $state[i]$.aw.addr;
|$awprot$ <= $state[i]$.aw.prot;
|$wvalid$ <= $state[i]$.w.valid;
|$wdata$ <= $state[i]$.w.data;
|$wstrb$ <= $state[i]$.w.strb;
|$bready$ <= not $state[i]$.b.valid;
|$else
|$awvalid$ <= '0';
|$awaddr$ <= X"00000000";
|$awprot$ <= "000";
|$wvalid$ <= '0';
|$wdata$ <= X"$'0'*(width//4)$";
|$wstrb$ <= "$'0'*(width//8)$";
|$bready$ <= '1';
|$endif
|$if b.bus.can_read()
|$arvalid$ <= $state[i]$.ar.valid;
|$araddr$ <= $state[i]$.ar.addr;
|$arprot$ <= $state[i]$.ar.prot;
|$rready$ <= not $state[i]$.r.valid;
|$else
|$arvalid$ <= '0';
|$araddr$ <= X"00000000";
|$arprot$ <= "000";
|$rready$ <= '1';
|$endif
|$else
|$m2s[i]$.ar <= AXI4LA_RESET;
|$m2s[i]$.r <= AXI4LH_RESET;
|$if b.bus.can_write()
|$m2s[i]$.aw <= $state[i]$.aw;
|$m2s[i]$.w <= $state[i]$.w;
|$m2s[i]$.b.ready <= not $state[i]$.b.valid;
|$else
|$m2s[i]$.aw <= AXI4LA_RESET;
|$m2s[i]$.w <= AXI4LW$width$_RESET;
|$m2s[i]$.b <= AXI4LH_RESET;
|$endif
|$if b.bus.can_read()
|$m2s[i]$.ar <= $state[i]$.ar;
|$m2s[i]$.r.ready <= not $state[i]$.r.valid;
|$else
|$m2s[i]$.ar <= AXI4LA_RESET;
|$m2s[i]$.r <= AXI4LH_RESET;
|$endif
|$endif
|$endblock

0 comments on commit 389dd1b

Please sign in to comment.