rust_hdl_hls/
router_rom.rs1use crate::bus::{SoCBusController, SoCBusResponder};
2use crate::HLSNamedPorts;
3use rust_hdl_core::prelude::*;
4use rust_hdl_widgets::prelude::*;
5use std::collections::BTreeMap;
6
7#[derive(LogicBlock)]
13pub struct RouterROM<const D: usize, const A: usize, const N: usize> {
14 pub upstream: SoCBusResponder<D, A>,
15 pub nodes: [SoCBusController<D, A>; N],
16 node_decode: ROM<Bits<8>, A>,
17 virtual_decode: ROM<Bits<A>, A>,
18 active: DFF<Bits<8>>,
19 virtual_address: DFF<Bits<A>>,
20 address_strobe_delay: DFF<Bit>,
21 clock: Signal<Local, Clock>,
22 _address_map: Vec<String>,
23}
24
25impl<const D: usize, const A: usize, const N: usize> HLSNamedPorts for RouterROM<D, A, N> {
26 fn ports(&self) -> Vec<String> {
27 self._address_map.clone()
28 }
29}
30
31impl<const D: usize, const A: usize, const N: usize> RouterROM<D, A, N> {
32 pub fn new(downstream_names: [&str; N], downstream_devices: [&dyn HLSNamedPorts; N]) -> Self {
33 let address_count = downstream_devices
34 .iter()
35 .map(|x| x.ports().len())
36 .collect::<Vec<_>>();
37 let mut _address_map = vec![];
38 for ndx in 0..N {
39 let prefix = downstream_names[ndx];
40 _address_map.extend(
41 downstream_devices[ndx]
42 .ports()
43 .iter()
44 .map(|x| format!("{}_{}", prefix, x)),
45 );
46 }
47 let mut offset = 0;
49 let mut node_rom = BTreeMap::new();
50 let mut base_rom = BTreeMap::new();
51 for (ndx, count) in address_count.iter().enumerate() {
52 assert_ne!(*count, 0);
53 for addr in 0..*count {
54 let address: Bits<A> = (offset + addr).to_bits();
55 let node: Bits<8> = ndx.to_bits();
56 node_rom.insert(address, node);
57 let virtual_address: Bits<A> = addr.to_bits();
58 base_rom.insert(address, virtual_address);
59 }
60 offset = offset + count;
61 }
62 Self {
63 upstream: Default::default(),
64 nodes: array_init::array_init(|_| Default::default()),
65 node_decode: ROM::new(node_rom),
66 virtual_decode: ROM::new(base_rom),
67 active: Default::default(),
68 virtual_address: Default::default(),
69 address_strobe_delay: Default::default(),
70 clock: Default::default(),
71 _address_map,
72 }
73 }
74}
75
76impl<const D: usize, const A: usize, const N: usize> Logic for RouterROM<D, A, N> {
77 #[hdl_gen]
78 fn update(&mut self) {
79 self.clock.next = self.upstream.clock.val();
80 self.upstream.ready.next = false;
81 self.upstream.to_controller.next = 0.into();
82 dff_setup!(self, clock, active, virtual_address, address_strobe_delay);
83 self.node_decode.address.next = self.upstream.address.val();
84 self.virtual_decode.address.next = self.upstream.address.val();
85 if self.upstream.address_strobe.val() {
86 self.active.d.next = self.node_decode.data.val();
87 self.virtual_address.d.next = self.virtual_decode.data.val();
88 }
89 self.address_strobe_delay.d.next = self.upstream.address_strobe.val();
92 for i in 0..N {
93 self.nodes[i].from_controller.next = 0x5ea1.into();
94 self.nodes[i].address.next = 0.into();
95 self.nodes[i].address_strobe.next = false;
96 self.nodes[i].strobe.next = false;
97 self.nodes[i].clock.next = self.clock.val();
98 if self.active.q.val().index() == i {
99 self.nodes[i].from_controller.next = self.upstream.from_controller.val();
100 self.nodes[i].address.next = self.virtual_address.q.val();
101 self.nodes[i].strobe.next = self.upstream.strobe.val();
102 self.upstream.to_controller.next = self.nodes[i].to_controller.val();
103 self.upstream.ready.next = self.nodes[i].ready.val();
104 self.nodes[i].address_strobe.next = self.address_strobe_delay.q.val();
105 }
106 }
107 if self.upstream.address_strobe.val() {
108 self.upstream.ready.next = false;
109 }
110 }
111}
112
113#[test]
114fn test_router_rom_is_synthesizable() {
115 use crate::bridge::Bridge;
116 let bridge1 = Bridge::<16, 8, 4>::new(["Top", "Left", "Right", "Bottom"]);
117 let bridge2 = Bridge::<16, 8, 2>::new(["Red", "Blue"]);
118 let bridge3 =
119 Bridge::<16, 8, 6>::new(["Club", "Spades", "Diamond", "Heart", "Joker", "Instruction"]);
120 let mut router =
121 RouterROM::<16, 8, 3>::new(["Sides", "Colors", "Faces"], [&bridge1, &bridge2, &bridge3]);
122 router.connect_all();
123 let vlog = generate_verilog(&router);
124 yosys_validate("router_rom", &vlog).unwrap();
125}