def __init__( s, dtype ): s.enq_bits = InPort ( dtype ) s.deq_bits = OutPort ( dtype ) # Control signal (ctrl -> dpath) s.wen = InPort ( 1 ) s.bypass_mux_sel = InPort ( 1 ) # Queue storage s.queue = RegEn( dtype ) s.connect( s.queue.en, s.wen ) s.connect( s.queue.in_, s.enq_bits ) # Bypass mux s.bypass_mux = Mux( dtype, 2 ) s.connect( s.bypass_mux.in_[0], s.queue.out ) s.connect( s.bypass_mux.in_[1], s.enq_bits ) s.connect( s.bypass_mux.sel, s.bypass_mux_sel ) s.connect( s.bypass_mux.out, s.deq_bits )
def __init__(s, Type): s.enq = InValRdyIfc(Type) s.deq = OutValRdyIfc(Type) s.buf = RegEn(Type)(out=s.deq.msg, in_=s.enq.msg) s.next_full = Wire(int if Type is int else Bits1) s.full = Wire(int if Type is int else Bits1) s.connect(s.full, s.deq.val) @s.update_on_edge def up_full(): s.full = s.next_full if Type is int: @s.update def up_pipeq_set_enq_rdy(): s.enq.rdy = (not s.full) | s.deq.rdy @s.update def up_pipeq_full(): s.buf.en = s.enq.val & s.enq.rdy s.next_full = s.enq.val | (s.full & (not s.deq.rdy)) else: @s.update def up_pipeq_set_enq_rdy(): s.enq.rdy = ~s.full | s.deq.rdy @s.update def up_pipeq_full(): s.buf.en = s.enq.val & s.enq.rdy s.next_full = s.enq.val | (s.full & ~s.deq.rdy)
def __init__(s, Type): s.enq = EnqIfcRTL(Type) s.deq = DeqIfcRTL(Type) s.buf = RegEn(Type)(in_=s.enq.msg) s.full = Reg(Bits1) s.byp_mux = Mux(Type, 2)( out=s.deq.msg, in_={ 0: s.enq.msg, 1: s.buf.out, }, sel=s.full.out, # full -- buf.out, empty -- bypass ) @s.update def up_bypq_set_enq_rdy(): s.enq.rdy = ~s.full.out @s.update def up_bypq_set_deq_rdy(): s.deq.rdy = s.full.out | s.enq.en # if enq is enabled deq must be rdy @s.update def up_bypq_full(): # enable buf <==> receiver marks deq.en=0 even if it sees deq.rdy=1 s.buf.en = ~s.deq.en & s.enq.en s.full.in_ = ~s.deq.en & (s.enq.en | s.full.out)
def __init__(s, type_): s.enq = EnqIfcRTL(type_) s.deq = DeqIfcRTL(type_) s.buf = RegEn(type_)(out=s.deq.msg, in_=enq.msg) s.full = Reg(Bits1) @s.update def up_normq_set_both_rdy(): s.enq.rdy = ~s.full.out s.deq.rdy = s.full.out @s.update def up_normq_full(): s.buf.en = s.enq.en s.full.in_ = ~s.deq.en & (s.enq.en | s.full.out)
def __init__(s, Type): s.enq = InValRdyIfc(Type) s.deq = OutValRdyIfc(Type) s.buf = RegEn(Type)(in_=s.enq.msg) s.next_full = Wire(int if Type is int else Bits1) s.full = Wire(int if Type is int else Bits1) s.byp_mux = Mux(Type, 2)( out=s.deq.msg, in_={ 0: s.enq.msg, 1: s.buf.out, }, sel=s.full, # full -- buf.out, empty -- bypass ) @s.update_on_edge def up_full(): s.full = s.next_full if Type is int: @s.update def up_bypq_set_enq_rdy(): s.enq.rdy = not s.full @s.update def up_bypq_internal(): s.buf.en = (not s.deq.rdy) & (s.enq.val & s.enq.rdy) s.next_full = (not s.deq.rdy) & s.deq.val else: @s.update def up_bypq_set_enq_rdy(): s.enq.rdy = ~s.full @s.update def up_bypq_internal(): s.buf.en = (~s.deq.rdy) & (s.enq.val & s.enq.rdy) s.next_full = (~s.deq.rdy) & s.deq.val # this enables the sender to make enq.val depend on enq.rdy @s.update def up_bypq_set_deq_val(): s.deq.val = s.full | s.enq.val
def __init__( s, dtype ): s.enq_bits = InPort ( dtype ) s.deq_bits = OutPort ( dtype ) # Control signal (ctrl -> dpath) s.wen = InPort ( 1 ) # Queue storage s.queue = RegEn( dtype ) # Connect queue storage s.connect( s.queue.en, s.wen ) s.connect( s.queue.in_, s.enq_bits ) s.connect( s.queue.out, s.deq_bits )
def __init__ ( s ): s.req_msg_data = InPort (1) s.resp_msg_data = OutPort(32) s.sel = InPort (1) s.en = InPort (1) # Input Mux s.reg_out = Wire(32) s.mux = m = Mux( 32, 2) s.connect_dict({ m.sel : s.sel, m.in_[0] : 0, m.in_[1] : s.reg_out }) # Output Register s.adder_out = Wire(32) s.reg = m = RegEn( 32 ) s.connect_dict({ m.en : s.en, m.in_ : s.adder_out, m.out : s.reg_out }) # Zero Extender s.zext = m = ZeroExtender( 1, 32 ) s.connect_dict({ m.in_ : s.req_msg_data }) # Adder s.add = m = Adder( 32 ) s.connect_dict({ m.in0 : s.zext.out, m.in1 : s.mux.out, m.cin : 0, m.out : s.adder_out }) # Connect to output port s.connect( s.reg_out, s.resp_msg_data )
def __init__(s, Type): s.enq = EnqIfcRTL(Type) s.deq = DeqIfcRTL(Type) s.buf = RegEn(Type)(out=s.deq.msg, in_=s.enq.msg) s.full = Reg(Bits1) @s.update def up_pipeq_set_deq_rdy(): s.deq.rdy = s.full.out @s.update def up_pipeq_set_enq_rdy(): s.enq.rdy = ~s.full.out | s.deq.en @s.update def up_pipeq_full(): s.buf.en = s.enq.en s.full.in_ = s.enq.en | (s.full.out & ~s.deq.en)
def __init__(s, nbits): nbitsx2 = nbits * 2 dtype = mk_bits(nbits) dtypex2 = mk_bits(nbitsx2) s.req_msg = InVPort(dtypex2) s.resp_msg = OutVPort(dtypex2) # Status signals s.sub_negative1 = OutVPort(Bits1) s.sub_negative2 = OutVPort(Bits1) # Control signals s.quotient_mux_sel = InVPort(Bits1) s.quotient_reg_en = InVPort(Bits1) s.remainder_mux_sel = InVPort(Bits2) s.remainder_reg_en = InVPort(Bits1) s.divisor_mux_sel = InVPort(Bits1) # Dpath components s.remainder_mux = Mux(dtypex2, 3)(sel=s.remainder_mux_sel) @s.update def up_remainder_mux_in0(): s.remainder_mux.in_[R_MUX_SEL_IN] = dtypex2() s.remainder_mux.in_[R_MUX_SEL_IN][0:nbits] = s.req_msg[0:nbits] s.remainder_reg = RegEn(dtypex2)( in_=s.remainder_mux.out, en=s.remainder_reg_en, ) # lower bits of resp_msg save the remainder s.connect(s.resp_msg[0:nbits], s.remainder_reg.out[0:nbits]) s.divisor_mux = Mux(dtypex2, 2)(sel=s.divisor_mux_sel) @s.update def up_divisor_mux_in0(): s.divisor_mux.in_[D_MUX_SEL_IN] = dtypex2() s.divisor_mux.in_[D_MUX_SEL_IN][nbits - 1:nbitsx2 - 1] = s.req_msg[nbits:nbitsx2] s.divisor_reg = Reg(dtypex2)(in_=s.divisor_mux.out) s.quotient_mux = Mux(dtype, 2)(sel=s.quotient_mux_sel) s.connect(s.quotient_mux.in_[Q_MUX_SEL_0], 0) s.quotient_reg = RegEn(dtype)( in_=s.quotient_mux.out, en=s.quotient_reg_en, # higher bits of resp_msg save the quotient out=s.resp_msg[nbits:nbitsx2], ) # shamt should be 2 bits! s.quotient_lsh = LShifter(dtype, 2)(in_=s.quotient_reg.out) s.connect(s.quotient_lsh.shamt, 2) s.inc = Wire(Bits2) s.connect(s.sub_negative1, s.inc[1]) s.connect(s.sub_negative2, s.inc[0]) @s.update def up_quotient_inc(): s.quotient_mux.in_[Q_MUX_SEL_LSH] = s.quotient_lsh.out + ~s.inc # stage 1/2 s.sub1 = Subtractor(dtypex2)( in0=s.remainder_reg.out, in1=s.divisor_reg.out, out=s.remainder_mux.in_[R_MUX_SEL_SUB1], ) s.connect(s.sub_negative1, s.sub1.out[nbitsx2 - 1]) s.remainder_mid_mux = Mux(dtypex2, 2)( in_={ 0: s.sub1.out, 1: s.remainder_reg.out, }, sel=s.sub_negative1, ) s.divisor_rsh1 = RShifter(dtypex2, 1)(in_=s.divisor_reg.out, ) s.connect(s.divisor_rsh1.shamt, 1) # stage 2/2 s.sub2 = Subtractor(dtypex2)( in0=s.remainder_mid_mux.out, in1=s.divisor_rsh1.out, out=s.remainder_mux.in_[R_MUX_SEL_SUB2], ) s.connect(s.sub_negative2, s.sub2.out[nbitsx2 - 1]) s.divisor_rsh2 = RShifter(dtypex2, 1)( in_=s.divisor_rsh1.out, out=s.divisor_mux.in_[D_MUX_SEL_RSH], ) s.connect(s.divisor_rsh2.shamt, 1)
def elaborate_logic(s): #--------------------------------------------------------------------- # Datapath Structural Composition #--------------------------------------------------------------------- s.sub_out = Wire(32) s.b_reg_out = Wire(32) # A mux s.a_mux = m = Mux(32, 3) s.connect_dict({ m.sel: s.a_mux_sel, m.in_[A_MUX_SEL_IN]: s.in_msg_a, m.in_[A_MUX_SEL_SUB]: s.sub_out, m.in_[A_MUX_SEL_B]: s.b_reg_out, }) # A register s.a_reg = m = RegEn(32) s.connect_dict({ m.en: s.a_reg_en, m.in_: s.a_mux.out, }) # B mux s.b_mux = m = Mux(32, 2) s.connect_dict({ m.sel: s.b_mux_sel, m.in_[B_MUX_SEL_A]: s.a_reg.out, m.in_[B_MUX_SEL_IN]: s.in_msg_b, }) # B register s.b_reg = m = RegEn(32) s.connect_dict({ m.en: s.b_reg_en, m.in_: s.b_mux.out, m.out: s.b_reg_out, }) # Zero compare s.b_zero = m = arith.ZeroComparator(32) s.connect_dict({ m.in_: s.b_reg.out, m.out: s.is_b_zero, }) # Less-than comparator s.a_lt_b = m = arith.LtComparator(32) s.connect_dict({ m.in0: s.a_reg.out, m.in1: s.b_reg.out, m.out: s.is_a_lt_b }) # Subtractor s.sub = m = arith.Subtractor(32) s.connect_dict({ m.in0: s.a_reg.out, m.in1: s.b_reg.out, m.out: s.sub_out, }) # connect to output port s.connect(s.sub.out, s.out_msg)
def __init__(s): # Interface s.req_msg_data = InPort(DATA_NBITS) s.resp_msg_data = OutPort(DISTANCE_NBITS) s.req_msg_type = InPort(TYPE_NBITS) s.resp_msg_type = OutPort(TYPE_NBITS) s.req_msg_digit = InPort(DIGIT_NBITS) s.resp_msg_digit = OutPort(DIGIT_NBITS) # Control signals (ctrl -> dpath) s.en_test = InPort(1) s.en_train = InPort(1) s.en_out = InPort(1) s.sel_out = InPort(1) s.sel = InPort(6) # Input Mux for Test Data s.in_test = Wire(DATA_NBITS) s.mux_in_test = m = Mux(DATA_NBITS, 2) s.connect_dict({ m.sel: s.req_msg_type, m.in_[0]: s.in_test, m.in_[1]: s.req_msg_data, m.out: s.in_test }) # Input Mux for Train Data s.in_train = Wire(DATA_NBITS) s.mux_in_train = m = Mux(DATA_NBITS, 2) s.connect_dict({ m.sel: s.req_msg_type, m.in_[0]: s.req_msg_data, m.in_[1]: s.in_train, m.out: s.in_train }) # Register for Test Data s.out_test = Wire(DATA_NBITS) s.reg_test = m = RegEn(DATA_NBITS) s.connect_dict({m.en: s.en_test, m.in_: s.in_test, m.out: s.out_test}) # Register for Train Data s.out_train = Wire(DATA_NBITS) s.reg_train = m = RegEn(DATA_NBITS) s.connect_dict({ m.en: s.en_train, m.in_: s.in_train, m.out: s.out_train }) # 49-1 Mux for Test Data s.data_test = Wire(1) s.mux_test = m = Mux(1, 49) for i in range(49): s.connect(m.in_[i], s.out_test[i]) s.connect(m.sel, s.sel) s.connect(m.out, s.data_test) # 49-1 Mux for Train Data s.data_train = Wire(1) s.mux_train = m = Mux(1, 49) for i in range(49): s.connect(m.in_[i], s.out_train[i]) s.connect(m.sel, s.sel) s.connect(m.out, s.data_train) # Comparator s.is_not_equal = Wire(1) s.is_equal = Wire(1) s.comp = m = EqComparator(1) s.connect_dict({ m.in0: s.data_test, m.in1: s.data_train, m.out: s.is_equal }) @s.combinational def not_value(): s.is_not_equal.value = ~s.is_equal # Zero Extender s.zext = m = ZeroExtender(1, DISTANCE_NBITS) s.connect_dict({m.in_: s.is_not_equal}) # Input Mux for Adder s.reg_out = Wire(DISTANCE_NBITS) s.mux_add = m = Mux(DISTANCE_NBITS, 2) s.connect_dict({m.sel: s.sel_out, m.in_[0]: 0, m.in_[1]: s.reg_out}) # Adder s.add = m = Adder(DISTANCE_NBITS) s.connect_dict({m.in0: s.zext.out, m.in1: s.mux_add.out, m.cin: 0}) # Output Register s.reg = m = RegEn(DISTANCE_NBITS) s.connect_dict({m.en: s.en_out, m.in_: s.add.out, m.out: s.reg_out}) # Connect to output port s.connect(s.reg_out, s.resp_msg_data) s.connect(0, s.resp_msg_type) s.connect(s.req_msg_digit, s.resp_msg_digit)
def __init__(s, nstages=2): # Interface s.req = InValRdyBundle(MymultReqMsg()) s.resp = OutValRdyBundle(Bits(16)) # We currently only support power of two number of stages assert nstages in [1, 2, 4, 8, 16] # Input registers s.val_reg = RegEn(1) s.a_reg = RegEn(16) s.b_reg = RegEn(16) s.connect(s.req.val, s.val_reg.in_) s.connect(s.resp.rdy, s.val_reg.en) s.connect(s.req.msg.a, s.a_reg.in_) s.connect(s.resp.rdy, s.a_reg.en) s.connect(s.req.msg.b, s.b_reg.in_) s.connect(s.resp.rdy, s.b_reg.en) # Instantiate steps s.steps = MymultNstageStep[16]() # Structural composition for first step s.connect(s.val_reg.out, s.steps[0].in_val) s.connect(s.a_reg.out, s.steps[0].in_a) s.connect(s.b_reg.out, s.steps[0].in_b) s.connect(0, s.steps[0].in_result) # Pipeline registers s.val_preg = RegEn[nstages - 1](1) s.a_preg = RegEn[nstages - 1](16) s.b_preg = RegEn[nstages - 1](16) s.result_preg = RegEn[nstages - 1](16) # Structural composition for intermediate steps nstage = 0 for i in xrange(1, 16): # Insert a pipeline register if i % (16 / nstages) == 0: s.connect(s.steps[i - 1].out_val, s.val_preg[nstage].in_) s.connect(s.steps[i - 1].out_a, s.a_preg[nstage].in_) s.connect(s.steps[i - 1].out_b, s.b_preg[nstage].in_) s.connect(s.steps[i - 1].out_result, s.result_preg[nstage].in_) s.connect(s.val_preg[nstage].out, s.steps[i].in_val) s.connect(s.a_preg[nstage].out, s.steps[i].in_a) s.connect(s.b_preg[nstage].out, s.steps[i].in_b) s.connect(s.result_preg[nstage].out, s.steps[i].in_result) s.connect(s.resp.rdy, s.val_preg[nstage].en) s.connect(s.resp.rdy, s.a_preg[nstage].en) s.connect(s.resp.rdy, s.b_preg[nstage].en) s.connect(s.resp.rdy, s.result_preg[nstage].en) nstage += 1 # No pipeline register else: s.connect(s.steps[i - 1].out_val, s.steps[i].in_val) s.connect(s.steps[i - 1].out_a, s.steps[i].in_a) s.connect(s.steps[i - 1].out_b, s.steps[i].in_b) s.connect(s.steps[i - 1].out_result, s.steps[i].in_result) # Structural composition for last step s.connect(s.resp.val, s.steps[15].out_val) s.connect(s.resp.msg, s.steps[15].out_result) # Wire resp rdy to req rdy s.connect(s.resp.rdy, s.req.rdy)
def __init__(s, nstages, nBits, k): #Interface s.req = InValRdyBundle(MymultReqMsg(nBits)) s.resp = OutValRdyBundle(nBits * 2) s.approxNStage = ApproxMultNStage(nstages=2, kBits=k) s.truncation1 = truncationStep(nBits, k) s.truncation2 = truncationStep(nBits, k) s.LOD1 = LeadingOne(nBits, nstages) s.LOD2 = LeadingOne(nBits, nstages) s.LeftShift1 = LeftLogicalShifter(nBits * 2, 10, 10) s.zeroExt = ZeroExtender(k * 2, nBits * 2) s.val_reg1 = RegEn(1) s.val_reg2 = RegEn(1) s.a_msg_reg = RegEn(nBits) s.b_msg_reg = RegEn(nBits) s.mult_reg1 = RegEn(1) s.mult_reg2 = RegEn(1) s.delay1 = RegEn(10) s.delay2 = RegEn(10) s.delay3 = RegEn(10) s.delay4 = RegEn(10) # rdy signal that goes into multiplier s.connect(s.resp.rdy, s.approxNStage.rdy_in) # registers for input reqs s.connect(s.req.val, s.val_reg1.in_) s.connect(s.resp.rdy, s.val_reg1.en) s.connect(s.req.val, s.val_reg2.in_) s.connect(s.resp.rdy, s.val_reg2.en) s.connect(s.req.msg.a, s.a_msg_reg.in_) s.connect(s.resp.rdy, s.a_msg_reg.en) s.connect(s.req.msg.b, s.b_msg_reg.in_) s.connect(s.resp.rdy, s.b_msg_reg.en) # input register to LOD s.connect(s.val_reg1.out, s.LOD1.in_val) s.connect(s.a_msg_reg.out, s.LOD1.msg_in) s.connect(s.val_reg2.out, s.LOD2.in_val) s.connect(s.b_msg_reg.out, s.LOD2.msg_in) # LOD to trunc unit s.connect(s.LOD1.out_val, s.truncation1.in_val) s.connect(s.LOD1.msg_out, s.truncation1.msg_in) s.connect(s.LOD1.pos_out, s.truncation1.lod_in) s.connect(s.LOD2.out_val, s.truncation2.in_val) s.connect(s.LOD2.msg_out, s.truncation2.msg_in) s.connect(s.LOD2.pos_out, s.truncation2.lod_in) # trunc unit to multiplier s.connect(s.truncation1.msg_out, s.approxNStage.a) s.connect(s.truncation2.msg_out, s.approxNStage.b) # trunc unit to left shifter s.connect(s.truncation2.trunc_out, s.delay1.in_) s.connect(s.truncation1.trunc_out, s.delay3.in_) s.connect(s.resp.rdy, s.delay1.en) s.connect(s.resp.rdy, s.delay3.en) s.connect(s.delay1.out, s.delay2.in_) s.connect(s.delay3.out, s.delay4.in_) s.connect(s.resp.rdy, s.delay2.en) s.connect(s.resp.rdy, s.delay4.en) s.connect(s.delay2.out, s.LeftShift1.shamt) s.connect(s.delay4.out, s.LeftShift1.shamt2) # trunc unit to zero extender s.connect(s.mult_reg1.en, s.resp.rdy) s.connect(s.mult_reg2.en, s.resp.rdy) s.connect(s.truncation1.out_val, s.mult_reg1.in_) s.connect(s.mult_reg1.out, s.mult_reg2.in_) s.connect(s.mult_reg2.out, s.zeroExt.in_val) # multiplier to zero extender s.connect(s.approxNStage.resp, s.zeroExt.in_) # zero extender to left shifter s.connect(s.zeroExt.out_val, s.LeftShift1.in_val) s.connect(s.zeroExt.out, s.LeftShift1.in_) # left shifter to resp s.connect(s.LeftShift1.out, s.resp.msg) s.connect(s.LeftShift1.out_val, s.resp.val) s.connect(s.resp.rdy, s.req.rdy) def line_trace(s): return "in_rdy={},in_val={},in_msg={} > out_rdy={},out_val={},out_msg={}"\ .format(s.req.rdy, s.req.val, s.req.msg, s.resp.rdy, s.resp.val, s.resp.msg)
def __init__(s): #================================================================== # Interfaces #================================================================== s.req_msg_a = InPort(32) s.req_msg_b = InPort(32) s.resp_msg = OutPort(32) # Control signals s.a_mux_sel = InPort(A_MUX_SEL_NBITS) s.b_mux_sel = InPort(B_MUX_SEL_NBITS) s.result_mux_sel = InPort(RES_MUX_SEL_NBITS) s.add_mux_sel = InPort(ADD_MUX_SEL_NBITS) s.result_en = InPort(1) s.result_sign = InPort(OUT_MUX_SEL_NBITS) # Status signals s.b_lsb = OutPort(1) s.a_msb = OutPort(1) s.b_msb = OutPort(1) #================================================================== # Structure #================================================================== # A Mux s.in_a = Wire(32) # Take the abs value of the input @s.combinational def sign_handling_a(): s.in_a.value = s.req_msg_a if ~s.req_msg_a[31] \ else (~s.req_msg_a) + 1 s.l_shift_out = Wire(32) s.a_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.a_mux_sel, m.in_[A_MUX_SEL_IN], s.in_a, m.in_[A_MUX_SEL_SHIFT], s.l_shift_out, ) # A Register s.a_reg = m = Reg(32) s.connect(m.in_, s.a_mux.out) # Left Shifter s.l_shift = m = LeftLogicalShifter(32) s.connect_pairs( m.in_, s.a_reg.out, m.shamt, 1, m.out, s.l_shift_out, ) # B Mux s.in_b = Wire(32) # Take the abs value of the input @s.combinational def sign_handling_b(): s.in_b.value = s.req_msg_b if ~s.req_msg_b[31] \ else (~s.req_msg_b) + 1 s.r_shift_out = Wire(32) s.b_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.b_mux_sel, m.in_[B_MUX_SEL_IN], s.in_b, m.in_[B_MUX_SEL_SHIFT], s.r_shift_out, ) # B Register s.b_reg = m = Reg(32) s.connect(m.in_, s.b_mux.out) # Right Shifter s.r_shift = m = RightLogicalShifter(32) s.connect_pairs( m.in_, s.b_reg.out, m.shamt, 1, m.out, s.r_shift_out, ) # Result Mux s.add_mux_out = Wire(32) s.result_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.result_mux_sel, m.in_[RES_MUX_SEL_ZERO], 0, m.in_[RES_MUX_SEL_ADD], s.add_mux_out, ) # Result Register s.res_reg = m = RegEn(32) s.connect_pairs(m.in_, s.result_mux.out, m.en, s.result_en) # Adder s.adder = m = Adder(32) s.connect_pairs( m.in0, s.a_reg.out, m.in1, s.res_reg.out, m.cin, 0, ) # Add Mux s.add_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.add_mux_sel, m.in_[ADD_MUX_SEL_ADD], s.adder.out, m.in_[ADD_MUX_SEL_RES], s.res_reg.out, m.out, s.add_mux_out, ) # Output MUX s.res_neg = Wire(32) # Generate -res in case the output is negative @s.combinational def twos_compl_block(): s.res_neg.value = (~s.res_reg.out) + 1 s.out_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.result_sign, m.in_[OUT_MUX_SEL_POS], s.res_reg.out, m.in_[OUT_MUX_SEL_NEG], s.res_neg, m.out, s.resp_msg, ) # Connect status signals s.connect(s.b_reg.out[0], s.b_lsb) s.connect(s.req_msg_a[31], s.a_msb) s.connect(s.req_msg_b[31], s.b_msb)
def __init__( s, nstages, kBits): # Interface s.a = InPort(kBits) s.b = InPort(kBits) s.resp = OutPort (kBits*2) s.rdy_in = InPort(1) # We currently only support power of two number of stages assert nstages in [1,2,4] # Input registers s.a_reg = RegEn(kBits*2) s.b_reg = RegEn(kBits*2) # input kBits, append zeros so output becomes kBits s.zeroExtend1 = ZeroExtender (kBits, kBits*2) s.zeroExtend2 = ZeroExtender (kBits, kBits*2) # (input) s.a -> zeroExtender1 -> a_reg s.connect( s.a, s.zeroExtend1.in_ ) s.connect( s.zeroExtend1.out, s.a_reg.in_ ) s.connect( s.a_reg.en, s.rdy_in ) # (input) s.b -> zeroExtender2 -> b_reg s.connect( s.b, s.zeroExtend2.in_ ) s.connect( s.zeroExtend2.out, s.b_reg.in_ ) s.connect( s.b_reg.en, s.rdy_in ) # Instantiate steps s.steps = ApproxMultNStageStep[kBits](kBits*2) # Structural composition for first step s.connect( s.a_reg.out, s.steps[0].in_a ) s.connect( s.b_reg.out, s.steps[0].in_b ) s.connect( 0, s.steps[0].in_result ) # Pipeline registers s.a_preg = RegEn[nstages-1](kBits*2) s.b_preg = RegEn[nstages-1](kBits*2) s.result_preg = RegEn[nstages-1](kBits*2) # Structural composition for intermediate steps nstage = 0 for i in xrange(1,kBits): # 1 to kBits-1 # Insert a pipeline register # e.g. kBits = 6, nstages = 3. 6/3 = 2 pipeline registers # i % (kBits/nstages) bascially at i = 2, 4, 6 will have pipeline registers. # essentially every 2 steps. # s0 s1 s2 | s3 s4 s5 # the last step will always have a pipeline register if i % (kBits/nstages) == 0: s.connect( s.steps[i-1].out_a, s.a_preg[nstage].in_ ) s.connect( s.steps[i-1].out_b, s.b_preg[nstage].in_ ) s.connect( s.steps[i-1].out_result, s.result_preg[nstage].in_ ) s.connect(s.a_preg[nstage].en, s.rdy_in ) s.connect(s.b_preg[nstage].en, s.rdy_in ) s.connect(s.result_preg[nstage].en, s.rdy_in ) s.connect( s.a_preg[nstage].out, s.steps[i].in_a ) s.connect( s.b_preg[nstage].out, s.steps[i].in_b ) s.connect( s.result_preg[nstage].out, s.steps[i].in_result ) nstage += 1 # No pipeline register else: # connect one step module to the next step module s.connect( s.steps[i-1].out_a, s.steps[i].in_a ) s.connect( s.steps[i-1].out_b, s.steps[i].in_b ) s.connect( s.steps[i-1].out_result, s.steps[i].in_result ) # Structural composition for last step s.connect( s.resp, s.steps[kBits-1].out_result )
def __init__(s): #--------------------------------------------------------------------- # Interface #--------------------------------------------------------------------- s.req_msg_a = InPort(16) s.req_msg_b = InPort(16) s.resp_msg = OutPort(16) # Control signals (ctrl -> dpath) s.a_mux_sel = InPort(A_MUX_SEL_NBITS) s.a_reg_en = InPort(1) s.b_mux_sel = InPort(B_MUX_SEL_NBITS) s.b_reg_en = InPort(1) # Status signals (dpath -> ctrl) s.is_b_zero = OutPort(1) s.is_a_lt_b = OutPort(1) #--------------------------------------------------------------------- # Structural composition #--------------------------------------------------------------------- # A mux s.sub_out = Wire(16) s.b_reg_out = Wire(16) s.a_mux = m = Mux(16, 3) s.connect_dict({ m.sel: s.a_mux_sel, m.in_[A_MUX_SEL_IN]: s.req_msg_a, m.in_[A_MUX_SEL_SUB]: s.sub_out, m.in_[A_MUX_SEL_B]: s.b_reg_out, }) # A register s.a_reg = m = RegEn(16) s.connect_dict({ m.en: s.a_reg_en, m.in_: s.a_mux.out, }) # B mux s.b_mux = m = Mux(16, 2) s.connect_dict({ m.sel: s.b_mux_sel, m.in_[B_MUX_SEL_A]: s.a_reg.out, m.in_[B_MUX_SEL_IN]: s.req_msg_b, }) # B register s.b_reg = m = RegEn(16) s.connect_dict({ m.en: s.b_reg_en, m.in_: s.b_mux.out, m.out: s.b_reg_out, }) # Zero compare s.b_zero = m = ZeroComparator(16) s.connect_dict({ m.in_: s.b_reg.out, m.out: s.is_b_zero, }) # Less-than comparator s.a_lt_b = m = LtComparator(16) s.connect_dict({ m.in0: s.a_reg.out, m.in1: s.b_reg.out, m.out: s.is_a_lt_b }) # Subtractor s.sub = m = Subtractor(16) s.connect_dict({ m.in0: s.a_reg.out, m.in1: s.b_reg.out, m.out: s.sub_out, }) # connect to output port s.connect(s.sub.out, s.resp_msg)
def __init__(s): #================================================================== # Interfaces #================================================================== s.req_msg_a = InPort(32) s.req_msg_b = InPort(32) s.resp_msg = OutPort(32) # Control signals s.a_mux_sel = InPort(A_MUX_SEL_NBITS) s.b_mux_sel = InPort(B_MUX_SEL_NBITS) s.result_mux_sel = InPort(RES_MUX_SEL_NBITS) s.add_mux_sel = InPort(ADD_MUX_SEL_NBITS) s.result_en = InPort(1) s.result_sign = InPort(OUT_MUX_SEL_NBITS) # Status signals s.b_lsb = OutPort(1) s.a_msb = OutPort(1) s.b_msb = OutPort(1) s.to_ctrl_shamt = OutPort(6) # shamt input to shifters, calculated by ShamtGen s.shamt = Wire(6) # Binary representation of the multiplier s.bit_string = Wire(32) #================================================================== # Structure #================================================================== # A Mux s.in_a = Wire(32) # Take the absolute value of the input @s.combinational def sign_handling_a(): s.in_a.value = s.req_msg_a if ~s.req_msg_a[31] \ else (~s.req_msg_a) + 1 s.l_shift_out = Wire(32) s.a_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.a_mux_sel, m.in_[A_MUX_SEL_IN], s.in_a, m.in_[A_MUX_SEL_SHIFT], s.l_shift_out, ) # A Register s.a_reg = m = Reg(32) s.connect(m.in_, s.a_mux.out) # Left Shifter s.l_shift = m = LeftLogicalShifter(32, 6) s.connect_pairs( m.in_, s.a_reg.out, m.shamt, s.shamt, m.out, s.l_shift_out, ) # B Mux s.in_b = Wire(32) # Take the absolute value of the input @s.combinational def sign_handling_b(): s.in_b.value = s.req_msg_b if ~s.req_msg_b[31] \ else (~s.req_msg_b) + 1 s.r_shift_out = Wire(32) s.b_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.b_mux_sel, m.in_[B_MUX_SEL_IN], s.in_b, m.in_[B_MUX_SEL_SHIFT], s.r_shift_out, ) # B Register s.b_reg = m = Reg(32) s.connect(m.in_, s.b_mux.out) # Take the higher 31 bits and add 0 in the high order # The ShamtGen module will generate the appropriate shamt # according to the number of consecutive zeros in lower s.bit_string @s.combinational def bit_string_block(): s.bit_string.value = concat(Bits(1, 0), s.b_reg.out[1:32]) # Right Shifter s.r_shift = m = RightLogicalShifter(32, 6) s.connect_pairs( m.in_, s.b_reg.out, m.shamt, s.shamt, m.out, s.r_shift_out, ) # Result Mux s.add_mux_out = Wire(32) s.result_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.result_mux_sel, m.in_[RES_MUX_SEL_ZERO], 0, m.in_[RES_MUX_SEL_ADD], s.add_mux_out, ) # Result Register s.res_reg = m = RegEn(32) s.connect_pairs(m.in_, s.result_mux.out, m.en, s.result_en) # Adder s.adder = m = Adder(32) s.connect_pairs( m.in0, s.a_reg.out, m.in1, s.res_reg.out, m.cin, 0, ) # Add Mux s.add_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.add_mux_sel, m.in_[ADD_MUX_SEL_ADD], s.adder.out, m.in_[ADD_MUX_SEL_RES], s.res_reg.out, m.out, s.add_mux_out, ) # ShamtGen s.shamt_gen = m = ShamtGenPRTL() s.connect_pairs( m.a, s.bit_string, m.shamt, s.shamt, ) # Forward shamt to control unit so the counter can update # accordingly @s.combinational def to_ctrl_shamt_block(): s.to_ctrl_shamt.value = s.shamt # Output MUX s.res_neg = Wire(32) # Generate -res in case the result is negative @s.combinational def twos_compl_block(): s.res_neg.value = (~s.res_reg.out) + 1 s.out_mux = m = Mux(32, 2) s.connect_pairs( m.sel, s.result_sign, m.in_[OUT_MUX_SEL_POS], s.res_reg.out, m.in_[OUT_MUX_SEL_NEG], s.res_neg, m.out, s.resp_msg, ) # Connect status signals s.connect(s.b_reg.out[0], s.b_lsb) s.connect(s.req_msg_a[31], s.a_msb) s.connect(s.req_msg_b[31], s.b_msb)