Compare commits
No commits in common. "68be74d032b74cb3de03e898cdac2055a41bf109" and "f03c777e285ac0c69bd296238f2234766c8cbf2a" have entirely different histories.
68be74d032
...
f03c777e28
129
src/frontend.rs
129
src/frontend.rs
|
@ -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,
|
||||||
|
|
|
@ -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)>,
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue