1"""
2========================================================================
3queues.py
4========================================================================
5This file contains cycle-level queues.
6
7Author : Shunning Jiang, Yanghui Ou
8Date   : Mar 10, 2018
9"""
10
11from collections import deque
12
13from pymtl3 import *
14
15#-------------------------------------------------------------------------
16# PipeQueueCL
17#-------------------------------------------------------------------------
18
19class PipeQueueCL( Component ):
20
21  def construct( s, num_entries=1 ):
22    s.queue = deque( maxlen=num_entries )
23
24    s.add_constraints(
25      M( s.peek   ) < M( s.enq  ),
26      M( s.deq    ) < M( s.enq  )
27    )
28
29  @non_blocking( lambda s: len( s.queue ) < s.queue.maxlen )
30  def enq( s, msg ):
31    s.queue.appendleft( msg )
32
33  @non_blocking( lambda s: len( s.queue ) > 0 )
34  def deq( s ):
35    return s.queue.pop()
36
37  @non_blocking( lambda s: len( s.queue ) > 0 )
38  def peek( s ):
39    return s.queue[-1]
40
41  def line_trace( s ):
42    return "{}( ){}".format( s.enq, s.deq )
43
44#-------------------------------------------------------------------------
45# BypassQueueCL
46#-------------------------------------------------------------------------
47
48class BypassQueueCL( Component ):
49
50  def construct( s, num_entries=1 ):
51    s.queue = deque( maxlen=num_entries )
52
53    s.add_constraints(
54      M( s.enq    ) < M( s.peek    ),
55      M( s.enq    ) < M( s.deq     ),
56    )
57
58  @non_blocking( lambda s: len( s.queue ) < s.queue.maxlen )
59  def enq( s, msg ):
60    s.queue.appendleft( msg )
61
62  @non_blocking( lambda s: len( s.queue ) > 0 )
63  def deq( s ):
64    return s.queue.pop()
65
66  @non_blocking( lambda s: len( s.queue ) > 0 )
67  def peek( s ):
68    return s.queue[-1]
69
70  def line_trace( s ):
71    return "{}( ){}".format( s.enq, s.deq )
72
73#-------------------------------------------------------------------------
74# NormalQueueCL
75#-------------------------------------------------------------------------
76
77class NormalQueueCL( Component ):
78
79  def construct( s, num_entries=1 ):
80    s.queue = deque( maxlen=num_entries )
81    s.enq_rdy = False
82    s.deq_rdy = False
83
84    @update
85    def up_pulse():
86      s.enq_rdy = len( s.queue ) < s.queue.maxlen
87      s.deq_rdy = len( s.queue ) > 0
88
89    s.add_constraints(
90      U( up_pulse ) < M( s.enq.rdy ),
91      U( up_pulse ) < M( s.deq.rdy ),
92      M( s.peek   ) < M( s.deq.rdy  ),
93      M( s.peek   ) < M( s.enq.rdy  )
94    )
95
96  @non_blocking( lambda s: s.enq_rdy )
97  def enq( s, msg ):
98    s.queue.appendleft( msg )
99
100  @non_blocking( lambda s: s.deq_rdy )
101  def deq( s ):
102    return s.queue.pop()
103
104  @non_blocking( lambda s: len( s.queue ) > 0 )
105  def peek( s ):
106    return s.queue[-1]
107
108  def line_trace( s ):
109    return "{}( ){}".format( s.enq, s.deq )
110