|
|
|
@ -58,8 +58,40 @@ pub struct Callable {
|
|
|
|
|
pub instantiate: Box<dyn Fn(&str, &[rtlil::SigSpec], &rtlil::SigSpec) -> rtlil::Cell>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Context {
|
|
|
|
|
/// map callable name to callable
|
|
|
|
|
callables: BTreeMap<String, Callable>,
|
|
|
|
|
/// map signal name to Signal
|
|
|
|
|
signals: BTreeMap<String, Signal>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
|
fn get_signal(&self, signame: &str) -> Option<&Signal> {
|
|
|
|
|
self.signals.get(signame)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn try_get_signal(&self, signame: &str) -> Result<&Signal, CompileError> {
|
|
|
|
|
self.get_signal(signame)
|
|
|
|
|
.ok_or(CompileError::new(CompileErrorKind::UndefinedReference(signame.to_owned())))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn lower_process_statement(
|
|
|
|
@ -199,7 +231,10 @@ fn lower_expression(
|
|
|
|
|
) -> Result<rtlil::SigSpec, CompileError> {
|
|
|
|
|
let expr = desugar_expression(expr.clone());
|
|
|
|
|
match expr {
|
|
|
|
|
parser::Expression::Ident(ident) => Ok(rtlil::SigSpec::Wire(make_pubid(ident))),
|
|
|
|
|
parser::Expression::Ident(ident) => {
|
|
|
|
|
let signal = ctx.try_get_signal(ident)?;
|
|
|
|
|
Ok(signal.sigspec())
|
|
|
|
|
},
|
|
|
|
|
parser::Expression::Call(call) => {
|
|
|
|
|
let args_resolved = call
|
|
|
|
|
.args
|
|
|
|
@ -246,7 +281,7 @@ fn lower_assignment(
|
|
|
|
|
module: &mut rtlil::Module,
|
|
|
|
|
assignment: parser::Assign,
|
|
|
|
|
) -> Result<(), CompileError> {
|
|
|
|
|
let target_id = rtlil::SigSpec::Wire(make_pubid(assignment.lhs));
|
|
|
|
|
let target_id = ctx.try_get_signal(assignment.lhs)?.sigspec();
|
|
|
|
|
let return_wire = lower_expression(ctx, module, &assignment.expr)?;
|
|
|
|
|
module.add_connection(&target_id, &return_wire);
|
|
|
|
|
Ok(())
|
|
|
|
@ -255,20 +290,28 @@ fn lower_assignment(
|
|
|
|
|
pub fn lower_module(pa_module: parser::Module) -> Result<String, CompileError> {
|
|
|
|
|
let mut writer = rtlil::ILWriter::new();
|
|
|
|
|
let mut ir_module = rtlil::Module::new(make_pubid(pa_module.name));
|
|
|
|
|
let context = Context {
|
|
|
|
|
let mut context = Context {
|
|
|
|
|
callables: get_builtins()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|clb| (clb.name.to_owned(), clb))
|
|
|
|
|
.collect(),
|
|
|
|
|
signals: BTreeMap::new(),
|
|
|
|
|
};
|
|
|
|
|
writer.write_line("autoidx 1");
|
|
|
|
|
for (idx, port) in pa_module.ports.iter().enumerate() {
|
|
|
|
|
let sig = Signal {
|
|
|
|
|
name: port.net.name.to_owned(),
|
|
|
|
|
il_id: make_pubid(port.net.name),
|
|
|
|
|
typ: Type::Wire(GenericParam::Solved(port.net.width.unwrap_or(1) as u32))
|
|
|
|
|
};
|
|
|
|
|
let sig = context.signals.entry(port.net.name.to_owned()).or_insert(sig);
|
|
|
|
|
|
|
|
|
|
let dir_option = match port.direction {
|
|
|
|
|
parser::PortDirection::Input => rtlil::PortOption::Input(idx as i32 + 1),
|
|
|
|
|
parser::PortDirection::Output => rtlil::PortOption::Output(idx as i32 + 1),
|
|
|
|
|
};
|
|
|
|
|
let wire = rtlil::Wire::new(
|
|
|
|
|
make_pubid(port.net.name),
|
|
|
|
|
sig.il_id.to_owned(),
|
|
|
|
|
port.net.width.unwrap_or(1) as u32,
|
|
|
|
|
Some(dir_option),
|
|
|
|
|
);
|
|
|
|
|