Description
Problem
Current design assumes uses:
fn get_id_ports(&self) -> (String, Ports) {
(
self.id.clone(),
Ports {
inputs: vec![self.a_in.clone(), self.b_in.clone()],
out_type: OutputType::Combinatorial,
outputs: vec![Output::Function; 2], # <- in this case 2 outputs
},
)
}
The intuition behind is that each component may have both clocked (synchronous) and combinatorial outputs. But the way the the simulator is designed (and the topological order established) is solely looking at the out_type
and not the individual outputs
.
So here we have a design choice to make:
- A) keep it as is
- B) change it to
usize
If A) we should perhaps split evaluate
into two functions. One evaluate_clock
(which happens when the model is clocked), and one evaluate_combinatorial
, which is the current evaluate
. In that case out_type
becomes redundant and should be removed.
If B), not much need to be changed besides the type. (The Output
type could be removed.)
This is something for us to discuss.
A) is clearly more powerful, but could be more error prone to use. Also the clear distinction between synchronous and combinatorial logic is to some extent diffused. If we want to support hierarchical designs A) is a must, its not realistic to think of sub-systems as being either completely synchronous or completely combinatorial I believe. Also A) more closely replicates the behavior of components in HDLs like Verilog/VHDL.
B) on the other hand simplifes SyncRim
and leaves us with a very clear and concise component model.
So think about the problem and leave comments below to why you would prefer to go one way or the other.