-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsequential.go
136 lines (122 loc) · 2.75 KB
/
sequential.go
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import "sync"
// intermediate values are reevaluated upon each input change
// sequential chips consist of DFFs in between combinational chip layers
type SequentialChip interface {
Run(clock chan bit)
}
func Run(clock chan bit, chips ...SequentialChip) {
clocks := fanout(clock, len(chips))
for i, chip := range chips {
go chip.Run(clocks[i])
}
}
// primitive, uses builtin go
type DFF struct {
In chan bit
Out chan bit
}
func NewDFF(in, out chan bit) DFF {
return DFF{
In: in,
Out: out,
}
}
func (c DFF) Run(clock chan bit) {
var in bit
var lock sync.Mutex
go func() {
for {
b := <-c.In
lock.Lock()
in = b
lock.Unlock()
}
}()
// this is the builtin part
// other chips are not allowed to listen to clock directly
for {
<-clock
lock.Lock()
temp := in
lock.Unlock()
c.Out<-temp
}
}
// rest is not primitive, derives from DFF
type Bit struct {
In chan bit
Load chan bit
Out chan bit
dff DFF
}
func NewBit(in, load, out chan bit) Bit {
dffin := make(chan bit, 1)
dffout := make(chan bit, 1)
dff := NewDFF(dffin, dffout)
return Bit{
In: in,
Load: load,
Out: out,
dff: dff,
}
}
func (c Bit) Run(clock chan bit) {
go c.dff.Run(clock)
var in, load, outloop bit
var lock sync.Mutex
go func() {
for {
b := <-c.Load
lock.Lock()
load = b
tin, tload, toutloop := in, load, outloop
lock.Unlock()
c.dff.In<-Mux(toutloop, tin, tload)
}
}()
for {
select {
case b := <-c.In:
lock.Lock()
in = b
c.dff.In<-Mux(outloop, in, load)
lock.Unlock()
case b := <-c.dff.Out:
lock.Lock()
outloop = b
c.dff.In<-Mux(outloop, in, load)
lock.Unlock()
c.Out <- b
}
// eval the combinational part at the end of each case
// since each of the above 3 is an input
}
}
type Register struct {
In chan [16]bit
Load chan bit
Out chan [16]bit
bits []SequentialChip
}
func NewRegister(in, out chan [16]bit, load chan bit) Register {
loads := fanout(load, 16)
ins := chanBitArray16()
split16(in, ins)
outs := chanBitArray16()
gather16(outs, out)
bits := make([]SequentialChip, 16)
for i:=0; i<16; i++ {
bits[i] = NewBit(ins[i], loads[i], outs[i])
}
return Register{
In: in,
Out: out,
Load: load,
bits: bits,
}
}
func (c Register) Run(clock chan bit) {
go Run(clock, c.bits...)
}
// TODO: counter