Skip to content

Commit

Permalink
All tests but calyx emission pass!
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanuppal committed Jul 25, 2024
1 parent e6349a0 commit 24482c4
Show file tree
Hide file tree
Showing 58 changed files with 917 additions and 491 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ members = [
]

[workspace.package]
name = "pulsar"
description = "A high-level programming language for building hardware accelerators"
homepage = "https://github.com/ethanuppal/pulsar/tree/main"
repository = "https://github.com/ethanuppal/pulsar/tree/main"
Expand Down Expand Up @@ -37,12 +36,10 @@ inform = "0.1.0"
serde = "1.0.204"
serde_json = "1.0.120"
memmap2 = "0.9.4"
log = "0.4.22"
log = { version = "0.4.22", features = ["release_max_level_off"] }
env_logger = "0.11.3"
either = "1.13.0"

[log]
features = ["release_max_level_off"]
match_deref = "0.1.1"

[package]
name = "pulsar-lang"
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ clean:
.PHONY: docs
docs:
@echo '[INFO] Building and viewing documentation'
@cargo doc -p pulsar-frontend -p pulsar-ir -p pulsar-backend -p pulsar-utils -p pulsar --no-deps
@cargo doc -p pulsar-frontend -p pulsar-ir -p pulsar-backend -p pulsar-utils -p pulsar-lang --no-deps --examples


.PHONY: cloc
Expand Down
1 change: 0 additions & 1 deletion data/test.plsr
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
func main(a: Int[64], b: Int[64]) -> (c: Int[64]) {
for i in 0 ..< 64 {
let temp = 4
c[i] = a[i] + b[i]
}
}
21 changes: 18 additions & 3 deletions pulsar-frontend/src/ast/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ use pulsar_utils::{id::Id, pool::Handle};
use std::{
cmp,
fmt::{self, Display, Write},
hash::Hash,
mem
};

