blob: c7346dcec596270ce260cea4da7e58704fc8718b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package chisel3.core
/**
* A Binder is a function from UnboundBinding to some Binding.
*
* These are used exclusively by Binding.bind and sealed in order to keep
* all of them in one place. There are two flavors of Binders:
* Non-terminal (returns another UnboundBinding): These are used to reformat an
* UnboundBinding (like setting direction) before it is terminally bound.
* Terminal (returns any other Binding): Due to the nature of Bindings, once a
* Data is bound to anything but an UnboundBinding, it is forever locked to
* being that type (as it now represents something in the hardware graph).
*
* Note that some Binders require extra arguments to be constructed, like the
* enclosing Module.
*/
sealed trait Binder[Out <: Binding] extends Function1[UnboundBinding, Out]{
def apply(in: UnboundBinding): Out
}
// THE NON-TERMINAL BINDERS
// These 'rebind' to another unbound node of different direction!
case object InputBinder extends Binder[UnboundBinding] {
def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Input))
}
case object OutputBinder extends Binder[UnboundBinding] {
def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Output))
}
case object FlippedBinder extends Binder[UnboundBinding] {
def apply(in: UnboundBinding) = UnboundBinding(in.direction.map(_.flip))
// TODO(twigg): flipping a None should probably be a warning/error
}
// The need for this should be transient.
case object NoDirectionBinder extends Binder[UnboundBinding] {
def apply(in: UnboundBinding) = UnboundBinding(None)
}
// THE TERMINAL BINDERS
case object LitBinder extends Binder[LitBinding] {
def apply(in: UnboundBinding) = LitBinding()
}
case class MemoryPortBinder(enclosure: Module) extends Binder[MemoryPortBinding] {
def apply(in: UnboundBinding) = MemoryPortBinding(enclosure)
}
case class OpBinder(enclosure: Module) extends Binder[OpBinding] {
def apply(in: UnboundBinding) = OpBinding(enclosure)
}
// Notice how PortBinder uses the direction of the UnboundNode
case class PortBinder(enclosure: Module) extends Binder[PortBinding] {
def apply(in: UnboundBinding) = PortBinding(enclosure, in.direction)
}
case class RegBinder(enclosure: Module) extends Binder[RegBinding] {
def apply(in: UnboundBinding) = RegBinding(enclosure)
}
case class WireBinder(enclosure: Module) extends Binder[WireBinding] {
def apply(in: UnboundBinding) = WireBinding(enclosure)
}
|