class TestSimJtagGpio(unittest.TestCase): def setUp(self): cocotb_compile_and_run([ os.path.join(os.path.dirname(__file__), 'jtag_tap.v'), os.path.join(os.path.dirname(__file__), 'test_SimJtagGpio.v') ]) self.chip = Dut(cnfg_yaml) self.chip.init(init_yaml) def test_gpio(self): ID_CODE = BitLogic('0010') BYPASS = BitLogic('1111') DEBUG = BitLogic('1000') ret_ir = BitLogic('0101') # TEST REG INIT dev1ret = StdRegister(driver=None, conf=yaml.safe_load(gpio_yaml)) dev1ret.init() dev1ret['F1'] = 0x1 dev1ret['F2'] = 0x2f dev1ret['F3'] = 0x2 dev1ret['F4'] = 0x17cf4 self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.chip['DEV1']['F2'] = 0 self.assertFalse(dev1ret[:] == self.chip['DEV1'][:]) self.chip.set_configuration(init_yaml) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.chip['JTAG'].reset() # IR CODE ret = self.chip['JTAG'].scan_ir([ID_CODE] * 2) self.assertEqual(ret, [ret_ir] * 2) # ID CODE id_code = BitLogic.from_value(0x149B51C3, fmt='I') ret = self.chip['JTAG'].scan_dr(['0' * 32] * 2) self.assertEqual(ret, [id_code] * 2) # BYPASS + ID CODE bypass_code = BitLogic('0') ret = self.chip['JTAG'].scan_ir([ID_CODE, BYPASS]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip['JTAG'].scan_dr(['0' * 32, '1']) self.assertEqual(ret, [id_code, bypass_code]) ret = self.chip['JTAG'].scan_ir([BYPASS, ID_CODE]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip['JTAG'].scan_dr(['1', '0' * 32]) self.assertEqual(ret, [bypass_code, id_code]) # DEBUG ret = self.chip['JTAG'].scan_ir([DEBUG, DEBUG]) self.assertEqual(ret, [ret_ir] * 2) self.chip['JTAG'].scan_dr(['1' * 32, '0' * 1 + '1' * 30 + '0' * 1]) ret = self.chip['JTAG'].scan_dr(['0' * 32, '1' * 32]) self.assertEqual( ret, [BitLogic('1' * 32), BitLogic('0' * 1 + '1' * 30 + '0' * 1)]) ret = self.chip['JTAG'].scan_dr(['0' * 32, '0' * 32]) self.assertEqual(ret, [BitLogic('0' * 32), BitLogic('1' * 32)]) # SHIT IN DEV REG/DEBUG self.chip['JTAG'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) # GPIO RETURN dev1ret.frombytes(self.chip['GPIO_DEV1'].get_data()) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.assertFalse(dev1ret[:] == self.chip['DEV2'][:]) dev1ret.frombytes(self.chip['GPIO_DEV2'].get_data()) self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) # JTAG RETURN ret = self.chip['JTAG'].scan_dr(['0' * 32, '0' * 32]) dev1ret.set(ret[0]) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) dev1ret.set(ret[1]) self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) # REPEATING REGISTER self.chip['JTAG'].scan_dr([self.chip['DEV'][:]]) ret1 = self.chip['JTAG'].scan_dr([self.chip['DEV'][:]]) self.chip['JTAG'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) ret2 = self.chip['JTAG'].scan_dr( [self.chip['DEV1'][:] + self.chip['DEV2'][:]]) ret3 = self.chip['JTAG'].scan_dr( [self.chip['DEV1'][:] + self.chip['DEV2'][:]]) self.assertEqual(ret1[:], ret2[:]) self.assertEqual(ret2[:], ret3[:]) # REPEATING SETTING self.chip['JTAG'].scan_dr(['1' * 32 + '0' * 32]) ret = self.chip['JTAG'].scan_dr(['0' * 32 + '0' * 32]) self.chip['DEV'].set(ret[0]) self.assertEqual(self.chip['DEV'][:], BitLogic('0' * 32 + '1' * 32)) self.chip['JTAG'].scan_dr( [self.chip['DEV1'][:] + self.chip['DEV2'][:]]) ret = self.chip['JTAG'].scan_dr( [self.chip['DEV1'][:] + self.chip['DEV2'][:]]) self.chip['DEV'].set(ret[0]) self.assertEqual(self.chip['DEV'][:], self.chip['DEV1'][:] + self.chip['DEV2'][:]) def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean()
class TestSimJtagMaster(unittest.TestCase): def setUp(self): cocotb_compile_and_run( [ os.path.join(os.path.dirname(__file__), "jtag_tap.v"), os.path.join(os.path.dirname(__file__), "test_SimJtagMaster.v"), ] ) self.chip = Dut(cnfg_yaml) self.chip.init(init_yaml) def test_sequence(self): self.jtag_master_FSM_tests() self.jtag_tests() def jtag_master_FSM_tests(self): # Make sure register are set to default values self.chip["JTAG"].reset() size = self.chip["JTAG"].SIZE self.assertEqual(size, 2000 * 8) byte_size = self.chip["JTAG"].MEM_BYTES self.assertEqual(byte_size, 2000) word_cnt = self.chip["JTAG"].WORD_COUNT self.assertEqual(word_cnt, 1) op = self.chip["JTAG"].get_command() self.assertEqual(op, "INSTRUCTION") wait = self.chip["JTAG"].WAIT self.assertEqual(wait, 0) # Test reset self.chip["JTAG"].reset() # Write 1 word test self.chip["JTAG"].set_data([0xFF] + list(range(15))) ret = self.chip["JTAG"].get_data(size=16, addr=0) # to read back what was written self.assertEqual(ret.tolist(), [0xFF] + list(range(15))) self.chip["JTAG"].SIZE = 16 self.chip["JTAG"].start() while not self.chip["JTAG"].READY: pass # Write 2 word test self.chip["JTAG"].WORD_COUNT = 2 word_cnt = self.chip["JTAG"].WORD_COUNT self.assertEqual(word_cnt, 2) self.chip["JTAG"].start() while not self.chip["JTAG"].READY: pass # Write 5 word test self.chip["JTAG"].WORD_COUNT = 5 word_cnt = self.chip["JTAG"].WORD_COUNT self.assertEqual(word_cnt, 5) self.chip["JTAG"].start() while not self.chip["JTAG"].READY: pass def jtag_tests(self): ID_CODE_STR = "0010" ID_CODE = BitLogic(ID_CODE_STR) BYPASS = BitLogic("1111") DEBUG = BitLogic("1000") ret_ir = BitLogic("0101") # TEST REG INIT dev1ret = StdRegister(driver=None, conf=yaml.safe_load(gpio_yaml)) dev1ret.init() dev1ret["F1"] = 0x1 dev1ret["F2"] = 0x2F dev1ret["F3"] = 0x2 dev1ret["F4"] = 0x17CF4 self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) self.chip["DEV1"]["F2"] = 0 self.assertFalse(dev1ret[:] == self.chip["DEV1"][:]) self.chip.set_configuration(init_yaml) self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) self.chip["JTAG"].reset() # IR CODE with self.assertRaises(ValueError): self.chip["JTAG"].scan_ir(ID_CODE_STR + ID_CODE_STR) ret = self.chip["JTAG"].scan_ir([ID_CODE] * 2, readback=False) self.assertEqual(ret, None) ret = self.chip["JTAG"].scan_ir([ID_CODE] * 2) self.assertEqual(ret, [ret_ir] * 2) # ID CODE with self.assertRaises(ValueError): self.chip["JTAG"].scan_dr("0" * 32 * 2) ret = self.chip["JTAG"].scan_dr(["0" * 32] * 2, readback=False) self.assertEqual(ret, None) id_code = BitLogic.from_value(0x149B51C3, fmt="I") ret = self.chip["JTAG"].scan_dr(["0" * 32] * 2) self.assertEqual(ret, [id_code] * 2) # BYPASS + ID CODE bypass_code = BitLogic("0") ret = self.chip["JTAG"].scan_ir([ID_CODE, BYPASS]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip["JTAG"].scan_dr(["0" * 32, "1"]) self.assertEqual(ret, [id_code, bypass_code]) ret = self.chip["JTAG"].scan_ir([BYPASS, ID_CODE]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip["JTAG"].scan_dr(["1", "0" * 32]) self.assertEqual(ret, [bypass_code, id_code]) # DEBUG ret = self.chip["JTAG"].scan_ir([DEBUG, DEBUG]) self.assertEqual(ret, [ret_ir] * 2) self.chip["JTAG"].scan_dr(["1" * 32, "0" * 1 + "1" * 30 + "0" * 1]) ret = self.chip["JTAG"].scan_dr(["0" * 32, "1" * 32]) self.assertEqual(ret, [BitLogic("1" * 32), BitLogic("0" * 1 + "1" * 30 + "0" * 1)]) ret = self.chip["JTAG"].scan_dr(["0" * 32, "0" * 32]) self.assertEqual(ret, [BitLogic("0" * 32), BitLogic("1" * 32)]) # SHIT IN DEV REG/DEBUG self.chip["JTAG"].scan_dr([self.chip["DEV1"][:], self.chip["DEV2"][:]]) # GPIO RETURN dev1ret.frombytes(self.chip["GPIO_DEV1"].get_data()) self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) self.assertFalse(dev1ret[:] == self.chip["DEV2"][:]) dev1ret.frombytes(self.chip["GPIO_DEV2"].get_data()) self.assertEqual(dev1ret[:], self.chip["DEV2"][:]) # JTAG RETURN ret = self.chip["JTAG"].scan_dr(["0" * 32, "0" * 32]) dev1ret.set(ret[0]) self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) dev1ret.set(ret[1]) self.assertEqual(dev1ret[:], self.chip["DEV2"][:]) # REPEATING REGISTER self.chip["JTAG"].scan_dr([self.chip["DEV"][:]], word_size=len(self.chip["DEV"][:])) ret1 = self.chip["JTAG"].scan_dr([self.chip["DEV"][:]], word_size=len(self.chip["DEV"][:])) self.chip["JTAG"].scan_dr([self.chip["DEV1"][:], self.chip["DEV2"][:]]) ret2 = self.chip["JTAG"].scan_dr( [self.chip["DEV1"][:] + self.chip["DEV2"][:]], word_size=len(self.chip["DEV1"][:]), ) ret3 = self.chip["JTAG"].scan_dr( [self.chip["DEV1"][:] + self.chip["DEV2"][:]], word_size=len(self.chip["DEV1"][:]), ) self.assertEqual(ret1[:], ret2[:]) self.assertEqual(ret2[:], ret3[:]) # REPEATING SETTING self.chip["JTAG"].scan_dr(["1" * 32 + "0" * 32]) ret = self.chip["JTAG"].scan_dr(["0" * 32 + "0" * 32]) self.chip["DEV"].set(ret[0]) self.assertEqual(self.chip["DEV"][:], BitLogic("1" * 32 + "0" * 32)) self.chip["JTAG"].scan_dr( [self.chip["DEV1"][:] + self.chip["DEV2"][:]], word_size=len(self.chip["DEV1"][:]), ) ret = self.chip["JTAG"].scan_dr( [self.chip["DEV1"][:] + self.chip["DEV2"][:]], word_size=len(self.chip["DEV1"][:]), ) self.chip["DEV"].set(ret[0]) self.assertEqual(self.chip["DEV"][:], self.chip["DEV1"][:] + self.chip["DEV2"][:]) # BYPASS AND DEBUG REGISTER self.chip["fifo1"].reset() self.chip["fifo2"].reset() fifo_size = self.chip["fifo1"].get_fifo_size() self.assertEqual(fifo_size, 0) # Generate some data data_string = [] data = np.power(range(20), 6) for i in range(len(data)): s = str(bin(data[i]))[2:] data_string.append("0" * (32 - len(s)) + s) # Bypass first device, put data in the debug register of the second device self.chip["JTAG"].scan_ir([DEBUG, BYPASS]) for i in range(len(data_string)): self.chip["JTAG"].scan_dr([data_string[i], "1"]) fifo_size = self.chip["fifo1"].get_fifo_size() self.assertEqual(fifo_size, len(data_string) * 4) fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.assertListEqual(list(data), list(fifo_tap1_content)) self.assertNotEqual(list(data), list(fifo_tap2_content)) # empty fifos fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() # Bypass second device, put data in the debug register of the first device self.chip["JTAG"].scan_ir([BYPASS, DEBUG]) for i in range(len(data_string)): self.chip["JTAG"].scan_dr(["1", data_string[i]]) fifo_size = self.chip["fifo1"].get_fifo_size() self.assertEqual(fifo_size, len(data_string) * 4) fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.assertNotEqual(list(data), list(fifo_tap1_content)) self.assertListEqual(list(data), list(fifo_tap2_content)) # TEST OF SENDING MULTIPLE WORDS WITH SCAN_DR FUNCTION self.chip["JTAG"].scan_ir([DEBUG, DEBUG]) self.chip["JTAG"].set_data([0x00] * 100) self.chip["JTAG"].set_command("DATA") self.chip["JTAG"].SIZE = 100 * 8 self.chip["JTAG"].start() while not self.chip["JTAG"].READY: pass # empty fifos fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.chip["JTAG"].scan_ir([DEBUG, BYPASS]) self.chip["JTAG"].scan_dr([BitLogic("0" * 24 + "10101101"), BitLogic("1")] * 15, word_size=33) fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.assertListEqual([int("0" * 24 + "10101101", 2)] * 15, list(fifo_tap1_content)) self.assertNotEqual([int("0" * 24 + "10101101", 2)] * 15, list(fifo_tap2_content)) # change value of debug registers self.chip["JTAG"].scan_ir([DEBUG, DEBUG]) self.chip["JTAG"].scan_dr(["0" * 32, "0" * 32]) # empty fifos fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.chip["JTAG"].scan_ir([BYPASS, DEBUG]) self.chip["JTAG"].scan_dr([BitLogic("1"), BitLogic("0" * 24 + "10101101")] * 15, word_size=33) fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() self.assertNotEqual([int("0" * 24 + "10101101", 2)] * 15, list(fifo_tap1_content)) self.assertListEqual([int("0" * 24 + "10101101", 2)] * 15, list(fifo_tap2_content)) # TEST OF SENDING MULTIPLE WORDS BY WRITING DIRECTLY IN JTAG MODULE MEMORY # The ring register (DEBUG register) is 32 bits long, so the data have to be arranged like this : # [WORD1(dev1) WORD1(dev2) WORD2(dev1) WORD2(dev2) ...] data = np.byte( [ 0x01, 0x02, 0x03, 0x04, 0x02, 0x04, 0x06, 0x08, 0x11, 0x12, 0x13, 0x14, 0x12, 0x14, 0x16, 0x18, 0x21, 0x22, 0x23, 0x24, 0x22, 0x24, 0x26, 0x28, 0x31, 0x32, 0x33, 0x34, 0x32, 0x34, 0x36, 0x38, 0x41, 0x42, 0x43, 0x44, 0x42, 0x44, 0x46, 0x48, ] ) device_number = 2 word_size_bit = 32 word_count = 5 self.chip["JTAG"].scan_ir([DEBUG, DEBUG]) # empty fifo self.chip["fifo1"].get_data() self.chip["fifo2"].get_data() self.chip["JTAG"].set_data(data) self.chip["JTAG"].SIZE = word_size_bit * device_number self.chip["JTAG"].set_command("DATA") self.chip["JTAG"].WORD_COUNT = word_count self.chip["JTAG"].start() while not self.chip["JTAG"].READY: pass fifo_tap1_content = self.chip["fifo1"].get_data() fifo_tap2_content = self.chip["fifo2"].get_data() expected_result_tap1 = [ int("0x01020304", 16), int("0x11121314", 16), int("0x21222324", 16), int("0x31323334", 16), int("41424344", 16), ] expected_result_tap2 = [ int("0x02040608", 16), int("0x12141618", 16), int("0x22242628", 16), int("0x32343638", 16), int("42444648", 16), ] self.assertListEqual(expected_result_tap1, list(fifo_tap1_content)) self.assertListEqual(expected_result_tap2, list(fifo_tap2_content)) def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean()
class m26(object): ''' Mimosa26 telescope readout with MMC3 hardware. Note: - Remove not used Mimosa26 planes by commenting out the drivers in the DUT file (i.e. m26.yaml). - Set up trigger in DUT configuration file (i.e. m26_configuration.yaml). ''' def __init__(self, conf=None): if conf is None: conf = os.path.join(os.path.dirname(os.path.abspath(__file__)), "m26.yaml") logger.info("Loading DUT configuration from file %s" % conf) # initialize class self.dut = Dut(conf=conf) def init(self, init_conf=None, configure_m26=True): # initialize hardware logging.info("Initializing Telescope...") self.dut.init(init_conf=init_conf) self.telescope_conf = init_conf # check firmware version fw_version = self.dut['ETH'].read(0x0000, 1)[0] logging.info("Pymosa MMC3 firmware version: %s" % (fw_version)) if int(self.dut.version) != fw_version: raise Exception( "Pymosa MMC3 firmware version does not match DUT configuration file (read: %s, require: %s)" % (fw_version, int(self.dut.version))) # default configuration # use self.telescope_conf to store conf dict to telescope data file self.telescope_conf["fw_version"] = fw_version self.run_id = self.telescope_conf.get('run_id', 'M26_TELESCOPE') self.working_dir = self.telescope_conf.get("output_folder", None) if not self.working_dir: self.working_dir = os.path.join(os.getcwd(), "telescope_data") self.working_dir = os.path.normpath(self.working_dir.replace( '\\', '/')) self.output_filename = self.telescope_conf.get( 'filename', None) # default None: filename is generated if self.output_filename: self.output_filename = os.path.basename(self.output_filename) self.run_number = self.telescope_conf.get('run_number', None) self.m26_configuration_file = self.telescope_conf.get( 'm26_configuration_file', None) if not self.m26_configuration_file: self.m26_configuration_file = 'm26_config/m26_threshold_8.yaml' self.m26_jtag_configuration = self.telescope_conf.get( 'm26_jtag_configuration', True) # default True self.no_data_timeout = self.telescope_conf.get( 'no_data_timeout', 0) # default None: no data timeout self.scan_timeout = self.telescope_conf.get( 'scan_timeout', 0) # default 0: no scan timeout self.max_triggers = self.telescope_conf.get( 'max_triggers', 0) # default 0: infinity triggers self.send_data = self.telescope_conf.get( 'send_data', None) # default None: do not send data to online monitor self.enabled_m26_channels = self.telescope_conf.get( 'enabled_m26_channels', None) # default None: all channels enabled if not os.path.exists(self.working_dir): os.makedirs(self.working_dir) logger.info("Storing telescope data in %s" % self.working_dir) # configure Mimosa26 sensors if configure_m26: self.configure_m26() # FIFO readout self.m26_readout = M26Readout(dut=self.dut) def close(self): self.dut.close() def configure_m26(self, m26_configuration_file=None, m26_jtag_configuration=None): '''Configure Mimosa26 sensors via JTAG. ''' if m26_configuration_file: self.m26_configuration_file = m26_configuration_file else: m26_configuration_file = os.path.join( os.path.dirname(pymosa.__file__), self.m26_configuration_file) if not self.m26_configuration_file: raise ValueError('M26 configuration file not provided') logger.info('Loading M26 configuration file %s', m26_configuration_file) def write_jtag(irs, IR): for ir in irs: logger.info('Programming M26 JTAG configuration reg %s', ir) logger.debug(self.dut[ir][:]) self.dut['JTAG'].scan_ir([BitLogic(IR[ir])] * 6) self.dut['JTAG'].scan_dr([self.dut[ir][:]])[0] def check_jtag(irs, IR): # read first registers ret = {} for ir in irs: logger.info('Reading M26 JTAG configuration reg %s', ir) self.dut['JTAG'].scan_ir([BitLogic(IR[ir])] * 6) ret[ir] = self.dut['JTAG'].scan_dr([self.dut[ir][:]])[0] # check registers for k, v in ret.items(): if k == "CTRL_8b10b_REG1_ALL": pass elif k == "BSR_ALL": pass # TODO mask clock bits and check others elif self.dut[k][:] != v: logger.error("JTAG data does not match %s get=%s set=%s" % (k, v, self.dut[k][:])) else: logger.info("Checking M26 JTAG %s ok" % k) # set the clock distributer inputs in correct states. self.set_clock_distributer() # set M26 configuration file self.dut.set_configuration(m26_configuration_file) if m26_jtag_configuration is not None: self.m26_jtag_configuration = m26_jtag_configuration else: m26_jtag_configuration = self.m26_jtag_configuration if m26_jtag_configuration: # reset JTAG; this is important otherwise JTAG programming works not properly. self.dut['JTAG'].reset() IR = { "BSR_ALL": '00101', "DEV_ID_ALL": '01110', "BIAS_DAC_ALL": '01111', "LINEPAT0_REG_ALL": '10000', "DIS_DISCRI_ALL": '10001', "SEQUENCER_PIX_REG_ALL": '10010', "CONTROL_PIX_REG_ALL": '10011', "LINEPAT1_REG_ALL": '10100', "SEQUENCER_SUZE_REG_ALL": '10101', "HEADER_REG_ALL": '10110', "CONTROL_SUZE_REG_ALL": '10111', "CTRL_8b10b_REG0_ALL": '11000', "CTRL_8b10b_REG1_ALL": '11001', "RO_MODE1_ALL": '11101', "RO_MODE0_ALL": '11110', "BYPASS_ALL": '11111' } irs = [ "DEV_ID_ALL", "BIAS_DAC_ALL", "BYPASS_ALL", "BSR_ALL", "RO_MODE0_ALL", "RO_MODE1_ALL", "DIS_DISCRI_ALL", "LINEPAT0_REG_ALL", "LINEPAT1_REG_ALL", "CONTROL_PIX_REG_ALL", "SEQUENCER_PIX_REG_ALL", "HEADER_REG_ALL", "CONTROL_SUZE_REG_ALL", "SEQUENCER_SUZE_REG_ALL", "CTRL_8b10b_REG0_ALL", "CTRL_8b10b_REG1_ALL" ] # write JTAG configuration write_jtag(irs, IR) # check if registers are properly programmed by reading them and comparing to settings. check_jtag(irs, IR) # START procedure logger.info('Starting M26') temp = self.dut['RO_MODE0_ALL'][:] # disable extstart for reg in self.dut["RO_MODE0_ALL"]["RO_MODE0"]: reg['En_ExtStart'] = 0 reg['JTAG_Start'] = 0 self.dut['JTAG'].scan_ir([BitLogic(IR['RO_MODE0_ALL'])] * 6) self.dut['JTAG'].scan_dr([self.dut['RO_MODE0_ALL'][:]]) # JTAG start for reg in self.dut["RO_MODE0_ALL"]["RO_MODE0"]: reg['JTAG_Start'] = 1 self.dut['JTAG'].scan_ir([BitLogic(IR['RO_MODE0_ALL'])] * 6) self.dut['JTAG'].scan_dr([self.dut['RO_MODE0_ALL'][:]]) for reg in self.dut["RO_MODE0_ALL"]["RO_MODE0"]: reg['JTAG_Start'] = 0 self.dut['JTAG'].scan_ir([BitLogic(IR['RO_MODE0_ALL'])] * 6) self.dut['JTAG'].scan_dr([self.dut['RO_MODE0_ALL'][:]]) # write original configuration self.dut['RO_MODE0_ALL'][:] = temp self.dut['JTAG'].scan_ir([BitLogic(IR['RO_MODE0_ALL'])] * 6) self.dut['JTAG'].scan_dr([self.dut['RO_MODE0_ALL'][:]]) # readback? self.dut['JTAG'].scan_ir([BitLogic(IR['RO_MODE0_ALL'])] * 6) self.dut['JTAG'].scan_dr([self.dut['RO_MODE0_ALL'][:]] * 6) else: logger.info("Skipping M26 JTAG configuration") def set_clock_distributer(self, clk=0, start=1, reset=0, speak=1): # Default values -same as in GUI- (self, clk=0, start=1, reset=0, speak=1) self.dut["START_RESET"]["CLK"] = clk self.dut["START_RESET"]["START"] = start self.dut["START_RESET"]["RESET"] = reset self.dut["START_RESET"]["SPEAK"] = speak self.dut["START_RESET"].write() def reset(self, reset_time=2): self.dut["START_RESET"]["RESET"] = 1 self.dut["START_RESET"].write() sleep(reset_time) self.dut["START_RESET"]["RESET"] = 0 self.dut["START_RESET"].write() def scan(self): '''Scan Mimosa26 telescope loop. ''' with self.readout(enabled_m26_channels=self.enabled_m26_channels): got_data = False start = time() while not self.stop_scan: sleep(1.0) if not got_data: if self.m26_readout.data_words_per_second()[0] > 0: got_data = True logging.info('Taking data...') if self.max_triggers: self.pbar = tqdm(total=self.max_triggers, ncols=80) else: self.pbar = tqdm(total=self.scan_timeout, ncols=80) else: triggers = self.dut['TLU']['TRIGGER_COUNTER'] try: if self.max_triggers: self.pbar.update(triggers - self.pbar.n) else: self.pbar.update(time() - start - self.pbar.n) except ValueError: pass if self.max_triggers and triggers >= self.max_triggers: self.stop_scan = True self.pbar.close() logging.info('Trigger limit was reached: %i' % self.max_triggers) logging.info('Total amount of triggers collected: %d', self.dut['TLU']['TRIGGER_COUNTER']) def analyze(self): pass def start(self): '''Start Mimosa26 telescope scan. ''' self.stop_scan = False signal.signal(signal.SIGINT, self._signal_handler) logging.info('Press Ctrl-C to stop run') # check for filename that is not in use while True: if not self.output_filename and self.run_number: filename = 'run_' + str(self.run_number) + '_' + self.run_id else: if self.output_filename: filename = self.output_filename else: filename = strftime("%Y%m%d-%H%M%S") + '_' + self.run_id if filename in [ os.path.splitext(f)[0] for f in os.listdir(self.working_dir) if os.path.isfile(os.path.join(self.working_dir, f)) ]: if not self.output_filename and self.run_number: self.run_number += 1 # increase run number and try again continue else: raise IOError("Filename %s already exists." % filename) else: self.run_filename = os.path.join(self.working_dir, filename) break # set up logger self.fh = logging.FileHandler(self.run_filename + '.log') self.fh.setLevel(logging.DEBUG) self.fh.setFormatter(logging.Formatter(FORMAT)) self.logger = logging.getLogger() self.logger.addHandler(self.fh) with self.access_file(): save_configuration_dict(self.raw_data_file.h5_file, 'configuration', self.telescope_conf) self.scan() self.logger.removeHandler(self.fh) logging.info('Data Output Filename: %s', self.run_filename + '.h5') self.analyze() @contextmanager def readout(self, *args, **kwargs): try: self.start_readout(*args, **kwargs) yield finally: try: self.stop_readout(timeout=10.0) except Exception: # in case something fails, call this on last resort if self.m26_readout.is_running: self.m26_readout.stop(timeout=0.0) def start_readout(self, *args, **kwargs): '''Start readout of Mimosa26 sensors. ''' enabled_m26_channels = kwargs.get( 'enabled_m26_channels', None) # None will enable all existing Mimosa26 channels self.m26_readout.start(fifos="SITCP_FIFO", callback=self.handle_data, errback=self.handle_err, reset_rx=True, reset_fifo=True, no_data_timeout=self.no_data_timeout, enabled_m26_channels=enabled_m26_channels) self.dut['TLU']['MAX_TRIGGERS'] = self.max_triggers self.dut['TLU']['TRIGGER_ENABLE'] = True self.m26_readout.print_readout_status() def timeout(): self.stop_scan = True logging.info('Scan timeout was reached') self.scan_timeout_timer = Timer(self.scan_timeout, timeout) if self.scan_timeout: self.scan_timeout_timer.start() def stop_readout(self, timeout=10.0): '''Stop readout of Mimosa26 sensors. ''' self.scan_timeout_timer.cancel() self.dut['TLU']['TRIGGER_ENABLE'] = False self.m26_readout.stop(timeout=timeout) self.m26_readout.print_readout_status() @contextmanager def access_file(self): try: self.open_file() yield finally: try: self.close_file() except Exception: # in case something fails, call this on last resort self.raw_data_file = None def open_file(self): self.raw_data_file = open_raw_data_file(filename=self.run_filename, mode='w', title=os.path.basename( self.run_filename), socket_address=self.send_data) if self.raw_data_file.socket: # send reset to indicate a new scan for the online monitor send_meta_data(self.raw_data_file.socket, None, name='Reset') def close_file(self): # close file object self.raw_data_file.close() # delete file object self.raw_data_file = None def handle_data(self, data, new_file=False, flush=True): '''Handling of raw data and meta data during readout. ''' for data_tuple in data: if data_tuple is None: continue self.raw_data_file.append(data_iterable=data_tuple, new_file=new_file, flush=flush) def handle_err(self, exc): '''Handling of error messages during readout. ''' msg = '%s' % exc[1] if msg: logging.error('%s%s Aborting run...', msg, msg[-1]) else: logging.error('Aborting run...') self.stop_scan = True def _signal_handler(self, signum, frame): signal.signal( signal.SIGINT, signal.SIG_DFL ) # setting default handler... pressing Ctrl-C a second time will kill application logging.info('Pressed Ctrl-C') self.stop_scan = True
class TestRegisterHardwareLayer(unittest.TestCase): def setUp(self): self.dut = Dut(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer.yaml')) self.dut.init() def test_init_non_existing(self): with self.assertRaises(KeyError): self.dut.init({"test_register": {"NON_EXISTING": 1}}) def test_lazy_programming(self): self.dut['test_register'].set_default() self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_WO = 255 self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 255, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_WO # get value from write-only register, but this will write zero instead self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) def test_get_configuration(self): self.dut.set_configuration(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer_configuration.yaml')) conf = self.dut['test_register'].get_configuration() self.assertDictEqual({'REG1': 257, 'REG2': 1, 'REG3': 2, 'REG_TEST_INIT': 0, 'REG_BYTE_ARRAY': [1, 2, 3, 4]}, conf) def test_set_configuration(self): self.dut.set_configuration(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer_configuration.yaml')) self.assertDictEqual({0: 1, 1: 129, 2: 2, 3: 0, 5: 5, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) def test_set_configuration_non_existing(self): with self.assertRaises(KeyError): self.dut.set_configuration({"test_register": {"NON_EXISTING": 1}}) def test_read_only(self): self.assertRaises(IOError, self.dut['test_register']._set, 'REG4_RO', value=0) # def test_write_only(self): # self.assertRaises(IOError, self.dut['test_register']._get, 'REG5_WO') def test_write_only_lazy_programming(self): self.dut['test_register'].set_default() self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_WO = 20 self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 20, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_WO self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.assertIs(None, self.dut['test_register']._get('REG5_WO')) def test_set_default(self): self.dut['test_register'].set_default() self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) def test_set_attribute_add(self): val = self.dut['test_register']._registers['REG1']['default'] self.dut['test_register'].REG1 = val # 12 mem = self.dut['dummy_tl'].mem.copy() self.dut['test_register'].REG1 += 1 # 13 mem[0] = 13 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_write_read_reg(self): for reg in ['REG1', 'REG2', 'REG3']: val = self.dut['test_register']._registers[reg]['default'] self.dut['test_register']._set(reg, val) ret_val = self.dut['test_register']._get(reg) self.assertEqual(ret_val, val) self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) def test_set_attribute_by_value(self): self.dut['test_register'].set_default() self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) self.dut['test_register'].REG2 = 0 mem = self.dut['dummy_tl'].mem.copy() mem[1] = 0 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_set_attribute_by_string(self): mem = self.dut['dummy_tl'].mem.copy() self.dut['test_register'].REG3 = '1010101010101010' # dfghfghdfghgfdghf mem[2] = 170 mem[3] = 170 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_get_attribute_by_string(self): self.dut['test_register'].REG3 = '1010101010101010' # 43690 self.assertEqual(43690, self.dut['test_register'].REG3) def test_set_attribute_too_long_string(self): val = '11010101010101010' # 17 bit self.assertRaises(ValueError, self.dut['test_register']._set, 'REG3', value=val) def test_set_attribute_dict_access(self): self.dut['test_register']['REG1'] = 27306 # 27306 self.assertEqual(27306, self.dut['test_register']['REG1']) def test_set_attribute_too_big_val(self): val = 2 ** 16 # max 2 ** 16 - 1 self.assertRaises(ValueError, self.dut['test_register']._set, 'REG3', value=val) def test_set_by_function(self): self.dut['test_register'].set_REG1(27308) self.assertEqual(27308, self.dut['test_register']['REG1']) def test_get_by_function(self): self.dut['test_register']['REG1'] = 27305 # 27306 ret = self.dut['test_register'].get_REG1() self.assertEqual(ret, self.dut['test_register']['REG1']) def test_init_with_dict(self): self.dut['test_register'].set_default() self.dut.init({'test_register': _test_init}) conf = self.dut.get_configuration() self.assertDictEqual({'test_register': {'REG1': 120, 'REG2': 1, 'REG3': 65535, 'REG_TEST_INIT': 15, 'REG_BYTE_ARRAY': [4, 3, 2, 1]}, 'dummy_tl': {}}, conf) def test_get_dut_configuration(self): self.dut['test_register'].set_default() conf = self.dut.get_configuration() self.assertDictEqual({'test_register': {'REG1': 12, 'REG2': 1, 'REG3': 65535, 'REG_TEST_INIT': 0, 'REG_BYTE_ARRAY': [1, 2, 3, 4]}, 'dummy_tl': {}}, conf) def test_get_set_value(self): for val in range(256): self.dut['test_register'].set_value(val, 0, size=8, offset=0) ret_val = self.dut['test_register'].get_value(0, size=8, offset=0) self.assertEqual(ret_val, val) def test_write_read_reg_with_bit_str(self): val = '00110110' # 54 self.dut['test_register'].set_value(val, 0, size=8, offset=0) ret_val = self.dut['test_register'].get_value(0, size=8, offset=0) self.assertEqual(ret_val, int(val, base=2)) def test_write_read_reg_with_offset(self): for offset in range(32): val = 131 self.dut['test_register'].set_value(val, 0, size=8, offset=offset) ret_val = self.dut['test_register'].get_value(0, size=8, offset=offset) self.assertEqual(ret_val, val) def test_write_read_reg_with_size(self): for size in range(8, 33): val = 131 self.dut['test_register'].set_value(val, 0, size=size, offset=7) ret_val = self.dut['test_register'].get_value(0, size=size, offset=7) self.assertEqual(ret_val, val) def test_read_non_existing(self): with self.assertRaises(KeyError): self.dut['test_register'].NON_EXISTING with self.assertRaises(KeyError): self.dut['test_register']['NON_EXISTING'] with self.assertRaises(KeyError): self.dut['test_register'].get_NON_EXISTING() def test_write_non_existing(self): with self.assertRaises(KeyError): self.dut['test_register'].NON_EXISTING = 42 with self.assertRaises(KeyError): self.dut['test_register']['NON_EXISTING'] = 42 with self.assertRaises(KeyError): self.dut['test_register'].set_NON_EXISTING(42) def test_wrong_size(self): self.assertRaises(ValueError, self.dut['test_register'].set_value, 131, addr=0, size=7, offset=7)
class TestRegisterHardwareLayer(unittest.TestCase): def setUp(self): self.dut = Dut('test_RegisterHardwareLayer.yaml') self.dut.init() def test_lazy_programming(self): self.dut['test_register'].set_default() self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_wo = 255 self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 255, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.dut[ 'test_register'].REG5_wo # get value from write-only register, but this will write zero instead self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) def test_get_configuration(self): self.dut.set_configuration( 'test_RegisterHardwareLayer_configuration.yaml') conf = self.dut['test_register'].get_configuration() self.assertDictEqual( { 'REG1': 0, 'REG2': 1, 'REG3': 2, 'REG_test_init': 0, 'REG_byte_array': [1, 2, 3, 4] }, conf) def test_set_configuration(self): self.dut.set_configuration( 'test_RegisterHardwareLayer_configuration.yaml') self.assertDictEqual( { 0: 0, 1: 128, 2: 2, 3: 0, 5: 5, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) def test_read_only(self): self.assertRaises(IOError, self.dut['test_register']._set, 'REG4_ro', value=0) # def test_write_only(self): # self.assertRaises(IOError, self.dut['test_register']._get, 'REG5_wo') def test_write_only_lazy_programming(self): self.dut['test_register'].set_default() self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_wo = 20 self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 20, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.dut['test_register'].REG5_wo self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.assertIs(None, self.dut['test_register']._get('REG5_wo')) def test_set_default(self): self.dut['test_register'].set_default() self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) def test_set_attribute_add(self): val = self.dut['test_register']._registers['REG1']['default'] self.dut['test_register'].REG1 = val # 12 mem = self.dut['dummy_tl'].mem.copy() self.dut['test_register'].REG1 += 1 # 13 mem[0] = 13 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_write_read_reg(self): for reg in ['REG1', 'REG2', 'REG3']: val = self.dut['test_register']._registers[reg]['default'] self.dut['test_register']._set(reg, val) ret_val = self.dut['test_register']._get(reg) self.assertEqual(ret_val, val) self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) def test_set_attribute_by_value(self): self.dut['test_register'].set_default() self.assertDictEqual( { 0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4 }, self.dut['dummy_tl'].mem) self.dut['test_register'].REG2 = 0 mem = self.dut['dummy_tl'].mem.copy() mem[1] = 0 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_set_attribute_by_string(self): mem = self.dut['dummy_tl'].mem.copy() self.dut[ 'test_register'].REG3 = '1010101010101010' # dfghfghdfghgfdghf mem[2] = 170 mem[3] = 170 self.assertDictEqual(mem, self.dut['dummy_tl'].mem) def test_get_attribute_by_string(self): self.dut['test_register'].REG3 = '1010101010101010' # 43690 self.assertEqual(43690, self.dut['test_register'].REG3) def test_set_attribute_too_long_string(self): val = '11010101010101010' # 17 bit self.assertRaises(ValueError, self.dut['test_register']._set, 'REG3', value=val) def test_set_attribute_dict_access(self): self.dut['test_register']['REG1'] = 27306 # 27306 self.assertEqual(27306, self.dut['test_register']['REG1']) def test_set_attribute_too_big_val(self): val = 2**16 # max 2 ** 16 - 1 self.assertRaises(ValueError, self.dut['test_register']._set, 'REG3', value=val) def test_set_by_function(self): self.dut['test_register'].set_REG1(27308) self.assertEqual(27308, self.dut['test_register']['REG1']) def test_get_by_function(self): self.dut['test_register']['REG1'] = 27305 # 27306 ret = self.dut['test_register'].get_REG1() self.assertEqual(ret, self.dut['test_register']['REG1']) def test_init_with_dict(self): self.dut['test_register'].set_default() self.dut.init({'test_register': _test_init}) conf = self.dut.get_configuration() self.assertDictEqual( { 'test_register': { 'REG1': 120, 'REG2': 1, 'REG3': 65535, 'REG_test_init': 15, 'REG_byte_array': [4, 3, 2, 1] }, 'dummy_tl': {} }, conf) def test_get_dut_configuration(self): self.dut['test_register'].set_default() conf = self.dut.get_configuration() self.assertDictEqual( { 'test_register': { 'REG1': 12, 'REG2': 1, 'REG3': 65535, 'REG_test_init': 0, 'REG_byte_array': [1, 2, 3, 4] }, 'dummy_tl': {} }, conf)
class TestSimJtagGpio(unittest.TestCase): def setUp(self): cocotb_compile_and_run([ os.path.join(os.path.dirname(__file__), 'jtag_tap.v'), os.path.join(os.path.dirname(__file__), 'test_SimJtagGpio.v')] ) self.chip = Dut(cnfg_yaml) self.chip.init(init_yaml) def test_gpio(self): ID_CODE = BitLogic('0010') BYPASS = BitLogic('1111') DEBUG = BitLogic('1000') ret_ir = BitLogic('0101') # TEST REG INIT dev1ret = StdRegister(driver=None, conf=yaml.load(gpio_yaml)) dev1ret.init() dev1ret['F1'] = 0x1 dev1ret['F2'] = 0x2f dev1ret['F3'] = 0x2 dev1ret['F4'] = 0x17cf4 self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.chip['DEV1']['F2'] = 0 self.assertFalse(dev1ret[:] == self.chip['DEV1'][:]) self.chip.set_configuration(init_yaml) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.chip['jtag'].reset() # IR CODE ret = self.chip['jtag'].scan_ir([ID_CODE] * 2) self.assertEqual(ret, [ret_ir] * 2) # ID CODE id_code = BitLogic.from_value(0x149B51C3, fmt='I') ret = self.chip['jtag'].scan_dr(['0' * 32] * 2) self.assertEqual(ret, [id_code] * 2) # BYPASS + ID CODE bypass_code = BitLogic('0') ret = self.chip['jtag'].scan_ir([ID_CODE, BYPASS]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip['jtag'].scan_dr(['0' * 32, '1']) self.assertEqual(ret, [id_code, bypass_code]) ret = self.chip['jtag'].scan_ir([BYPASS, ID_CODE]) self.assertEqual(ret, [ret_ir] * 2) ret = self.chip['jtag'].scan_dr(['1', '0' * 32]) self.assertEqual(ret, [bypass_code, id_code]) # DEBUG ret = self.chip['jtag'].scan_ir([DEBUG, DEBUG]) self.assertEqual(ret, [ret_ir] * 2) self.chip['jtag'].scan_dr(['1' * 32, '0' * 1 + '1' * 30 + '0' * 1]) ret = self.chip['jtag'].scan_dr(['0' * 32, '1' * 32]) self.assertEqual(ret, [BitLogic('1' * 32), BitLogic('0' * 1 + '1' * 30 + '0' * 1)]) ret = self.chip['jtag'].scan_dr(['0' * 32, '0' * 32]) self.assertEqual(ret, [BitLogic('0' * 32), BitLogic('1' * 32)]) # SHIT IN DEV REG/DEBUG self.chip['jtag'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) # GPIO RETURN dev1ret.frombytes(self.chip['gpio_dev1'].get_data()) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) self.assertFalse(dev1ret[:] == self.chip['DEV2'][:]) dev1ret.frombytes(self.chip['gpio_dev2'].get_data()) self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) # JTAG RETURN ret = self.chip['jtag'].scan_dr(['0' * 32, '0' * 32]) dev1ret.set(ret[0]) self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) dev1ret.set(ret[1]) self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) # REPEATING REGISTER self.chip['jtag'].scan_dr([self.chip['DEV'][:]]) ret1 = self.chip['jtag'].scan_dr([self.chip['DEV'][:]]) self.chip['jtag'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) ret2 = self.chip['jtag'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) ret3 = self.chip['jtag'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) self.assertEqual(ret1[:], ret2[:]) self.assertEqual(ret2[:], ret3[:]) # REPEATING SETTING self.chip['jtag'].scan_dr(['1' * 32 + '0' * 32]) ret = self.chip['jtag'].scan_dr(['0' * 32 + '0' * 32]) self.chip['DEV'].set(ret[0]) self.assertEqual(self.chip['DEV'][:], BitLogic('0' * 32 + '1' * 32)) self.chip['jtag'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) ret = self.chip['jtag'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) self.chip['DEV'].set(ret[0]) self.assertEqual(self.chip['DEV'][:], self.chip['DEV1'][:] + self.chip['DEV2'][:]) def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean()