use std::cell::RefCell;
use std::rc::Rc;
use cmtrs::*;
use gen_ir::ModuleMold;
struct Counter {
module: cmtrs::gen_ir::ModuleMold,
ctx_view: Box<dyn InstanceView>,
pub t: Type,
}
struct CounterItfc {
module: cmtrs::gen_ir::ModuleMold,
params: CounterParams,
}
struct CounterIO {
pub set_val: Var,
pub count: Var,
}
impl ItfcIO for CounterIO {}
struct CounterParams {
pub t: Type,
}
impl ItfcParams for CounterParams {
fn id_str(&self) -> String {
format!("{}", self.t.name())
}
}
impl Itfc for CounterItfc {
type IO = CounterIO;
type Params = CounterParams;
type Inst = Counter;
fn as_context(params: CounterParams, span: Option<MySpan>) -> Self {
Self {
module: cmtrs::gen_ir::ModuleMold::new(
format!("Counter_{}", params.id_str()),
span,
),
params,
}
}
fn module_mut(&mut self) -> &mut cmtrs::gen_ir::ModuleMold {
&mut self.module
}
fn module(&self) -> &cmtrs::gen_ir::ModuleMold {
&self.module
}
fn methods(&self) -> &'static [&'static str] {
&["read", "set"]
}
fn params(&self) -> &Self::Params {
&self.params
}
fn io(__cmt_gen: Rc<RefCell<Option<Self>>>) -> CounterIO {
let set_val = input!("set_val".to_string(), {
let t = __cmt_gen.borrow().as_ref().unwrap().params().t.clone();
t
});
let count = output!("count".to_string(), {
let t = __cmt_gen.borrow().as_ref().unwrap().params().t.clone();
t
});
CounterIO { set_val, count }
}
fn into_inner(self) -> (gen_ir::ModuleMold, Self::Params) {
(self.module, self.params)
}
}
impl Instance for Counter {
type Params = CounterParams;
fn type_name() -> &'static str {
&"Counter"
}
fn from_itfc(module: gen_ir::ModuleMold, params: Self::Params) -> Self {
Self {
module,
ctx_view: Box::new(InstanceViewStruct::<CounterItfc>::new()),
t: params.t,
}
}
fn as_instance(&mut self, views: &mut InstanceViewIter) {
self.ctx_view = views.next().unwrap();
}
fn as_nested_itfc_io(
&self,
name: String,
views: &mut InstanceViewIter,
) -> Self {
let instance = Self {
module: gen_ir::ModuleMold::clone_with_new_name(&self.module, name),
ctx_view: views.next().unwrap(),
t: self.t.clone(),
};
instance
}
fn make_nested_methods(
&self,
name: String,
__cmt_gen: ContextItfc<impl Itfc>,
) {
let set_val = input!(format!("{}_set_val", name), self.t.clone());
let count = output!(format!("{}_count", name), self.t.clone());
named_method! {format!("{}_read", name); () -> (count) {self.read()}};
named_method! {format!("{}_set", name); (set_val) {self.set(set_val)}};
}
fn module_mut(&mut self) -> &mut cmtrs::gen_ir::ModuleMold {
&mut self.module
}
fn module(&self) -> &cmtrs::gen_ir::ModuleMold {
&self.module
}
fn nested_names(&self) -> Vec<String> {
vec![]
}
fn invoke(&self, name: &str, args: &[&cmtrs::Var], num_res: usize, span: Option<MySpan>) -> Vars {
Vars(self.ctx_view.invoke(
name.to_string(),
args.iter().map(|x| x.ast()).collect(),
num_res,
span,
))
}
}
impl Counter {
pub fn read(&self) -> Var {
self
.ctx_view
.invoke("read".to_string(), Vec::new(), 1, None)
.into_iter()
.next()
.unwrap()
}
pub fn set(&self, a: impl CmtAST) {
self.ctx_view.invoke("set".to_string(), vec![a.ast()], 0, None);
}
}
impl ToIOMacro for Counter {
type Output = Self;
fn to_io_macro(self) -> Self::Output {
self
}
}
fn make_counter(lim: usize, ty: &Type) -> Counter {
let __cmt_gen = Rc::new(RefCell::new(Some(CounterItfc::as_context(
CounterParams { t: ty.clone() },
None,
))));
let io = Itfc::io(__cmt_gen.clone());
let reg_i = Itfc::instantiate(&__cmt_gen, "reg_i".to_string(), stl::reg(ty));
Itfc::begin_rule(
&__cmt_gen,
false,
false,
"inc".to_string(),
cmtir::RuleSignature::Always {
inputs: vec![],
outputs: vec![],
},
cmtir::RuleTiming::SingleCycle,
None,
None,
None,
);
Itfc::rule_guard(&__cmt_gen);
Itfc::if_(&__cmt_gen, None);
Itfc::statement(&__cmt_gen, reg_i.read().lt(literal(lim as i32, ty)));
Itfc::sep(&__cmt_gen);
Itfc::block(&__cmt_gen, None);
let x = Itfc::add_var(&__cmt_gen, Some("x".to_string()));
Itfc::assign(&__cmt_gen, &x, reg_i.read() + literal(1, ty), None);
reg_i.write(&x);
Itfc::statement(&__cmt_gen, Itfc::end(&__cmt_gen));
Itfc::sep(&__cmt_gen);
reg_i.write(literal(0, ty));
Itfc::statement(&__cmt_gen, Itfc::end(&__cmt_gen));
let _inc = Itfc::end_rule(&__cmt_gen);
Itfc::begin_rule(
&__cmt_gen,
false,
false,
"set".to_string(),
cmtir::RuleSignature::Method {
inputs: vec![io.set_val.value_id().unwrap()],
outputs: vec![],
side_effect: Some(true),
},
cmtir::RuleTiming::SingleCycle,
None,
None,
None,
);
Itfc::rule_guard(&__cmt_gen);
reg_i.write(io.set_val);
let set = Itfc::end_rule(&__cmt_gen);
Itfc::begin_rule(
&__cmt_gen,
false,
false,
"read".to_string(),
cmtir::RuleSignature::Method {
inputs: vec![],
outputs: vec![io.count.value_id().unwrap()],
side_effect: Some(false),
},
cmtir::RuleTiming::SingleCycle,
None,
None,
None,
);
Itfc::rule_guard(&__cmt_gen);
Itfc::statement(&__cmt_gen, reg_i.read().ast());
let read = Itfc::end_rule(&__cmt_gen);
Itfc::method_rel(&__cmt_gen, MethodRel::C, &[set], &[set]);
Itfc::dump(__cmt_gen)
}
fn main() {
let ty = Type::UInt(4);
let counter = make_counter(10, &ty);
let circuit = counter.to_cmtir();
println!("{}", circuit.ir_dump());
}