Skip to content

Commit 439a479

Browse files
committed
scheduled fft
1 parent f74034e commit 439a479

28 files changed

+1242
-84
lines changed

apps/fft/versions/filament/fft.fil

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,18 @@ comp AbstractFPAdd[E, M]<'G:1>(
1212
R: ['G+L, 'G+L+1] W,
1313
) with {
1414
some W where W > 0;
15-
some L where L >= 0;
15+
some L where L > 0;
1616
} where
1717
E > 0,
1818
M > 0
1919
{
2020
assume E == 8;
2121
assume M == 23;
2222

23-
let shift = 2;
24-
a_shift := new Shift[32, shift]<'G>(X);
25-
b_shift := new Shift[32, shift]<'G>(Y);
26-
mult := new FAdd[32, 8, 23]<'G+shift>(a_shift.out, b_shift.out);
27-
mult_shift := new Shift[32, shift]<'G+shift>(mult.out);
28-
R = mult_shift.out;
29-
L := shift * 2;
23+
add := new FAdd[32, 8, 23]<'G>(X, Y);
24+
reg := new Delay[32]<'G>(add.out);
25+
R = reg.out;
26+
L := 1;
3027
W := 32;
3128
}
3229

@@ -38,21 +35,18 @@ comp AbstractFPSub[E, M]<'G:1>(
3835
R: ['G+L, 'G+L+1] W,
3936
) with {
4037
some W where W > 0;
41-
some L where L >= 0;
38+
some L where L > 0;
4239
} where
4340
E > 0,
4441
M > 0
4542
{
4643
assume E == 8;
4744
assume M == 23;
4845

49-
let shift = 2;
50-
a_shift := new Shift[32, shift]<'G>(X);
51-
b_shift := new Shift[32, shift]<'G>(Y);
52-
mult := new FSub[32, 8, 23]<'G+shift>(a_shift.out, b_shift.out);
53-
mult_shift := new Shift[32, shift]<'G+shift>(mult.out);
54-
R = mult_shift.out;
55-
L := shift * 2;
46+
sub := new FSub[32, 8, 23]<'G>(X, Y);
47+
reg := new Delay[32]<'G>(sub.out);
48+
R = reg.out;
49+
L := 1;
5650
W := 32;
5751
}
5852

@@ -65,22 +59,18 @@ comp AbstractFPMult[E, M]<'G: 1>(
6559
R: ['G+L, 'G+L+1] W,
6660
) with {
6761
some W where W > 0;
68-
some L where L >= 0;
62+
some L where L > 0;
6963
} where
7064
E > 0,
7165
M > 0
7266
{
7367
assume E == 8;
7468
assume M == 23;
7569

76-
let shift = 2;
77-
a_shift := new Shift[32, shift]<'G>(X);
78-
b_shift := new Shift[32, shift]<'G>(Y);
79-
mult := new FMult[32, 8, 23]<'G+shift>(a_shift.out, b_shift.out);
80-
mult_shift := new Shift[32, shift]<'G+shift>(mult.out);
81-
R = mult_shift.out;
82-
83-
L := shift * 2;
70+
mult := new FMult[32, 8, 23]<'G>(X, Y);
71+
reg := new Delay[32]<'G>(mult.out);
72+
R = reg.out;
73+
L := 1;
8474
W := 32;
8575
}
8676

apps/fft/versions/scheduled/fft.fil

Lines changed: 524 additions & 0 deletions
Large diffs are not rendered by default.

