1use crate::bus::{SoCBusController, SoCBusResponder};
2use crate::HLSNamedPorts;
3use rust_hdl_core::prelude::*;
4use rust_hdl_widgets::prelude::*;
5
6#[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 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}