Compare commits

..

No commits in common. "68be74d032b74cb3de03e898cdac2055a41bf109" and "f03c777e285ac0c69bd296238f2234766c8cbf2a" have entirely different histories.

5 changed files with 53 additions and 117 deletions

View File

@ -43,9 +43,22 @@ impl CompileError {
} }
} }
#[derive(Debug)] /// A user-defined signal
pub struct Module { pub struct Signal {
pub blocks: Vec<typed_ir::Block>, /// the user-visible name of the signal
pub name: String,
/// the id of the signal in RTLIL
pub il_id: String,
/// the type of the signal
pub typ: Type,
// unique ID of the signal
// pub uid: u64,
}
impl Signal {
fn sigspec(&self) -> rtlil::SigSpec {
rtlil::SigSpec::Wire(self.il_id.to_owned())
}
} }
pub struct Context { pub struct Context {
@ -214,20 +227,20 @@ impl Context {
Ok(t_expr) Ok(t_expr)
} }
fn callable_from_block( fn type_comb(
&mut self, &mut self,
comb: &parser::comb::CombBlock, comb: &parser::comb::CombBlock,
) -> Result<CallableId, CompileError> { ) -> Result<typed_ir::Block, CompileError> {
let mut genargs = vec![]; let mut signals = Vec::new();
for (idx, tvarname) in comb.genparams.iter().enumerate() { for (idx, tvarname) in comb.genparams.iter().enumerate() {
let tvar = self.types.make_typevar(0, idx as u32); let tvar = self.types.make_typevar(0, idx as u32);
// hacky workaround for no scopes
self.typenames.insert(tvarname.name.to_string(), tvar); self.typenames.insert(tvarname.name.to_string(), tvar);
genargs.push((Some(tvarname.name.to_string()), tvar));
} }
let mut args = vec![];
for port in comb.ports.iter() { for port in comb.ports.iter() {
let sig_id = self.ids.next();
let sig_typename = &port.net.typ; let sig_typename = &port.net.typ;
let mut sig_type = self.try_get_type(sig_typename.name.fragment())?; let mut sig_type = self.try_get_type(sig_typename.name.fragment())?;
if let Some(arg) = &sig_typename.generics { if let Some(arg) = &sig_typename.generics {
@ -239,73 +252,38 @@ impl Context {
.unwrap(); .unwrap();
} }
args.push((Some(port.net.name.to_string()), sig_type)); let sig = typed_ir::Signal {
id: typed_ir::DefId(sig_id as u32),
typ: sig_type,
};
signals.push(sig.clone());
self.signals.insert(port.net.name.to_string(), sig);
} }
let ret_typename = &comb.ret.name; let ret_typename = &comb.ret.name;
let ret_type = self.try_get_type(ret_typename.fragment())?; let _ret_type = self.try_get_type(ret_typename.fragment())?;
// TODO: use ret type
let signature = Callable {
name: comb.name.to_string(),
args,
genargs,
ret_type,
};
let signature_id = self.callables.add(signature);
self.callable_names
.insert(comb.name.to_string(), signature_id);
Ok(signature_id)
}
fn type_comb(
&mut self,
comb: &parser::comb::CombBlock,
) -> Result<typed_ir::Block, CompileError> {
let mut signals = Vec::new();
let callable_id = self.callable_from_block(comb)?;
let callable = self.callables.get(callable_id);
for (argname, typ) in &callable.args {
let sig_id = self.ids.next();
let sig = typed_ir::Signal {
id: typed_ir::DefId(sig_id as u32),
typ: *typ,
};
signals.push(sig.clone());
if let Some(argname) = argname {
self.signals.insert(argname.clone(), sig);
}
}
let root_expr = self.type_expression(&comb.expr)?; let root_expr = self.type_expression(&comb.expr)?;
Ok(typed_ir::Block { Ok(typed_ir::Block {
signature: callable_id,
signals, signals,
expr: root_expr, expr: root_expr,
}) })
} }
pub fn type_module(&mut self, module: parser::Module) -> Result<Module, CompileError> { pub fn type_module(&mut self, module: parser::Module) -> Result<typed_ir::Block, CompileError> {
let mut typed_module = Module { blocks: vec![] };
// hacky loop to predefine all names
for item in &module.items {
match &item {
parser::ModuleItem::Comb(comb) => self.callable_from_block(comb)?,
parser::ModuleItem::Proc(_) => todo!("proc block"),
parser::ModuleItem::State(_) => todo!("state block"),
};
}
for item in module.items { for item in module.items {
let block = match &item { let block = match &item {
parser::ModuleItem::Comb(comb) => self.type_comb(comb)?, parser::ModuleItem::Comb(comb) => self.type_comb(comb)?,
parser::ModuleItem::Proc(_) => todo!("proc block"), parser::ModuleItem::Proc(_) => todo!("proc block"),
parser::ModuleItem::State(_) => todo!("state block"), parser::ModuleItem::State(_) => todo!("state block"),
}; };
typed_module.blocks.push(block); return Ok(block);
} }
Ok(typed_module) Err(CompileError::new(CompileErrorKind::TodoError(
"no blocks in module".to_string(),
)))
} }
pub fn infer_expr_types(&mut self, expr: &typed_ir::Expr) -> typed_ir::Expr { pub fn infer_expr_types(&mut self, expr: &typed_ir::Expr) -> typed_ir::Expr {
@ -314,7 +292,7 @@ impl Context {
return expr.clone(); return expr.clone();
} }
match &expr.kind { match &expr.kind {
typed_ir::ExprKind::Literal(lit) => expr.clone().with_type(lit.typ), typed_ir::ExprKind::Literal(_) => todo!(),
// we can not see beyond this expression right now // we can not see beyond this expression right now
typed_ir::ExprKind::Path(_) => expr.clone(), typed_ir::ExprKind::Path(_) => expr.clone(),
typed_ir::ExprKind::Call { typed_ir::ExprKind::Call {
@ -379,35 +357,6 @@ impl Context {
w: &mut dyn std::fmt::Write, w: &mut dyn std::fmt::Write,
block: &typed_ir::Block, block: &typed_ir::Block,
) -> std::fmt::Result { ) -> std::fmt::Result {
let callsig = self.callables.get(block.signature);
{
// TODO: ugly copy paste job
let args = callsig
.args
.iter()
.map(|(name, typ)| {
let mut out = String::new();
self.types.pretty_type(&mut out, *typ)?;
Ok(out)
})
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
let genargs = callsig
.genargs
.iter()
.map(|(name, typ)| {
let mut type_str = String::new();
self.types.pretty_type(&mut type_str, *typ)?;
Ok(type_str)
})
.collect::<Result<Vec<String>, std::fmt::Error>>()?;
writeln!(
w,
"block {}<{}>({})",
callsig.name(),
genargs.join(", "),
args.join(", ")
)?;
}
for sig in &block.signals { for sig in &block.signals {
let mut typ_pretty = String::new(); let mut typ_pretty = String::new();
self.types.pretty_type(&mut typ_pretty, sig.typ)?; self.types.pretty_type(&mut typ_pretty, sig.typ)?;
@ -423,11 +372,7 @@ impl Context {
expr: &typed_ir::Expr, expr: &typed_ir::Expr,
) -> std::fmt::Result { ) -> std::fmt::Result {
let expr_pretty = match &expr.kind { let expr_pretty = match &expr.kind {
typed_ir::ExprKind::Literal(lit) => { typed_ir::ExprKind::Literal(_) => todo!(),
let mut lit_str = String::new();
self.types.pretty_value(&mut lit_str, lit)?;
lit_str
}
typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0), typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0),
typed_ir::ExprKind::Call { typed_ir::ExprKind::Call {
called, called,

View File

@ -3,7 +3,6 @@ use super::types::{Type, TypingContext};
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)] #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)]
pub struct CallableId(pub usize); pub struct CallableId(pub usize);
#[derive(Debug)]
pub struct Callable { pub struct Callable {
pub name: String, pub name: String,
pub args: Vec<(Option<String>, Type)>, pub args: Vec<(Option<String>, Type)>,

View File

@ -48,7 +48,6 @@ pub struct Signal {
/// A block of HDL code, e.g. comb block /// A block of HDL code, e.g. comb block
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Block { pub struct Block {
pub signature: CallableId,
pub signals: Vec<Signal>, pub signals: Vec<Signal>,
pub expr: Expr, pub expr: Expr,
} }

View File

@ -43,7 +43,7 @@ pub struct FnSig {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ElabData { pub struct ElabData {
pub typ: Type, typ: Type,
value: ElabValue, value: ElabValue,
} }

View File

@ -60,8 +60,7 @@ fn main() {
} }
let mut frontendcontext = crate::frontend::Context::new(); let mut frontendcontext = crate::frontend::Context::new();
let typed = frontendcontext.type_module(res.1); let typed = frontendcontext.type_module(res.1);
if let Ok(module) = typed { if let Ok(block) = typed {
for block in module.blocks {
if opt.debug { if opt.debug {
let mut pretty_block = String::new(); let mut pretty_block = String::new();
frontendcontext frontendcontext
@ -77,9 +76,6 @@ fn main() {
.unwrap(); .unwrap();
println!("{}", &pretty_block); println!("{}", &pretty_block);
} }
}
// TODO: be able to determine modules that are fully parameterized
/*
let lowered = frontend::lowering::lower_block(&mut frontendcontext, typed_inferred); let lowered = frontend::lowering::lower_block(&mut frontendcontext, typed_inferred);
match lowered { match lowered {
Ok(res) => { Ok(res) => {
@ -91,9 +87,6 @@ fn main() {
} }
Err(err) => eprintln!("{:#?}", err), Err(err) => eprintln!("{:#?}", err),
} }
*/
} else {
eprintln!("{:#?}", typed);
} }
} }
} }