make multiple blocks in one file work
This commit is contained in:
parent
8c16a94be4
commit
68be74d032
121
src/frontend.rs
121
src/frontend.rs
|
@ -43,22 +43,9 @@ impl CompileError {
|
|||
}
|
||||
}
|
||||
|
||||
/// A user-defined signal
|
||||
pub struct Signal {
|
||||
/// 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())
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
pub blocks: Vec<typed_ir::Block>,
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
|
@ -227,20 +214,20 @@ impl Context {
|
|||
Ok(t_expr)
|
||||
}
|
||||
|
||||
fn type_comb(
|
||||
fn callable_from_block(
|
||||
&mut self,
|
||||
comb: &parser::comb::CombBlock,
|
||||
) -> Result<typed_ir::Block, CompileError> {
|
||||
let mut signals = Vec::new();
|
||||
|
||||
) -> Result<CallableId, CompileError> {
|
||||
let mut genargs = vec![];
|
||||
for (idx, tvarname) in comb.genparams.iter().enumerate() {
|
||||
let tvar = self.types.make_typevar(0, idx as u32);
|
||||
// hacky workaround for no scopes
|
||||
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() {
|
||||
let sig_id = self.ids.next();
|
||||
|
||||
let sig_typename = &port.net.typ;
|
||||
let mut sig_type = self.try_get_type(sig_typename.name.fragment())?;
|
||||
if let Some(arg) = &sig_typename.generics {
|
||||
|
@ -252,38 +239,73 @@ impl Context {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
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);
|
||||
args.push((Some(port.net.name.to_string()), sig_type));
|
||||
}
|
||||
|
||||
let ret_typename = &comb.ret.name;
|
||||
let _ret_type = self.try_get_type(ret_typename.fragment())?;
|
||||
// TODO: use ret type
|
||||
let ret_type = self.try_get_type(ret_typename.fragment())?;
|
||||
|
||||
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)?;
|
||||
|
||||
Ok(typed_ir::Block {
|
||||
signature: callable_id,
|
||||
signals,
|
||||
expr: root_expr,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn type_module(&mut self, module: parser::Module) -> Result<typed_ir::Block, CompileError> {
|
||||
pub fn type_module(&mut self, module: parser::Module) -> Result<Module, 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 {
|
||||
let block = match &item {
|
||||
parser::ModuleItem::Comb(comb) => self.type_comb(comb)?,
|
||||
parser::ModuleItem::Proc(_) => todo!("proc block"),
|
||||
parser::ModuleItem::State(_) => todo!("state block"),
|
||||
};
|
||||
return Ok(block);
|
||||
typed_module.blocks.push(block);
|
||||
}
|
||||
Err(CompileError::new(CompileErrorKind::TodoError(
|
||||
"no blocks in module".to_string(),
|
||||
)))
|
||||
Ok(typed_module)
|
||||
}
|
||||
|
||||
pub fn infer_expr_types(&mut self, expr: &typed_ir::Expr) -> typed_ir::Expr {
|
||||
|
@ -357,6 +379,35 @@ impl Context {
|
|||
w: &mut dyn std::fmt::Write,
|
||||
block: &typed_ir::Block,
|
||||
) -> 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 {
|
||||
let mut typ_pretty = String::new();
|
||||
self.types.pretty_type(&mut typ_pretty, sig.typ)?;
|
||||
|
|
|
@ -3,6 +3,7 @@ use super::types::{Type, TypingContext};
|
|||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)]
|
||||
pub struct CallableId(pub usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Callable {
|
||||
pub name: String,
|
||||
pub args: Vec<(Option<String>, Type)>,
|
||||
|
|
|
@ -48,6 +48,7 @@ pub struct Signal {
|
|||
/// A block of HDL code, e.g. comb block
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Block {
|
||||
pub signature: CallableId,
|
||||
pub signals: Vec<Signal>,
|
||||
pub expr: Expr,
|
||||
}
|
||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -60,22 +60,26 @@ fn main() {
|
|||
}
|
||||
let mut frontendcontext = crate::frontend::Context::new();
|
||||
let typed = frontendcontext.type_module(res.1);
|
||||
if let Ok(block) = typed {
|
||||
if opt.debug {
|
||||
let mut pretty_block = String::new();
|
||||
frontendcontext
|
||||
.pretty_typed_block(&mut pretty_block, &block)
|
||||
.unwrap();
|
||||
println!("{}", &pretty_block);
|
||||
}
|
||||
let typed_inferred = frontendcontext.infer_types(block);
|
||||
if opt.debug {
|
||||
let mut pretty_block = String::new();
|
||||
frontendcontext
|
||||
.pretty_typed_block(&mut pretty_block, &typed_inferred)
|
||||
.unwrap();
|
||||
println!("{}", &pretty_block);
|
||||
if let Ok(module) = typed {
|
||||
for block in module.blocks {
|
||||
if opt.debug {
|
||||
let mut pretty_block = String::new();
|
||||
frontendcontext
|
||||
.pretty_typed_block(&mut pretty_block, &block)
|
||||
.unwrap();
|
||||
println!("{}", &pretty_block);
|
||||
}
|
||||
let typed_inferred = frontendcontext.infer_types(block);
|
||||
if opt.debug {
|
||||
let mut pretty_block = String::new();
|
||||
frontendcontext
|
||||
.pretty_typed_block(&mut pretty_block, &typed_inferred)
|
||||
.unwrap();
|
||||
println!("{}", &pretty_block);
|
||||
}
|
||||
}
|
||||
// TODO: be able to determine modules that are fully parameterized
|
||||
/*
|
||||
let lowered = frontend::lowering::lower_block(&mut frontendcontext, typed_inferred);
|
||||
match lowered {
|
||||
Ok(res) => {
|
||||
|
@ -87,6 +91,9 @@ fn main() {
|
|||
}
|
||||
Err(err) => eprintln!("{:#?}", err),
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
eprintln!("{:#?}", typed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue