-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanycore.expc
637 lines (522 loc) · 17.2 KB
/
manycore.expc
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
haskell {
(>>>) :: Bits a => a -> Int -> a
(>>>) = shiftR
(<<<) :: Bits a => a -> Int -> a
(<<<) = shiftL
type Int8 = Unsigned 8
type PC = Unsigned 5
type InstructionWord = Unsigned 8
type RegID = Unsigned 2
type Immediate = Unsigned 5
data Instruction
= ReadFIFO RegID
| WriteFIFO RegID
| Add RegID RegID RegID
| Move RegID RegID
| Branch RegID RegID
| LoadImm RegID Immediate
deriving (Show, Generic, NFDataX, BitPack)
nop = Move 0 0
data FIFOCommand
= FIFO_Write Int8
| FIFO_Read
| FIFO_Nothing
deriving (Show, Generic, NFDataX, BitPack)
type ReadRegs = (RegID, RegID)
type WriteReg = Maybe (Int8, RegID)
type RegisterFile = Vec 3 Int8
decode :: InstructionWord -> Instruction
decode word = if (bit 7)
then LoadImm immreg imm
else if not (bit 6)
then Add reg45 reg23 reg01
else if (bit 5)
then if bit 4
then WriteFIFO reg23
else ReadFIFO reg23
else if bit 4
then Branch reg23 reg01
else Move reg23 reg01
where
bit = testBit word
-- the .&. is probably unnecessary due to the resize
imm = resize $ word .&. 0b11111
immreg = resize $ (word >>> 5) .&. 0b11
reg01 = resize $ word .&. 0b11
reg23 = resize $ (word >>> 2) .&. 0b11
reg45 = resize $ (word >>> 4) .&. 0b11
encode :: Instruction -> InstructionWord
encode instr = case instr of
ReadFIFO id ->
0b0110_0000 .|. (resize id <<< 2)
WriteFIFO id ->
0b0111_0000 .|. (resize id <<< 2)
Add left right dest ->
0b0000_0000 .|. (resize left <<< 4) .|. (resize right <<< 2) .|. (resize dest)
Move from to ->
0b0100_0000 .|. (resize from <<< 2) .|. (resize to)
Branch cond addr ->
0b0101_0000 .|. (resize cond <<< 2) .|. (resize addr)
LoadImm reg imm ->
0b1000_0000 .|. (resize reg <<< 5) .|. (resize imm)
empty_regs :: RegisterFile
empty_regs = 0:>0:>0:>Nil
type Program = Vec 32 InstructionWord
test_router_inp :: [(Bool, FIFOCommand)]
test_router_inp = [
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 13),
(True, FIFO_Write 21),
(True, FIFO_Nothing),
(True, FIFO_Write 7),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 59),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 3),
(True, FIFO_Write 3),
(True, FIFO_Write 3),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 19),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 17),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 1),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Write 0),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing),
(True, FIFO_Nothing)
] L.++ (L.take 30 $ L.repeat (True, FIFO_Nothing))
default_prog :: Program
default_prog = map encode $ program ++ repeat (nop)
where
program =
(LoadImm 1 1):> -- 0 Load non-zero value in reg1 to avoid jumping
(LoadImm 3 7):> -- 1 Set jump addr to write sequence
(ReadFIFO 1):> -- 2 read from fifo
(Branch 1 3):> -- 3 if we receive zero, jump to write sequence
(Add 1 2 2):> -- 4 otherwise, add input to sum reg
(LoadImm 3 1):> -- 5 Set jump addr to start of program
(Branch 0 3):> -- 6 Always jump to address 1, i.e. read again
(LoadImm 3 31):> -- 7 Set destination to (4, 5)
(LoadImm 1 31):> -- 8 We need this convoluted way, since (4, 5) is 69
(Add 1 3 3):> -- 9 as an encoded value, which does not fit in 5 bits imm_values...
(LoadImm 1 7):> -- 10 31 + 31 + 7 = 69, probably better to use the 5th loadimm bit for
(Add 1 3 3):> -- 11 load upper vs load lower, but meh
(WriteFIFO 3):> -- 12 write destination
(WriteFIFO 2):> -- 13 write sum value
(LoadImm 3 15):> -- 14 set jump addr to end program
(Branch 0 3):> -- 15 End program, infinite loop
Nil
writes :: FIFOCommand -> Maybe Int8
writes (FIFO_Write a) = Just a
writes _ = Nothing
type DataQueue = Vec 8 Int8
type DataPtr = Unsigned 3
empty_queue :: DataQueue
empty_queue = 1:>2:>3:>4:>5:>6:>7:>8:>Nil
type PacketQueue = Vec 4 Packet
data Packet = Packet Location Int8
deriving (Show, Generic, NFDataX, BitPack)
type Location = (Unsigned 4, Unsigned 4)
empty_packet_queue :: PacketQueue
empty_packet_queue = zr:>zr:>zr:>zr:>Nil
where
zr = Packet (0, 0) 0
empty_packet :: Packet
empty_packet = Packet (0, 0) 0
empty_loc :: Location
empty_loc = (0, 0)
nothing = Nothing
data PacketControlState = Idle | GotLoc Location | Ready Location Int8
deriving (Show, Generic, NFDataX, BitPack)
int2loc :: Int8 -> Location
int2loc v = (resize $ v >>> 4, resize v)
loc2int :: Location -> Int8
loc2int (x, y) = resize x <<< 4 .|. resize y
data SerializerState = SerIdle | SerSendLoc Packet | SerSendVal Packet
deriving (Show, Generic, NFDataX, BitPack)
data Direction = North | East | South | West | Core
deriving (Show, Generic, NFDataX, BitPack, Eq)
router_test_data :: [(Maybe Packet, Maybe Int8, Maybe Int8, Maybe Int8, Maybe Int8)]
router_test_data = [
(Nothing, Just 17, Nothing, Nothing, Nothing),
(Nothing, Just 80, Nothing, Nothing, Nothing),
(Nothing, Nothing, Nothing, Just 0b1_0010, Nothing),
(Nothing, Nothing, Nothing, Just 79, Nothing),
(Nothing, Just 0b0001_0000, Just 0b0010_0001, Nothing, Nothing),
(Nothing, Just 13, Just 14, Nothing, Nothing),
(Nothing, Just 0b0010_0001, Nothing, Just 18, Nothing),
(Nothing, Just 55, Nothing, Just 78, Nothing),
(Nothing, Nothing, Nothing, Nothing, Nothing),
(Nothing, Nothing, Nothing, Nothing, Nothing),
(Nothing, Nothing, Nothing, Nothing, Nothing),
(Nothing, Nothing, Nothing, Nothing, Nothing),
(Nothing, Nothing, Nothing, Nothing, Nothing)
]
to_br_data :: [(Maybe Int8, Maybe Int8)]
to_br_data = [
(Just 0b000_0001, Just 0b0011_0001),
(Just 59, Just 13),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing),
(Nothing, Nothing)
]
mc_input :: [Maybe Int8]
mc_input = [
Just 17, Just 5,
Nothing, Nothing,
Just 18, Just 13,
Nothing, Nothing,
Nothing, Nothing,
Nothing, Nothing,
Just 17, Just 5,
Just 18, Just 13,
Nothing, Nothing,
Just 17, Just 0,
Just 18, Just 0
] L.++ (L.take 1000 $ L.repeat Nothing)
}
component datapath() {
input instr_word : InstructionWord
input reg_a : Int8
input reg_b : Int8
input fifo_val : Maybe Int8
state delay = 0 : InstructionWord
state pc = 0 : PC
output read_ids : ReadRegs
output update_regs : WriteReg
output fifo_cmd : FIFOCommand
output pc_out : PC
-- 5x4
instruction = decode instr_word
delay' = instr_word
read_ids = case instruction of
(ReadFIFO _) -> (0, 0)
(WriteFIFO reg) -> (0, reg)
(Add left right _) -> (left, right)
(Move from _) -> (from, 0)
(Branch cond addr) -> (cond, addr)
(LoadImm _ _) -> (0, 0)
delayed_instr = decode delay
update_regs = case instruction of
(ReadFIFO dest) -> case fifo_val of
Just v -> Just (v, dest)
Nothing -> Nothing
(WriteFIFO _) -> Nothing
(Add _ _ dest) -> Just (reg_a + reg_b, dest)
(Move _ to) -> Just (reg_a, to)
(Branch _ _) -> Nothing
(LoadImm reg imm) -> Just (resize imm, reg)
update_pc = case instruction of
(Branch _ _) -> if reg_a == 0
then Just $ resize reg_b
else Nothing
(ReadFIFO _) -> case fifo_val of
Nothing -> Just pc
fifo_cmd = case instruction of
(ReadFIFO _) -> FIFO_Read
(WriteFIFO _) -> FIFO_Write reg_b
_ -> FIFO_Nothing
pc' = case instruction of
(Branch _ _) -> if reg_a == 0
then resize reg_b
else pc + 1
(ReadFIFO _) -> case fifo_val of
Nothing -> pc -- block on no value
_ -> pc + 1
_ -> pc + 1
pc_out = pc
}
component registers() {
input read_ids : ReadRegs
input write : WriteReg
state regs = empty_regs : RegisterFile
output reg_a : Int8
output reg_b : Int8
-- 4x4
regs' =
case write of
Just (value, regid) -> if regid == 0
then regs
else replace (regid - 1) value regs
Nothing -> regs
(reg_a_id, reg_b_id) = read_ids
reg_a = if reg_a_id == 0
then 0
else regs !! (reg_a_id - 1)
reg_b = if reg_b_id == 0
then 0
else regs !! (reg_b_id - 1)
}
component prog_mem() {
input pc : PC
state program = default_prog : Program
output instr : InstructionWord
-- voor default prog, moeilijk weinig: like 3x3, maar wsch in general een stuk meer nodig
instr = program !! pc
program' = program
}
component queue_controller() {
input proc_cmd : FIFOCommand
input route_cmd : FIFOCommand
input router_read : Bool
input outgoing_empty : Bool
input outgoing_value : Packet
output outgoing_read : Bool
output read_packet : Maybe Packet
input incoming_value : Int8
input incoming_empty : Bool
output incoming_read : Bool
output incoming_write : Bool
output incoming_datain : Int8
output read_value : Maybe Int8
-- 11 LUTs, ze lagen wat verspreid, niet veel iig.
incoming_read = case proc_cmd of
FIFO_Read -> True && (not incoming_empty)
_ -> False
incoming_write = case route_cmd of
FIFO_Write _ -> True
_ -> False
incoming_datain = case route_cmd of
FIFO_Write v -> v
_ -> 0
outgoing_read = router_read && (not outgoing_empty)
read_value = if incoming_read
then Just incoming_value
else Nothing
read_packet = if outgoing_read
then Just outgoing_value
else Nothing
}
component in_fifo() {
input datain : Int8
input write : Bool
input read : Bool
state rpntr = 0 : Unsigned 4
state wpntr = 0 : Unsigned 4
state elms = empty_queue : DataQueue
output dataout : Int8
output empty : Bool
-- output full : Bool
-- 6x5, at least
-- https://github.com/clash-lang/clash-compiler/blob/master/examples/Fifo.hs
wpntr' | write = wpntr + 1
| otherwise = wpntr
rpntr' | read = rpntr + 1
| otherwise = rpntr
mask = resize (maxBound :: Unsigned 3)
wind = wpntr .&. mask
rind = rpntr .&. mask
elms' | write = replace wind datain elms
| otherwise = elms
n = 3
empty = wpntr == rpntr
full = (testBit wpntr n) /= (testBit rpntr n) &&
(wind == rind)
dataout = elms !! rind
}
component packet_queue() {
input datain : Maybe Packet
input read : Bool
state rpntr = 0 : Unsigned 3
state wpntr = 0 : Unsigned 3
state elms = empty_packet_queue : PacketQueue
output dataout : Packet
output empty : Bool
-- output full : Bool
-- 5x5
write = case datain of
Just _ -> True
Nothing -> False
-- https://github.com/clash-lang/clash-compiler/blob/master/examples/Fifo.hs
wpntr' | write = wpntr + 1
| otherwise = wpntr
rpntr' | read = rpntr + 1
| otherwise = rpntr
mask = resize (maxBound :: Unsigned 2)
wind = wpntr .&. mask
rind = rpntr .&. mask
elms' | write = case datain of
(Just v) -> replace wind v elms
| otherwise = elms
n = 3
empty = wpntr == rpntr
full = (testBit wpntr n) /= (testBit rpntr n) &&
(wind == rind)
dataout = elms !! rind
}
component packet_control() {
input proc_cmd : FIFOCommand
state ctrl_state = Idle : PacketControlState
output packet : Maybe Packet
-- 3x3 is ruim
ctrl_state' = case ctrl_state of
Idle -> case proc_cmd of
(FIFO_Write v) -> GotLoc (int2loc v)
_ -> Idle
GotLoc l -> case proc_cmd of
(FIFO_Write v) -> Ready l v
_ -> GotLoc l
Ready _ _ -> Idle
write = case ctrl_state of
Ready _ _ -> True
_ -> False
packet = case ctrl_state of
Ready l v -> Just $ Packet l v
_ -> Nothing
}
component pkt_ser() {
input empty_send_queue : Bool
input packet : Packet
state ser_state = SerIdle : SerializerState
state send_loc = True : Bool
output value : Maybe Int8
output read_from_send_queue : Bool
send_loc' = not send_loc
ser_state' = case ser_state of
SerIdle -> if read_from_send_queue
then SerSendLoc packet
else SerIdle
SerSendLoc p -> SerSendVal p
SerSendVal p -> if read_from_send_queue
then SerSendLoc packet
else SerIdle
value = case ser_state' of
SerIdle -> Nothing
SerSendLoc (Packet loc _) -> Just $ loc2int loc
SerSendVal (Packet _ val) -> Just val
read_from_send_queue = send_loc && not empty_send_queue
}
component pkt_des() {
input value : Maybe Int8
state recv_loc = True : Bool
state prev_value = Nothing : Maybe Int8
output packet : Maybe Packet
recv_loc' = not recv_loc
prev_value' = value
packet = if recv_loc
then Nothing
else case value of
-- if this fromjust triggers, input data is out of sync with the des
(Just value) -> case prev_value of
(Just loc) -> Just $ Packet (int2loc loc) (value)
Nothing -> Nothing
}
component direction_decider() {
input my_x : Unsigned 4
input my_y : Unsigned 4
input from_north : Maybe Packet
input from_east : Maybe Packet
input from_south : Maybe Packet
input from_west : Maybe Packet
input from_core : Maybe Packet
state read_timer = 0 : Unsigned 2
output to_north : Maybe Packet
output to_east : Maybe Packet
output to_south : Maybe Packet
output to_west : Maybe Packet
output to_proc : FIFOCommand
output ready : Bool
-- expects to be have my_x and my_y driven by a constant signal.
to_north = pick_packet North
to_east = pick_packet East
to_south = pick_packet South
to_west = pick_packet West
to_proc = to_fifo $ pick_packet Core
ready = read_timer == 0
read_timer' = read_timer + 1
dest (Just (Packet (x, y) _))
| x > my_x = Just East
| x < my_x = Just West
| y > my_y = Just South
| y < my_y = Just North
| x == my_x && y == my_y = Just Core
dest Nothing = Nothing
-- silently drops packets :(
pick_packet dir = if dest from_core == Just dir
then from_core
else if dest from_north == Just dir
then from_north
else if dest from_east == Just dir
then from_east
else if dest from_south == Just dir
then from_south
else if dest from_west == Just dir
then from_west
else Nothing
to_fifo pkt = case pkt of
Just (Packet _ v) -> FIFO_Write v
Nothing -> FIFO_Nothing
}
component cap() {
input out : Maybe Int8
output inp : Maybe Int8
inp = Nothing
}