rust_hdl_hls/
router.rs

1use crate::bus::{SoCBusController, SoCBusResponder};
2use crate::HLSNamedPorts;
3use rust_hdl_core::prelude::*;
4use rust_hdl_widgets::prelude::*;
5
6// A router allows you to connect multiple bridges to a single master
7// Each bridge is assigned a base address (they must be non-overlapping).
8// The master then sees each port on the bridge mapped to the offset
9// of it's base address.  Note that you can stack routers if needed.
10
11#[derive(LogicBlock)]
12pub struct Router<const D: usize, const A: usize, const N: usize> {
13    pub upstream: SoCBusResponder<D, A>,
14    pub nodes: [SoCBusController<D, A>; N],
15    node_start_address: [Constant<Bits<A>>; N],
16    node_end_address: [Constant<Bits<A>>; N],
17    active: DFF<Bits<8>>,
18    virtual_address: DFF<Bits<A>>,
19    address_strobe_delay: DFF<Bit>,
20    clock: Signal<Local, Clock>,
21    _address_map: Vec<String>,
22}
23
24impl<const D: usize, const A: usize, const N: usize> HLSNamedPorts for Router<D, A, N> {
25    fn ports(&self) -> Vec<String> {
26        self._address_map.clone()
27    }
28}
29
30impl<const D: usize, const A: usize, const N: usize> Router<D, A, N> {
31    pub fn new(downstream_names: [&str; N], downstream_devices: [&dyn HLSNamedPorts; N]) -> Self {
32        let address_count = downstream_devices
33            .iter()
34            .map(|x| x.ports().len())
35            .collect::<Vec<_>>();
36        let mut _address_map = vec![];
37        for ndx in 0..N {
38            let prefix = downstream_names[ndx];
39            _address_map.extend(
40                downstream_devices[ndx]
41                    .ports()
42                    .iter()
43                    .map(|x| format!("{}_{}", prefix, x)),
44            );
45        }
46        let zero = Constant::<Bits<A>>::new(0.into());
47        let mut node_start_address: [Constant<Bits<A>>; N] = array_init::array_init(|_| zero);
48        let mut node_end_address: [Constant<Bits<A>>; N] = array_init::array_init(|_| zero);
49        let mut offset = 0;
50        for (ndx, count) in address_count.iter().enumerate() {
51            assert_ne!(*count, 0);
52            node_start_address[ndx] = Constant::<Bits<A>>::new(offset.into());
53            node_end_address[ndx] =
54                Constant::<Bits<A>>::new((offset + (*count as LiteralType)).into());
55            offset = offset + (*count) as LiteralType;
56        }
57        Self {
58            upstream: Default::default(),
59            nodes: array_init::array_init(|_| Default::default()),
60            node_start_address,
61            node_end_address,
62            active: Default::default(),
63            virtual_address: Default::default(),
64            address_strobe_delay: Default::default(),
65            clock: Default::default(),
66            _address_map,
67        }
68    }
69}
70
71impl<const D: usize, const A: usize, const N: usize> Logic for Router<D, A, N> {
72    #[hdl_gen]
73    fn update(&mut self) {
74        self.clock.next = self.upstream.clock.val();
75        self.upstream.ready.next = false;
76        self.upstream.to_controller.next = 0.into();
77        dff_setup!(self, clock, active, virtual_address, address_strobe_delay);
78        // Delay the address strobe by 1 clock cycle to allow the virtual address
79        // calculation to be pipelined.
80        self.address_strobe_delay.d.next = self.upstream.address_strobe.val();
81        for i in 0..N {
82            self.nodes[i].from_controller.next = 0.into();
83            self.nodes[i].address.next = 0.into();
84            self.nodes[i].address_strobe.next = false;
85            self.nodes[i].strobe.next = false;
86            self.nodes[i].clock.next = self.clock.val();
87            if (self.upstream.address.val() >= self.node_start_address[i].val())
88                & (self.upstream.address.val() < self.node_end_address[i].val())
89                & self.upstream.address_strobe.val()
90            {
91                self.active.d.next = i.to_bits();
92                self.virtual_address.d.next =
93                    self.upstream.address.val() - self.node_start_address[i].val();
94            }
95            if self.active.q.val().index() == i {
96                self.nodes[i].from_controller.next = self.upstream.from_controller.val();
97                self.nodes[i].address.next = self.virtual_address.q.val();
98                self.nodes[i].strobe.next = self.upstream.strobe.val();
99                self.upstream.to_controller.next = self.nodes[i].to_controller.val();
100                self.upstream.ready.next = self.nodes[i].ready.val();
101                self.nodes[i].address_strobe.next = self.address_strobe_delay.q.val();
102            }
103        }
104        if self.upstream.address_strobe.val() {
105            self.upstream.ready.next = false;
106        }
107    }
108}
109
110#[test]
111fn test_router_is_synthesizable() {
112    use crate::bridge::Bridge;
113    let bridge1 = Bridge::<16, 8, 4>::new(["Top", "Left", "Right", "Bottom"]);
114    let bridge2 = Bridge::<16, 8, 2>::new(["Red", "Blue"]);
115    let bridge3 =
116        Bridge::<16, 8, 6>::new(["Club", "Spades", "Diamond", "Heart", "Joker", "Instruction"]);
117    let mut router =
118        Router::<16, 8, 3>::new(["Sides", "Colors", "Faces"], [&bridge1, &bridge2, &bridge3]);
119    router.connect_all();
120    let vlog = generate_verilog(&router);
121    yosys_validate("router", &vlog).unwrap();
122}