-
Notifications
You must be signed in to change notification settings - Fork 49
Home
Shunning Jiang edited this page May 3, 2017
·
5 revisions
class GcdUnitCS( PortBundle ):
def init( s ): s.a_mux_sel = ValuePort(int) s.a_reg_en = ValuePort(int) s.b_mux_sel = ValuePort(int) s.b_reg_en = ValuePort(int) s.is_b_zero = ValuePort(int) s.is_a_lt_b = ValuePort(int)
class GcdUnitDpath( Updates ):
def init( s ):
s.req_msg_a = ValuePort(int)
s.req_msg_b = ValuePort(int)
s.resp_msg = ValuePort(int)
s.cs = GcdUnitCS()
s.sub_out = Wire(int)
s.a_reg = RegEn( Bits32 )( en = s.cs.a_reg_en )
s.b_reg = RegEn( Bits32 )( en = s.cs.b_reg_en )
s.a_mux = Mux( Bits32, 3 )(
out = s.a.reg.in_,
sel = s.cs.b_mux_sel,
)
# one way is to use |= for all elements in the array
s.a_mux.in_[A_MUX_SEL_IN] |= s.req_msg_a
s.a_mux.in_[A_MUX_SEL_SUB] |= s.sub_out
s.a_mux.in_[A_MUX_SEL_B] |= s.b_reg.out
# the keyword args won't work for "in_[B_MUX_SEL_A]"
ins = [None] * 2
ins[B_MUX_SEL_A] = s.a_reg.out
ins[B_MUX_SEL_IN] = s.req_msg_b
s.b_mux = Mux( Bits32, 2 )(
out = s.b.reg.in_,
sel = s.cs.b_mux_sel,
in_ = ins, # inside component I will connect based on index?
)
s.b_zcp = ZeroComp()( in_ = s.b_reg.out, out = s.cs.is_b_zero )
s.b_ltc = LTComp()(
in0 = s.a_reg.out,
in1 = s.b_reg.out,
out = s.cs.is_a_lt_b,
)
s.b_sub = Subtractor()(
in0 = s.a_reg.out,
in1 = s.b_reg.out,
out = s.resp_msg,
)
s.sub_out |= s.b_sub.out # out = x cannot do fan-out, maybe "out=[x,y,z] means fan-out?"
class GcdUnitCtrl( Updates ):
def init( s ):
s.req_val = ValuePort(int)
s.req_rdy = ValuePort(int)
s.resp_val = ValuePort(int)
s.resp_rdy = ValuePort(int)
s.state = Reg()
s.STATE_IDLE = 0
s.STATE_CALC = 1
s.STATE_DONE = 2
s.cs = GcdUnitCS()
@s.update
def state_transitions():
curr_state = s.state.out
if curr_state == s.STATE_IDLE:
if s.req_val and s.req_rdy:
s.state.in_ = s.STATE_CALC
elif curr_state == s.STATE_CALC:
if not s.cs.is_a_lt_b and s.cs.is_b_zero:
s.state.in_ = s.STATE_DONE
elif curr_state == s.STATE_DONE:
if s.resp_val and s.resp_rdy:
s.state.in_ = s.STATE_IDLE
@s.update
def state_outputs():
curr_state = s.state.out
s.req_rdy = 0
s.resp_val = 0
s.cs.a_mux_sel = 0
s.cs.a_reg_en = 0
s.cs.b_mux_sel = 0
s.cs.b_reg_en = 0
# In IDLE state we simply wait for inputs to arrive and latch them
if curr_state == s.STATE_IDLE:
s.req_rdy = 1
s.resp_val = 0
s.cs.a_mux_sel = A_MUX_SEL_IN
s.cs.b_mux_sel = B_MUX_SEL_IN
s.cs.a_reg_en = 1
s.cs.b_reg_en = 1
# In CALC state we iteratively swap/sub to calculate GCD
elif curr_state == s.STATE_CALC:
s.req_rdy = s.resp_val = 0
s.cs.a_mux_sel = A_MUX_SEL_B if s.cs.is_a_lt_b else A_MUX_SEL_SUB
s.cs.a_reg_en = 1
s.cs.b_mux_sel = B_MUX_SEL_A
s.cs.b_reg_en = s.cs.is_a_lt_b
# In DONE state we simply wait for output transaction to occur
elif curr_state == s.STATE_DONE:
s.req_rdy = 0
s.resp_val = 1
s.cs.a_mux_sel = A_MUX_SEL_X
s.cs.b_mux_sel = B_MUX_SEL_X
s.cs.a_reg_en = 0
s.cs.b_reg_en = 0
class GcdUnit( Updates ):
def init( s ):
s.req = ValRdyBundle()
s.resp = ValRdyBundle()
s.dpath = GcdUnitDpath()(
req_msg_a = s.req.msg[0:32],
req_msg_b = s.req.msg[32:64],
resp_msg = s.resp.msg,
)
s.ctrl = GcdUnitCtrl()(
req_val = s.req.val,
req_rdy = s.req.rdy,
resp_val = s.resp.val,
cs = s.dpath.cs,
)
def line_trace( s ): return s.dpath.a_reg.line_trace() + s.dpath.b_reg.line_trace()