def test_configurable_model_smoke(): EXPECTED_MSG = repr( TypeError( "Can't instantiate abstract class _ConfigurableModel with abstract methods __call__" )) # nopep8 has_type_error = False try: my_model = ConfigurableModel(32, 32)() except TypeError as e: msg = e.__repr__() has_type_error = True assert has_type_error assert msg == EXPECTED_MSG
class MemoryCore(ConfigurableModel(32, 32)): def __init__(self): super().__init__() self.reset() def configure(self, addr, data): self.config[addr] = data def reset(self): address_width = m.bitutils.clog2(data_depth) self.memory = Memory(address_width, data_width) self.data_out = fault.UnknownValue self.read_data = fault.UnknownValue # TODO: Is the initial config actually 0? self.configure(CONFIG_ADDR, BitVector(0, 32)) # Ignore these signals for now self.valid_out = fault.UnknownValue self.chain_out = fault.UnknownValue self.chain_valid_out = fault.UnknownValue self.almost_full = fault.UnknownValue self.almost_empty = fault.UnknownValue self.read_data_sram = fault.UnknownValue self.read_data_linebuf = fault.UnknownValue def read(self, addr): if self.__mode == Mode.SRAM: self.data_out = self.memory.read(addr) else: raise NotImplementedError(self.__mode) # pragma: nocover def write(self, addr, data): if self.__mode == Mode.SRAM: self.memory.write(addr, data) else: raise NotImplementedError(self.__mode) # pragma: nocover def read_and_write(self, addr, data): # write takes priority self.write(addr, data) def __call__(self, *args, **kwargs): raise NotImplementedError() @property def __mode(self): """ The mode is stored in the lowest 2 (least significant) bits of the configuration data. """ return Mode((self.config[CONFIG_ADDR] & 0x3).as_uint())
class _GlobalController(ConfigurableModel(32, 32)): def __init__(self): super().__init__() self.num_stall_domains = 4 self.reset() def reset(self): self.TST = [BitVector[config_data_width](0)] self.stall = [BitVector[self.num_stall_domains](0)] self.clk_sel = [BitVector[1](0)] self.rw_delay_sel = [BitVector[config_data_width](2)] self.clk_switch_delay_sel = [BitVector[1](0)] self.reset_out = [0] self.config_addr_out = [BitVector[config_addr_width](0)] self.config_data_out = [BitVector[config_data_width](0)] self.config_data_in = fault.UnknownValue self.read = [0] self.write = [0] self.config_data_to_jtag = [BitVector[config_data_width](0)] def config_read(self, addr): rw_delay = self.rw_delay_sel[0] duration = rw_delay.as_uint() self.read = [1] * duration + [0] self.write = [0] * (duration + 1) self.config_addr_out = [BitVector[config_addr_width](addr)] \ * (duration + 1) self.config_data_to_jtag = [self.config_data_to_jtag[-1]] \ + [self.config_data_in] * duration def config_write(self, addr, data): rw_delay = self.rw_delay_sel[0] duration = rw_delay.as_uint() self.read = [0] * (duration + 1) self.write = [1] * duration + [0] self.config_addr_out = [BitVector[config_addr_width](addr)] \ * (duration + 1) self.config_data_out = [BitVector[config_data_width](data)] \ * (duration + 1) def read_gc_reg(self, addr): if (addr == GCRegAddr.TST_ADDR): out = self.TST[-1] elif (addr == GCRegAddr.STALL_ADDR): out = self.stall[-1] elif (addr == GCRegAddr.CLK_SEL_ADDR): out = self.clk_sel[-1] elif (addr == GCRegAddr.RW_DELAY_SEL_ADDR): out = self.rw_delay_sel[-1] elif (addr == GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR): out = self.clk_switch_delay_sel[-1] else: raise ValueError("Reading from invalid GC_reg address") self.config_data_to_jtag = [BitVector[config_data_width](out)] def write_gc_reg(self, addr, data): if (addr == GCRegAddr.TST_ADDR): self.TST = [BitVector[config_data_width](data)] elif (addr == GCRegAddr.STALL_ADDR): self.stall = [BitVector[self.num_stall_domains](data)] elif (addr == GCRegAddr.CLK_SEL_ADDR): self.clk_sel = [BitVector[1](data)] elif (addr == GCRegAddr.RW_DELAY_SEL_ADDR): self.rw_delay_sel = [BitVector[config_data_width](data)] elif (addr == GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR): self.clk_switch_delay_sel = [BitVector[1](data)] else: raise ValueError("Writing to invalid GC_reg address") def global_reset(self, data): if (data > 0): self.reset_out = [1] * data + [0] else: self.reset_out = [1] * 20 + [0] def wr_A050(self): self.config_data_to_jtag = [BitVector[config_data_width](0xA050)] def advance_clk(self, addr, data): save_stall_reg = self.stall[-1] temp_stall_reg = BitVector[self.num_stall_domains](0) mask = BitVector[self.num_stall_domains](addr) for i in range(self.num_stall_domains): if (mask[i] == 1): temp_stall_reg[i] = 0 self.stall = [temp_stall_reg] * data + [save_stall_reg] def set_config_data_in(self, data): self.config_data_in = BitVector[config_data_width](data) def __cleanup(self): # Remove sequences from outputs/regs in preparation for the next # op. self.stall = [self.stall[-1]] self.config_addr_out = [self.config_addr_out[-1]] self.config_data_out = [self.config_data_out[-1]] self.read = [self.read[-1]] self.write = [self.write[-1]] self.config_data_to_jtag = [self.config_data_to_jtag[-1]] def __call__(self, **kwargs): self.__cleanup() # Op is mandatory. Other args are optional op = kwargs['op'] if 'data' in kwargs: data = kwargs['data'] if 'addr' in kwargs: addr = kwargs['addr'] # Decode op if (op == GCOp.CONFIG_WRITE): self.config_write(addr, data) if (op == GCOp.CONFIG_READ): self.config_read(addr) elif (op == GCOp.WRITE_A050): self.wr_A050() elif (op == GCOp.WRITE_TST): self.write_gc_reg(GCRegAddr.TST_ADDR, data) elif (op == GCOp.READ_TST): self.read_gc_reg(GCRegAddr.TST_ADDR) elif (op == GCOp.GLOBAL_RESET): self.global_reset(data) elif (op == GCOp.WRITE_STALL): self.write_gc_reg(GCRegAddr.STALL_ADDR, data) elif (op == GCOp.READ_STALL): self.read_gc_reg(GCRegAddr.STALL_ADDR) elif (op == GCOp.ADVANCE_CLK): self.advance_clk(addr, data) elif (op == GCOp.READ_CLK_DOMAIN): self.read_gc_reg(GCRegAddr.CLK_SEL_ADDR) elif (op == GCOp.SWITCH_CLK): self.write_gc_reg(GCRegAddr.CLK_SEL_ADDR, data) elif (op == GCOp.WRITE_RW_DELAY_SEL): self.write_gc_reg(GCRegAddr.RW_DELAY_SEL_ADDR, data) elif (op == GCOp.READ_RW_DELAY_SEL): self.read_gc_reg(GCRegAddr.RW_DELAY_SEL_ADDR) elif (op == GCOp.WRITE_CLK_SWITCH_DELAY_SEL): self.write_gc_reg(GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR, data) elif (op == GCOp.READ_CLK_SWITCH_DELAY_SEL): self.read_gc_reg(GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR) return self
class Foo(ConfigurableModel(32, 32)): def __init__(self): super().__init__() def __call__(self): return 0
class MemoryCore(ConfigurableModel(32, 32)): _data_depth = 1024 # Include functional models _fifo_model = kam.define_fifo() _sram_model = kam.define_sram() ___mode = 0 _switch = 0 def __init__(self): super().__init__() self.reset() def configure(self, addr, data): self.config[addr] = data def reset(self): address_width = m.bitutils.clog2(data_depth) self.memory = Memory(address_width, data_width) self.data_out = fault.UnknownValue self.read_data = fault.UnknownValue self.configure(CONFIG_ADDR, BitVector[32](0)) # Ignore these signals for now self.valid_out = fault.UnknownValue self.chain_out = fault.UnknownValue self.chain_valid_out = fault.UnknownValue self.almost_full = fault.UnknownValue self.almost_empty = fault.UnknownValue self.read_data_sram = fault.UnknownValue self.read_data_linebuf = fault.UnknownValue def set_mode(self, newmode): self.___mode = newmode def switch(self): if self.__mode == Mode.DB: self._db_model.switch() else: raise NotImplementedError(self.__mode) # pragma: nocover def read(self, addr=0): if self.__mode == Mode.SRAM: self._sram_model.addr = addr self.data_out = self._sram_model.read() elif self.__mode == Mode.FIFO: self.data_out = self._fifo_model.dequeue() elif self.__mode == Mode.DB: self.data_out = self._db_model.read(0, addr)[0] else: raise NotImplementedError(self.__mode) # pragma: nocover def write(self, addr, data): # SRAM if self.__mode == Mode.SRAM: self._sram_model.data_in = data self._sram_model.addr = addr self._sram_model.write() # DB elif self.__mode == Mode.DB: self._db_model.write(data) # FIFO elif self.__mode == Mode.FIFO: self._fifo_model.data_in = data self._fifo_model.enqueue() else: raise NotImplementedError(self.__mode) # pragma: nocover def config_fifo(self, depth): self._fifo_model.configure(memory_size=self._data_depth, capacity=depth) self._fifo_model.reset() self.set_mode(Mode.FIFO) def config_sram(self, mem_size): self._sram_model.configure(memory_size=mem_size) self._sram_model.reset() self.set_mode(Mode.SRAM) def config_db(self, capacity, ranges, strides, start, manual_switch, dimension, arb_addr=0): setup = {} setup["virtual buffer"] = {} setup["virtual buffer"]["input_port"] = 1 setup["virtual buffer"]["output_port"] = 1 setup["virtual buffer"]["capacity"] = capacity setup["virtual buffer"]["access_pattern"] = {} setup["virtual buffer"]["access_pattern"]["start"] = [start] setup["virtual buffer"]["access_pattern"]["range"] = \ ranges[0:dimension] setup["virtual buffer"]["access_pattern"]["stride"] = \ strides[0:dimension] setup["virtual buffer"]["manual_switch"] = manual_switch setup["virtual buffer"]["arbitrary_addr"] = arb_addr self._db_model = bam.CreateVirtualBuffer(setup["virtual buffer"]) self.set_mode(Mode.DB) def read_and_write(self, addr, data): # write takes priority if self.__mode == Mode.SRAM: self.write(addr, data) elif self.__mode == Mode.FIFO: self._fifo_model.data_in = data self._fifo_model.enqueue() self.data_out = self._fifo_model.dequeue() elif self.__mode == Mode.DB: self._db_model.write(data) self.data_out = self._db_model.read(0, addr)[0] else: raise NotImplementedError(self.__mode) # pragma: nocover def __call__(self, *args, **kwargs): raise NotImplementedError() # pragma: nocover @property def __mode(self): """ The mode is stored in the lowest 2 (least significant) bits of the configuration data. """ return Mode(self.___mode)