/// This isn't a real liquid type. Notably, the only constraint it can
/// express is equality to a given number.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum LiquidTypeValue {
Equal(usize),
All
Expand All @@ -33,6 +34,12 @@ impl PartialEq for LiquidType {

impl Eq for LiquidType {}

impl Hash for LiquidType {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}

impl PartialOrd for LiquidType {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(match (&self.value, &other.value) {
Expand All @@ -53,8 +60,10 @@ impl PartialOrd for LiquidType {
impl PrettyPrint for LiquidType {
fn pretty_print(&self, f: &mut IndentFormatter<'_, '_>) -> fmt::Result {
match self.value {
LiquidTypeValue::Equal(value) => write!(f, "{}", value),
LiquidTypeValue::All => write!(f, "?")
LiquidTypeValue::Equal(value) => {
write!(f, "{{ x | x = {} }}", value)
}
LiquidTypeValue::All => write!(f, "{{ x | x >= 0 }}")
}
}
}
Expand Down Expand Up @@ -210,4 +219,10 @@ impl PartialEq for Type {

impl Eq for Type {}

impl Hash for Type {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}

pub trait AsTypePool: AsNodePool<Type> + AsNodePool<LiquidType> {}
9 changes: 0 additions & 9 deletions pulsar-frontend/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ pub type Block = (Handle<Token>, Vec<Handle<Stmt>>, Handle<Token>);
#[derive(Default)]
struct ParseErrorContext {
loc: String,
fix: Option<String>,
refback: Option<Error>
}

Expand All @@ -44,11 +43,6 @@ impl ParseErrorContext {
Self::default()
}

pub fn fix<S: AsRef<str>>(mut self, msg: S) -> Self {
self.fix = Some(msg.as_ref().to_string());
self
}

pub fn refback(mut self, error: Error) -> Self {
self.refback = Some(error);
self
Expand Down Expand Up @@ -249,7 +243,6 @@ impl<'ast, 'err, P: AsASTPool> Parser<'ast, 'err, P> {
.with_code(ErrorCode::UnexpectedEOF)
.span(self.buffer.last().unwrap())
.explain(format!("Unexpected EOF {}", context.loc))
.maybe_fix(context.fix)
.build()
);
if let Some(refback) = context.refback {
Expand All @@ -276,7 +269,6 @@ impl<'ast, 'err, P: AsASTPool> Parser<'ast, 'err, P> {
context.loc
))
.explain(format!("Received '{}' here", actual.ty.name()))
.maybe_fix(context.fix)
.build()
);
if let Some(refback) = context.refback {
Expand Down Expand Up @@ -305,7 +297,6 @@ impl<'ast, 'err, P: AsASTPool> Parser<'ast, 'err, P> {
context.loc
))
.explain(format!("Received '{}' here", actual.ty.name()))
.maybe_fix(context.fix)
.build()
);
if let Some(refback) = context.refback {
Expand Down
65 changes: 31 additions & 34 deletions pulsar-frontend/src/type_inferer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use pulsar_utils::{
pool::{AsPool, Handle, HandleArray},
span::SpanProvider
};
use std::{fmt::Display, iter::zip};
use std::{fmt::Display, hash::Hash, iter::zip};

pub struct UnificationConstraint<T> {
expected: Handle<T>,
Expand Down Expand Up @@ -67,7 +67,7 @@ pub type TypeConstraint = UnificationConstraint<Type>;
pub type LiquidTypeConstraint = UnificationConstraint<LiquidType>;

trait Unifier<
T: NodeInterface + Eq + Display,
T: NodeInterface + Eq + Hash + Display,
P: AsPool<UnificationConstraint<T>, ()>
> {
fn type_pool_mut(&mut self) -> &mut P;
Expand All @@ -79,7 +79,7 @@ trait Unifier<
.add(UnificationConstraint::new(expected, actual));

self.constraints().push(handle);
log::info!("encountered constraint: {} = {}", expected, actual);
log::trace!("encountered constraint: {} = {}", expected, actual);
}

fn derive_constraint(
Expand All @@ -91,7 +91,7 @@ trait Unifier<
.add(UnificationConstraint::derived(expected, actual, source));
self.constraints().push(handle);

log::info!(
log::trace!(
"encountered constraint: {} = {} (from {} = {})",
expected,
actual,
Expand Down Expand Up @@ -243,21 +243,6 @@ impl<'pool, 'err, P: AsInferencePool> TypeInferer<'pool, 'err, P> {
);
}

fn report_called_non_function(&mut self, name: Handle<Token>) {
self.report(
ErrorBuilder::new()
.of_style(Style::Primary)
.at_level(Level::Error)
.with_code(ErrorCode::StaticAnalysisIssue)
.span(name)
.message(format!(
"Cannot call non-function value `{}`",
name.value
))
.build()
);
}

// fn report_invalid_operation(&mut self, explain: String, ctx:
// Handle<Token>) { self.report(
// ErrorBuilder::new()
Expand All @@ -271,12 +256,14 @@ impl<'pool, 'err, P: AsInferencePool> TypeInferer<'pool, 'err, P> {
// );
// }

fn report_unification_failure<T: SpanProvider + Display>(
fn report_unification_failure<
T: SpanProvider + Display + Eq + Hash + Clone
>(
&mut self, constraint: Handle<UnificationConstraint<T>>,
fix: Option<String>
dsu: &mut DisjointSets<Handle<T>>, fix: Option<String>
) {
let expected = constraint.expected();
let actual = constraint.actual();
let expected = dsu.find(constraint.expected()).unwrap();
let actual = dsu.find(constraint.actual()).unwrap();
let mut builder = ErrorBuilder::new()
.of_style(Style::Primary)
.at_level(Level::Error)
Expand Down Expand Up @@ -366,12 +353,17 @@ impl<'pool, 'err, P: AsInferencePool> TypeInferer<'pool, 'err, P> {
} else {
let element_count = elements.len();
let mut elements = elements.iter();
let first = elements.next().unwrap();
let first_type = self.visit_expr(*first)?;
for other in elements {
let other_type = self.visit_expr(*other)?;
self.new_constraint(first_type, other_type);
}
let element_type = if element_count > 0 {
let first = elements.next().unwrap();
let first_type = self.visit_expr(*first)?;
for other in elements {
let other_type = self.visit_expr(*other)?;
self.new_constraint(first_type, other_type);
}
first_type
} else {
self.new_type_var(expr)
};
let liquid_type = self.pool.generate(
if should_continue.is_some() {
LiquidTypeValue::All
Expand All @@ -382,7 +374,7 @@ impl<'pool, 'err, P: AsInferencePool> TypeInferer<'pool, 'err, P> {
expr.end_token()
);
self.pool.generate(
TypeValue::Array(first_type, liquid_type),
TypeValue::Array(element_type, liquid_type),
expr.start_token(),
expr.end_token()
)
Expand Down Expand Up @@ -459,13 +451,18 @@ impl<'pool, 'err, P: AsInferencePool> TypeInferer<'pool, 'err, P> {
StmtValue::Divider(_) => todo!(),
StmtValue::For {
var,
lower: _,
exclusive_upper: _,
lower,
exclusive_upper,
body
} => {
self.env.push();
let loop_var_type =
self.pool.generate(TypeValue::Int64, *var, *var);
let lower_type = self.visit_expr(*lower)?;
let upper_type = self.visit_expr(*exclusive_upper)?;
// TODO: figure out better semantic arrangement/source for cnstr
self.new_constraint(loop_var_type, lower_type);
self.new_constraint(loop_var_type, upper_type);
self.env.bind(var.value.clone(), loop_var_type);

self.env.push();
Expand Down Expand Up @@ -570,7 +567,7 @@ impl<'pool, 'err, P: AsInferencePool> Unifier<Type, P>
}
}
_ => {
self.report_unification_failure(constraint, None);
self.report_unification_failure(constraint, dsu, None);
return Err(());
}
}
Expand Down Expand Up @@ -622,7 +619,7 @@ impl<'pool, 'err, P: AsInferencePool> Unifier<LiquidType, P>
dsu.union(actual, expected, false);
}
_ => {
self.report_unification_failure(constraint, None);
self.report_unification_failure(constraint, dsu, None);
return Err(());
}
}
Expand Down
1 change: 1 addition & 0 deletions pulsar-ir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pulsar-utils.workspace = true
inform.workspace = true
either.workspace = true
log.workspace = true
match_deref.workspace = true
14 changes: 6 additions & 8 deletions pulsar-ir/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
//! License as published by the Free Software Foundation, either version 3 of
//! the License, or (at your option) any later version.
use std::fmt::{self, Display};

use crate::memory::Memory;
use pulsar_frontend::ast::ty::{LiquidTypeValue, Type, TypeValue};
use std::fmt::{self, Display};

/// A hardware element capable of storage.
pub enum Cell {
Expand Down Expand Up @@ -47,14 +46,13 @@ impl Display for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Cell::Memory(memory) => {
write!(
f,
"Memory(length={}, element={}, bank={})",
memory.length, memory.element, memory.bank
)
for level in memory.levels() {
write!(f, "[{} bank {}]", level.length, level.bank)?;
}
Cell::Register(memory.element()).fmt(f)
}
Cell::Register(bit_width) => {
write!(f, "Register(width={})", bit_width)
write!(f, "[0:{}]()", bit_width - 1)
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions pulsar-ir/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ pub struct Component {
label: Label,
inputs: Vec<(Variable, Handle<Cell>)>,
outputs: Vec<(Variable, Handle<Cell>)>,
internal_cells: Vec<Handle<Cell>>,
// internal_cells: Vec<Handle<Cell>>,
/// Like reg-alloc but for cells. need better way to represent
cell_alloc: HashMap<Variable, Handle<Cell>>,
pub cell_alloc: HashMap<Variable, Handle<Cell>>,
pub(crate) cfg: Control
}

Expand All @@ -33,7 +33,7 @@ impl Component {
label,
inputs,
outputs,
internal_cells: Vec::new(),
// internal_cells: Vec::new(),
cell_alloc: initial_cell_alloc,
cfg
}
Expand Down Expand Up @@ -70,7 +70,9 @@ impl PrettyPrint for Component {
writeln!(f, "cells {{")?;
{
f.increase_indent();
for (var, cell) in &self.cell_alloc {
let mut cell_alloc_list: Vec<_> = self.cell_alloc.iter().collect();
cell_alloc_list.sort_by(|a, b| a.0.cmp(b.0));
for (var, cell) in &cell_alloc_list {
writeln!(f, "{} = {}", var, cell)?;
}
f.decrease_indent();
Expand Down
Loading

0 comments on commit 24482c4

Please sign in to comment.