Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Calyx-FIRRTL] Add fud2 support for FIRRTL-written primitives + externalized memory simulation #1898

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d52e14b
Debug std_reg FIRRTL implementation
ayakayorihiro Jan 29, 2024
a2df85a
Fix std_const template typo
ayakayorihiro Jan 30, 2024
5c8fa19
Fix std_lsh FIRRTL primitive
ayakayorihiro Jan 31, 2024
44ce33c
Fixed std_reg bug that was causing to fail
ayakayorihiro Feb 1, 2024
1c752e1
Add fud2 support for FIRRTL-written primitives
ayakayorihiro Feb 5, 2024
a63b1d9
[SCRATCH] Committing current progress on fud2 e2e support for firrtl …
ayakayorihiro Feb 5, 2024
c4c6a63
Complete support for firrtl with primitives
ayakayorihiro Feb 6, 2024
8dde74f
Merge branch 'firrtl-primitives-debug' into fud2-firrtl-with-primitives
ayakayorihiro Feb 6, 2024
4254a80
Fix bug in externalized_mem
ayakayorihiro Feb 6, 2024
1a63051
Support creating extmodule for a special primitive that reads a memor…
ayakayorihiro Feb 6, 2024
7a9f657
Merge branch 'main' into fud2-firrtl-with-primitives
ayakayorihiro Feb 6, 2024
0f6d5dd
Started writing script to produce Verilog testbench that reads and wr…
ayakayorihiro Feb 9, 2024
a168169
Script to generate a custom testbench given the memories in a program
ayakayorihiro Feb 9, 2024
98d13cc
Fix bugs for memories with multiple index sizes
ayakayorihiro Feb 9, 2024
bee9275
Some cleanup from previous experimentation
ayakayorihiro Feb 9, 2024
a88caf5
Merge branch 'main' into fud2-firrtl-with-primitives
ayakayorihiro Feb 10, 2024
d3a2b78
Some changes based on PR comments
ayakayorihiro Feb 10, 2024
7729794
Fix fud2 to produce custom testbench. This is a bit hacky
ayakayorihiro Feb 11, 2024
ea1df1d
Fix formatting errors
ayakayorihiro Feb 11, 2024
7da5c8c
Small bug fixes and std_mult_pipe first pass
ayakayorihiro Feb 12, 2024
d8f48ba
Cleanup script
ayakayorihiro Feb 13, 2024
f0f7c26
First pass fix at setting output ports that are never used to invalid
ayakayorihiro Feb 13, 2024
81d0355
Fix clippy errors
ayakayorihiro Feb 13, 2024
457e6ee
Quick debugging of port hack + adding support for seq_mem_d1
ayakayorihiro Feb 13, 2024
2a47d00
Update backend tests to contain invalidation for all output ports upf…
ayakayorihiro Feb 13, 2024
1162924
Support for seq_mem_d2 in testbench generation script
ayakayorihiro Feb 13, 2024
e6150ea
Fix quick bug
ayakayorihiro Feb 13, 2024
86b72fb
Add seq mem definitions for extmodule version of firrtl
ayakayorihiro Feb 13, 2024
acbbe1e
Starter for std_div_pipe
ayakayorihiro Feb 14, 2024
4961f1c
Fix fud2 so that all firrtl leads to uses of the custom testbench
ayakayorihiro Feb 14, 2024
8337bb1
Use common method for output port initialization
ayakayorihiro Feb 19, 2024
3c0e659
Add description for dummy script
ayakayorihiro Feb 19, 2024
4f8a50e
Merge branch 'main' into fud2-firrtl-with-primitives
ayakayorihiro Feb 20, 2024
7017143
Revert "Single Port Memories (#1610)"
ayakayorihiro Feb 26, 2024
535962e
[WIP] Trying to implement std_div_pipe and stuck in an infinite loop …
ayakayorihiro Feb 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ RUN python3 setup.py bdist_wheel && python3 -m pip install dist/tvm-*.whl
WORKDIR /home
RUN git clone https://github.com/cucapra/dahlia.git
WORKDIR /home/dahlia
## Checkout specific version. Fetch before checkout because clone might be cached.
RUN git fetch --all && git checkout 88e05e5
## Checkout specific version
RUN git checkout 51954e7
RUN sbt "; getHeaders; assembly"

# Add the Calyx source code from the build context
Expand Down
15 changes: 13 additions & 2 deletions calyx-backend/src/firrtl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use calyx_ir::{self as ir, Binding, RRC};
use calyx_utils::{CalyxResult, Id, OutputFile};
use ir::Port;
use std::cell::RefCell;
use std::collections::HashSet;
use std::io;

Expand Down Expand Up @@ -82,6 +83,8 @@
comp: &ir::Component,
f: &mut F,
) -> io::Result<()> {
let mut dst_set: HashSet<ir::Canonical> = HashSet::new();

writeln!(f, "{}module {}:", SPACING, comp.name)?;

// Inputs and Outputs
Expand All @@ -91,6 +94,15 @@
emit_port(port, true, f)?;
}

// write invalid statements for all output ports.
for (_idx, port_ref) in sig.ports.iter().enumerate() {

Check failure on line 98 in calyx-backend/src/firrtl.rs

View workflow job for this annotation

GitHub Actions / Check Formatting

you seem to use `.enumerate()` and immediately discard the index
let port = port_ref.as_ref();
if port.borrow().direction == calyx_frontend::Direction::Input {
write_invalid_initialization(port, f)?;
dst_set.insert(port.borrow().canonical());
}
}

// Add a COMPONENT START: <name> anchor before any code in the component
writeln!(f, "{}; COMPONENT START: {}", SPACING.repeat(2), comp.name)?;

Expand Down Expand Up @@ -118,7 +130,6 @@
}
}

let mut dst_set: HashSet<ir::Canonical> = HashSet::new();
// Emit assignments
for asgn in &comp.continuous_assignments {
match asgn.guard.as_ref() {
Expand Down Expand Up @@ -293,7 +304,7 @@

// variables that get set in assignments should get initialized to avoid the FIRRTL compiler from erroring.
fn write_invalid_initialization<F: io::Write>(
port: &RRC<ir::Port>,
port: &RefCell<ir::Port>,
f: &mut F,
) -> io::Result<()> {
let default_initialization_str = "; default initialization";
Expand Down
4 changes: 2 additions & 2 deletions calyx-ir/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ impl<T: GetName> WRC<T> {
pub fn upgrade(&self) -> RRC<T> {
let Some(r) = self.internal.upgrade() else {
#[cfg(debug_assertions)]
unreachable!("weak reference points to a dropped value. Original object's name: `{}'", self.debug_name);
unreachable!("weak reference points to a dropped. Original object's name: `{}'", self.debug_name);
#[cfg(not(debug_assertions))]
unreachable!("weak reference points to a dropped value.");
unreachable!("weak reference points to a dropped.");
};
r
}
Expand Down
10 changes: 1 addition & 9 deletions calyx-ir/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,6 @@ impl Component {
self.namegen.gen_name(prefix)
}

/// Check whether this component is purely structural, i.e. has no groups or control
pub fn is_structural(&self) -> bool {
self.groups.is_empty()
&& self.comb_groups.is_empty()
&& self.static_groups.is_empty()
&& self.control.borrow().is_empty()
}

/// Check whether this is a static component.
/// A static component is a component which has a latency field.
pub fn is_static(&self) -> bool {
Expand Down Expand Up @@ -324,7 +316,7 @@ impl Component {
#[derive(Debug)]
pub struct IdList<T: GetName>(LinkedHashMap<Id, RRC<T>>);

/// Simple iter impl delegating to the [`Values`](linked_hash_map::Values).
/// Simple into-iter impl delegating to the [`Values`](linked_hash_map::Values).
impl<'a, T: GetName> IntoIterator for &'a IdList<T> {
type Item = &'a RRC<T>;

Expand Down
8 changes: 3 additions & 5 deletions calyx-opt/src/default_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::passes::{
AddGuard, Canonicalize, CellShare, ClkInsertion, CollapseControl, CombProp,
CompileInvoke, CompileRepeat, CompileStatic, CompileStaticInterface,
CompileSync, CompileSyncWithoutSyncReg, ComponentInliner, DataPathInfer,
DeadAssignmentRemoval, DeadCellRemoval, DeadGroupRemoval, DefaultAssigns,
DiscoverExternal, Externalize, GoInsertion, GroupToInvoke, GroupToSeq,
HoleInliner, InferShare, LowerGuards, MergeAssign, Papercut, ParToSeq,
DeadAssignmentRemoval, DeadCellRemoval, DeadGroupRemoval, DiscoverExternal,
Externalize, GoInsertion, GroupToInvoke, GroupToSeq, HoleInliner,
InferShare, LowerGuards, MergeAssign, Papercut, ParToSeq,
RegisterUnsharing, RemoveIds, ResetInsertion, SimplifyStaticGuards,
SimplifyWithControl, StaticInference, StaticInliner, StaticPromotion,
SynthesisPapercut, TopDownCompileControl, UnrollBounded, WellFormed,
Expand Down Expand Up @@ -59,7 +59,6 @@ impl PassManager {
pm.register_pass::<ResetInsertion>()?;
pm.register_pass::<MergeAssign>()?;
pm.register_pass::<WrapMain>()?;
pm.register_pass::<DefaultAssigns>()?;

// Enabled in the synthesis compilation flow
pm.register_pass::<SynthesisPapercut>()?;
Expand Down Expand Up @@ -135,7 +134,6 @@ impl PassManager {
ClkInsertion,
ResetInsertion,
MergeAssign,
DefaultAssigns,
]
);

Expand Down
129 changes: 0 additions & 129 deletions calyx-opt/src/passes/default_assigns.rs

This file was deleted.

2 changes: 0 additions & 2 deletions calyx-opt/src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ mod sync;
mod add_guard;
mod compile_static_interface;
mod data_path_infer;
mod default_assigns;
mod discover_external;
mod simplify_with_control;
mod synthesis_papercut;
Expand Down Expand Up @@ -82,7 +81,6 @@ pub use sync::CompileSyncWithoutSyncReg;
// pub use simplify_guards::SimplifyGuards;
pub use add_guard::AddGuard;
pub use compile_static_interface::CompileStaticInterface;
pub use default_assigns::DefaultAssigns;
pub use synthesis_papercut::SynthesisPapercut;
pub use top_down_compile_control::TopDownCompileControl;
pub use unroll_bound::UnrollBounded;
Expand Down
65 changes: 18 additions & 47 deletions calyx-opt/src/passes/papercut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,6 @@ pub struct Papercut {
cont_cells: HashSet<ir::Id>,
}

impl Papercut {
#[allow(unused)]
/// String representation of the write together and read together specifications.
/// Used for debugging. Should not be relied upon by external users.
fn fmt_write_together_spec(&self) -> String {
self.write_together
.iter()
.map(|(prim, writes)| {
let writes = writes
.iter()
.map(|write| {
write
.iter()
.sorted()
.map(|port| format!("{port}"))
.join(", ")
})
.join("; ");
format!("{}: [{}]", prim, writes)
})
.join("\n")
}
}

impl ConstructVisitor for Papercut {
fn from(ctx: &ir::Context) -> CalyxResult<Self> {
let write_together =
Expand Down Expand Up @@ -256,7 +232,7 @@ impl Papercut {
.join(", ");
let msg =
format!("Required signal not driven inside the group.\
\nWhen reading the port `{}.{}', the ports [{}] must be written to.\
\nWhen read the port `{}.{}', the ports [{}] must be written to.\
\nThe primitive type `{}' requires this invariant.",
inst,
read,
Expand All @@ -269,35 +245,30 @@ impl Papercut {
}
for ((inst, comp_type), writes) in all_writes {
if let Some(spec) = self.write_together.get(&comp_type) {
// For each write together spec.
for required in spec {
// It should either be the case that:
// 1. `writes` contains no writes that overlap with `required`
// In which case `required - writes` == `required`.
// 2. `writes` contains writes that overlap with `required`
// In which case `required - writes == {}`
let mut diff: HashSet<_> =
required.difference(&writes).copied().collect();
if diff.is_empty() || diff == *required {
continue;
let mut diff = required - &writes;
if !diff.is_empty() && diff != *required {
let first = writes.iter().sorted().next().unwrap();
let missing = diff
.drain()
.sorted()
.map(|port| format!("{}.{}", inst, port))
.join(", ");
let msg =
format!("Required signal not driven inside the group.\
\nWhen writing to the port `{}.{}', the ports [{}] must also be written to.\
\nThe primitive type `{}' requires this invariant.",
inst,
first,
missing,
comp_type);
return Err(Error::papercut(msg));
}

let first =
writes.intersection(required).sorted().next().unwrap();
let missing = diff
.drain()
.sorted()
.map(|port| format!("{}.{}", inst, port))
.join(", ");
let msg =
format!("Required signal not driven inside the group. \
When writing to the port `{}.{}', the ports [{}] must also be written to. \
The primitive type `{}' specifies this using a @write_together spec.",
inst,
first,
missing,
comp_type);
return Err(Error::papercut(msg));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion calyx-opt/src/passes/well_formed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl ConstructVisitor for WellFormed {
let mut ref_cell_types = HashMap::new();
for comp in ctx.components.iter() {
// Main component cannot use `ref` cells
if comp.name == ctx.entrypoint {
if !ctx.bc.synthesis_mode && comp.name == ctx.entrypoint {
for cell in comp.cells.iter() {
if cell.borrow().is_reference() {
return Err(Error::malformed_structure(
Expand Down
Loading
Loading