rhdl_fpga_planner/
resources.rs1use crate::*;
5
6pub const U280_LUT: u32 = 1_303_680;
8pub const U280_DSP: u32 = 9_024;
10pub const U280_BRAM36: u32 = 2_016;
12pub const U280_URAM: u32 = 960;
14pub const BUDGET_BRAM36: u32 = 1_776;
18pub const BASE_LUT: u32 = 485_000;
22pub const BASE_DSP: u32 = 4_520;
25pub const SHA_DEFAULT_LUT: u32 = 65_000;
29pub const DSIG_BATCH: f64 = 128.0;
32pub const SHA512_BLOCKS: &str = "sha512 blocks";
34
35#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
37pub struct Cost {
38 pub lut: u32,
40 pub dsp: u32,
42 pub bram36: u32,
44 pub uram: u32,
46}
47
48impl Cost {
50 pub fn add(self, other: Cost, n: u32) -> Cost {
52 Cost {
53 lut: self.lut + n * other.lut,
54 dsp: self.dsp + n * other.dsp,
55 bram36: self.bram36 + n * other.bram36,
56 uram: self.uram + n * other.uram,
57 }
58 }
59 pub fn fits(&self, share: &Share) -> bool {
61 self.lut <= share.lut && self.dsp <= share.dsp && self.bram36 <= share.bram36 && self.uram <= share.uram
62 }
63 pub fn limit(&self, share: &Share) -> &'static str {
65 let ratios = [
66 (self.lut as f64 / share.lut.max(1) as f64, "LUT"),
67 (self.dsp as f64 / share.dsp.max(1) as f64, "DSP"),
68 (self.bram36 as f64 / share.bram36.max(1) as f64, "BRAM"),
69 (self.uram as f64 / share.uram.max(1) as f64, "URAM"),
70 ];
71 ratios.iter().fold((0.0, "none"), |a, b| if b.0 > a.0 { *b } else { a }).1
72 }
73}
74
75pub type Share = Cost;
77
78#[derive(Clone, Copy, Debug, PartialEq)]
80pub struct Budget {
81 pub lut_percent: f64,
83 pub dsp_percent: f64,
85 pub bram_percent: f64,
88 pub uram_percent: f64,
90}
91
92impl Default for Budget {
95 fn default() -> Self {
96 Budget { lut_percent: 100.0, dsp_percent: 100.0, bram_percent: 100.0, uram_percent: 100.0 }
97 }
98}
99
100impl Budget {
102 pub fn luts(&self) -> u32 {
104 ((BASE_LUT as f64 * self.lut_percent / 100.0) as u32).min(U280_LUT)
105 }
106 pub fn dsps(&self) -> u32 {
108 ((BASE_DSP as f64 * self.dsp_percent / 100.0) as u32).min(U280_DSP)
109 }
110 pub fn brams(&self) -> u32 {
112 (BUDGET_BRAM36 as f64 * self.bram_percent.clamp(0.0, 100.0) / 100.0) as u32
113 }
114 pub fn urams(&self) -> u32 {
116 (U280_URAM as f64 * self.uram_percent.clamp(0.0, 100.0) / 100.0) as u32
117 }
118 pub fn chip(&self) -> Share {
121 Share { lut: self.luts(), dsp: self.dsps(), bram36: self.brams(), uram: self.urams() }
122 }
123 pub fn rest(&self, slots: &[Slot]) -> Share {
126 self.rest_with(&allowances(slots))
127 }
128 pub fn rest_with(&self, allow: &[Option<Share>]) -> Share {
130 let fixed = allow.iter().flatten().fold(Cost::default(), |a, f| a.add(*f, 1));
131 Share {
132 lut: self.luts().saturating_sub(fixed.lut),
133 dsp: self.dsps().saturating_sub(fixed.dsp),
134 bram36: self.brams().saturating_sub(fixed.bram36),
135 uram: self.urams().saturating_sub(fixed.uram),
136 }
137 }
138}
139
140#[derive(Clone, Copy, Debug, PartialEq, Eq)]
142pub enum Resource {
143 Lut,
145 Dsp,
147 Bram,
149 Uram,
151}
152
153impl Resource {
154 pub const ALL: [Resource; 4] = [Resource::Lut, Resource::Dsp, Resource::Bram, Resource::Uram];
156 pub fn name(self) -> &'static str {
158 match self {
159 Resource::Lut => "LUT",
160 Resource::Dsp => "DSP",
161 Resource::Bram => "BRAM",
162 Resource::Uram => "URAM",
163 }
164 }
165 pub fn of(self, c: &Cost) -> u32 {
167 match self {
168 Resource::Lut => c.lut,
169 Resource::Dsp => c.dsp,
170 Resource::Bram => c.bram36,
171 Resource::Uram => c.uram,
172 }
173 }
174 pub fn with(self, c: Cost, n: u32) -> Cost {
176 match self {
177 Resource::Lut => Cost { lut: n, ..c },
178 Resource::Dsp => Cost { dsp: n, ..c },
179 Resource::Bram => Cost { bram36: n, ..c },
180 Resource::Uram => Cost { uram: n, ..c },
181 }
182 }
183}