crates/filament/src/ir_passes/mono/monodeferred.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,33 @@ impl MonoDeferred<'_, '_> {
189189
// Monomorphize the component's body
190190
self.body();
191191

192+
// if this component has an interface, use the scheduling register.
193+
// Otherwise, use the shift register.
194+
assert!(
195+
self.underlying.events().len() == 1,
196+
"Component with multiple events cannot be scheduled."
197+
);
198+
199+
let delay_register = if self
200+
.underlying
201+
.events()
202+
.iter()
203+
.next()
204+
.unwrap()
205+
.1
206+
.has_interface
207+
{
208+
self.pass.scheduling_reg
209+
} else {
210+
self.pass.scheduling_shift
211+
};
212+
192213
// Run scheduling pass if needed
193214
if self.schedule {
194215
schedule::schedule(
195216
&self.pass.ctx,
196217
self.monosig.base.comp_mut(),
197-
self.pass.scheduling_reg,
218+
delay_register,
198219
self.pass.opts.solver_replay_file.as_ref(),
199220
);
200221
}

crates/filament/src/ir_passes/mono/monomorphize.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{cmdline, ir_passes::schedule::create_delay_register};
1+
use crate::{
2+
cmdline,
3+
ir_passes::schedule::{create_delay_register, create_delay_shift_register},
4+
};
25

36
use super::{
47
Base, CompKey, InstanceInfo, IntoBase, IntoUdl, MonoDeferred, MonoSig,
@@ -74,6 +77,8 @@ pub struct Monomorphize<'a> {
7477
gen_exec: &'a mut Option<fgen::GenExec>,
7578
/// Scheduling register
7679
pub scheduling_reg: ir::CompIdx,
80+
/// Scheduling shift register
81+
pub scheduling_shift: ir::CompIdx,
7782
}
7883

7984
impl<'a> Monomorphize<'a> {
@@ -84,6 +89,7 @@ impl<'a> Monomorphize<'a> {
8489
) -> Self {
8590
let mut ctx = ir::Context::default();
8691
let scheduling_reg = create_delay_register(&mut ctx);
92+
let scheduling_shift = create_delay_shift_register(&mut ctx);
8793

8894
Monomorphize {
8995
ctx,
@@ -95,6 +101,7 @@ impl<'a> Monomorphize<'a> {
95101
ext_map: HashMap::new(),
96102
gen_exec,
97103
scheduling_reg,
104+
scheduling_shift,
98105
}
99106
}
100107
}

crates/filament/src/ir_passes/schedule/combinational_paths.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ impl CombDataflow {
3434
.get(output)
3535
.get(utils::PortFloat::CombDelay)
3636
.unwrap_or_else(|| {
37-
panic!(
38-
"Combinational delay not found for port {}",
37+
log::warn!(
38+
"Combinational delay not found for port {}. Assuming zero.",
3939
comp.display(output)
40-
)
40+
);
41+
&0.0
4142
});
4243

4344
log::trace!(

crates/filament/src/ir_passes/schedule/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ mod solve;
66

77
use combinational_paths::CombDataflow;
88
pub use pass::schedule;
9-
pub use register::create_delay_register;
9+
pub use register::{create_delay_register, create_delay_shift_register};

crates/filament/src/ir_passes/schedule/register.rs

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,178 @@ use fil_ir::{self as ir, AddCtx, MutCtx};
33
use fil_utils::GPosIdx;
44
use std::path::PathBuf;
55

6+
// Delay shift register for interface-less components
7+
pub fn create_delay_shift_register(ctx: &mut ir::Context) -> ir::CompIdx {
8+
let mut sv_file = <PathBuf as From<_>>::from(file!());
9+
sv_file.pop();
10+
sv_file.push("register.sv");
11+
12+
log::debug!(
13+
"Adding external scheduling register from {}",
14+
sv_file.display()
15+
);
16+
17+
// Next, build the external component
18+
let mut comp =
19+
ir::Component::new(ir::CompType::External, Default::default());
20+
21+
let mut src_info =
22+
ir::InterfaceSrc::new("__SchedulingDelayShift".into(), None);
23+
24+
// Set up parameters to the component
25+
26+
let width = comp.add(ir::Info::param("WIDTH".into(), GPosIdx::UNKNOWN));
27+
let width = comp.add(ir::Param::new(ir::ParamOwner::Sig, width));
28+
29+
let delay = comp.add(ir::Info::param("DELAY".into(), GPosIdx::UNKNOWN));
30+
let delay = comp.add(ir::Param::new(ir::ParamOwner::Sig, delay));
31+
32+
let live = comp.add(ir::Info::param("LIVE".into(), GPosIdx::UNKNOWN));
33+
let live = comp.add(ir::Param::new(ir::ParamOwner::Sig, live));
34+
35+
// Add the parameters to the component
36+
src_info.params.push(width, "WIDTH".into());
37+
src_info.params.push(delay, "DELAY".into());
38+
src_info.params.push(live, "LIVE".into());
39+
40+
// Intern the proposition that LIVE == 1 (as this is interfaceless)
41+
let live_expr = comp.add(ir::Expr::Param(live));
42+
let live_prop = ir::Prop::Cmp(ir::CmpOp::eq(
43+
live_expr,
44+
comp.add(ir::Expr::Concrete(1)),
45+
));
46+
let live_prop = comp.add(live_prop);
47+
let live_info = comp.add(ir::Info::assert(ir::info::Reason::misc(
48+
"Signature assumption",
49+
GPosIdx::UNKNOWN,
50+
)));
51+
52+
comp.add_param_assert([(live_prop, GPosIdx::UNKNOWN)]);
53+
comp.param_args = Box::new([width, delay, live]);
54+
55+
let live_assumption = comp.assume(live_prop, live_info);
56+
comp.cmds.extend(live_assumption);
57+
58+
let width = comp.add(ir::Expr::Param(width));
59+
let delay = comp.add(ir::Expr::Param(delay));
60+
61+
// Concrete expressions
62+
let zero = comp.add(ir::Expr::Concrete(0));
63+
let one = comp.add(ir::Expr::Concrete(1));
64+
65+
let delay_1 = comp.add(ir::Expr::Bin {
66+
op: ast::Op::Add,
67+
lhs: delay,
68+
rhs: one,
69+
});
70+
71+
// Set up the event of the component
72+
let event = comp.add(ir::Info::event(
73+
"G".into(),
74+
GPosIdx::UNKNOWN,
75+
GPosIdx::UNKNOWN,
76+
None,
77+
));
78+
let event = comp.add(ir::Event {
79+
delay: ir::TimeSub::Unit(one),
80+
info: event,
81+
has_interface: false,
82+
});
83+
src_info.events.push(event, "G".into());
84+
comp.event_args = Box::new([event]);
85+
86+
// Set up ports to the component
87+
88+
// clk and reset ports are unannotated
89+
comp.unannotated_ports =
90+
Box::new(vec![("clk".into(), 1), ("reset".into(), 1)]);
91+
92+
// input port
93+
let input = ir::Port {
94+
owner: ir::PortOwner::Sig {
95+
dir: ir::Direction::Out,
96+
},
97+
width,
98+
live: ir::Liveness {
99+
idxs: vec![],
100+
lens: vec![comp.add(ir::Expr::Concrete(1))],
101+
range: ir::Range {
102+
start: comp.add(ir::Time {
103+
event,
104+
offset: zero,
105+
}),
106+
end: comp.add(ir::Time { event, offset: one }),
107+
},
108+
},
109+
info: comp.add(ir::Info::port(
110+
"in".into(),
111+
GPosIdx::UNKNOWN,
112+
GPosIdx::UNKNOWN,
113+
GPosIdx::UNKNOWN,
114+
)),
115+
};
116+
let input = comp.add(input);
117+
let input_param = ir::Param {
118+
owner: ir::ParamOwner::bundle(input),
119+
info: comp.add(ir::Info::param("_".into(), GPosIdx::UNKNOWN)),
120+
};
121+
let input_param = comp.add(input_param);
122+
123+
comp.get_mut(input).live.idxs.push(input_param);
124+
src_info.ports.push(input, "in".into());
125+
126+
// output port
127+
let output = ir::Port {
128+
owner: ir::PortOwner::Sig {
129+
dir: ir::Direction::In,
130+
},
131+
width,
132+
live: ir::Liveness {
133+
idxs: vec![],
134+
lens: vec![comp.add(ir::Expr::Concrete(1))],
135+
range: ir::Range {
136+
start: comp.add(ir::Time {
137+
event,
138+
offset: delay,
139+
}),
140+
end: comp.add(ir::Time {
141+
event,
142+
offset: delay_1,
143+
}),
144+
},
145+
},
146+
info: comp.add(ir::Info::port(
147+
"out".into(),
148+
GPosIdx::UNKNOWN,
149+
GPosIdx::UNKNOWN,
150+
GPosIdx::UNKNOWN,
151+
)),
152+
};
153+
let output = comp.add(output);
154+
155+
let output_param = ir::Param {
156+
owner: ir::ParamOwner::bundle(output),
157+
info: comp.add(ir::Info::param("_".into(), GPosIdx::UNKNOWN)),
158+
};
159+
let output_param = comp.add(output_param);
160+
161+
comp.get_mut(output).live.idxs.push(output_param);
162+
src_info.ports.push(output, "out".into());
163+
164+
comp.src_info = Some(src_info);
165+
comp.port_attrs = ir::DenseIndexInfo::with_default(comp.ports().len());
166+
167+
// Add the component to the context
168+
169+
let compidx = ctx.add(comp);
170+
171+
// Add the component to the external list
172+
let filename = sv_file.to_str().unwrap().to_string();
173+
ctx.externals.entry(filename).or_default().push(compidx);
174+
175+
compidx
176+
}
177+
6178
pub fn create_delay_register(ctx: &mut ir::Context) -> ir::CompIdx {
7179
let mut sv_file = <PathBuf as From<_>>::from(file!());
8180
sv_file.pop();

crates/filament/src/ir_passes/schedule/register.sv

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,38 @@
11

2+
module __SchedulingDelayShift #(
3+
parameter WIDTH = 32,
4+
parameter DELAY = 0,
5+
parameter LIVE = 1
6+
) (
7+
input wire clk,
8+
input wire reset,
9+
input wire logic [WIDTH-1:0] in, // ['G, 'G+1]
10+
output logic [WIDTH-1:0] out // ['G+DELAY, 'G+DELAY+1]
11+
);
12+
13+
// Basic shift register
14+
logic [WIDTH-1:0] shift[DELAY-1:0];
15+
always @(posedge clk) begin
16+
if (reset) begin
17+
shift[0] <= 0;
18+
end else begin
19+
shift[0] <= in;
20+
end
21+
end
22+
for (genvar i = 1; i < DELAY; i++) begin
23+
always @(posedge clk) begin
24+
if (reset) begin
25+
shift[i] <= 0;
26+
end else begin
27+
shift[i] <= shift[i-1];
28+
end
29+
end
30+
end
31+
32+
assign out = shift[DELAY-1];
33+
endmodule
34+
35+
236
module __SchedulingDelayRegister #(
337
parameter WIDTH = 32,
438
parameter DELAY = 0,

0 commit comments

Comments
 (0)