def __init__(self, address, write, writeEnable, reset, clock, read, mode=DEFAULT_MODE, default_size=DEFAULT_SIZE, default_value=DEFAULT_STATE, edge_type=DEFAULT_LATCH_TYPE, rst_type=DEFAULT_RESET_TYPE, memwr_type=DEFAULT_ENABLE_TYPE): """ Buses address : bus of size at least as large as size to map to cells write : word sized bus (32-bit) to write to addressed cell writeEnable : enable line to save write data to memory on clock edge reset : System reset line to clear memory clock: System clock line to store memory read : word sized bus (32-bit) to read from addressed cell mode : 2-bit bus signaling read type of memory 0 = memory off (return 0) (no write) 1 = byte access (read/write ignores upper bits) 2 = half-word access (read/write ignores upper bits) 3 = word access (default) Configuration default_size : size of program memory space in bytes default_value : byte value to load into unassigned memory cells edge_type : Store data on this clock edge rst_type : Activation state for reset line memwr_type : Activation state for storing on write clock edge """ # handle optional accessMode bus if mode is None: mode = Constant(2, 3) # ghost memory on bus to lower needed bits if default_size < 0: raise ValueError('Size must be within valid range') elif default_size == 0: size = 0 elif default_size < 2: size = 1 else: # len > 2 size = int(math.floor(math.log(default_size - 1, 2) + 1)) self._address_general = Bus(size) self._address_subset = BusSubset(address, [self._address_general], [(0, size)]) # Construct generalized memory passing parameters Memory.__init__(self, default_size, 4, 0, self._address_general, write, writeEnable, reset, clock, mode, read, default_value, edge_type, rst_type, memwr_type)
def __init__(self, c_in, v_in, n_in, z_in, rst, clk, en, c_out, v_out, n_out, z_out, default_state=DEFAULT_STATE, edge_type=DEFAULT_LATCH_TYPE, reset_type=DEFAULT_RESET_TYPE, enable_type=DEFAULT_ENABLE_TYPE): """ Constructor will check for valid parameters, exception thrown on invalid Parameters c_in: 1-bit input of 'c' v_in: 1-bit input of 'v' n_in: 1-bit input of 'n' z_in: 1-bit input of 'z' rst: Register reset clk: Register clock en: Register write enable c_out: 1-bit output of 'c' v_out: 1-bit output of 'v' n_out: 1-bit output of 'n' z_out: 1-bit output of 'z' default_state: Initial 4-bit state of ALU Flag edge_type: Clock state change to store flags reset_type: Asynchronous reset to default_state value enable_type: State to allow write to register """ if not isinstance(c_in, iBusRead) or not c_in.size() == 1: raise TypeError('c in must be a 1-bit readable bus') if not isinstance(v_in, iBusRead) or not v_in.size() == 1: raise TypeError('v in must be a 1-bit readable bus') if not isinstance(n_in, iBusRead) or not n_in.size() == 1: raise TypeError('n in must be a 1-bit readable bus') if not isinstance(z_in, iBusRead) or not z_in.size() == 1: raise TypeError('z in must be a 1-bit readable bus') if not isinstance(c_out, iBusWrite) or not c_out.size() == 1: raise TypeError('c out must be a 1-bit readable bus') if not isinstance(v_out, iBusWrite) or not v_out.size() == 1: raise TypeError('v out must be a 1-bit readable bus') if not isinstance(n_out, iBusWrite) or not n_out.size() == 1: raise TypeError('n out must be a 1-bit readable bus') if not isinstance(z_out, iBusWrite) or not z_out.size() == 1: raise TypeError('z out must be a 1-bit readable bus') self._flag_in = Bus(4) self._join = BusJoin([c_in, v_in, n_in, z_in], self._flag_in) self._flag_out = Bus(4) self._subset = BusSubset(self._flag_out, [c_out, v_out, n_out, z_out], [(0, 1), (1, 2), (2, 3), (3, 4)]) Register.__init__(self, 4, clk, rst, self._flag_in, self._flag_out, default_state, edge_type, reset_type, en, enable_type)
def test_run(self): "Prove correct combinational output given signals" c0 = Constant(16, 0xAAAA) b0 = Bus(4) b1 = Bus(8) b2 = Bus(2) b3 = Bus(2) b4 = Bus(1) bs = BusSubset(c0, [b0, b1, b2, b3, b4], [(0, 4), (4, 12), (12, 14), (14, 16), (3, 4)]) bs.run() self.assertTrue(b0.read() == 0x0A) self.assertTrue(b1.read() == 0xAA) self.assertTrue(b2.read() == 0x02) self.assertTrue(b3.read() == 0x02) self.assertTrue(b4.read() == 1)
def __init__(self, address, rst, read, default_size=DEFAULT_SIZE, default_value=DEFAULT_STATE, rst_type=DEFAULT_RESET_TYPE): """ Buses address : word sized address bus to access program memory rst : Reset bus to clear memory read : word sized bus with addressed instruction Configuration default_size : size of program memory space in bytes default_value : byte value to load into unassigned memory cells rst_type : Activation state for reset line """ # disable write behavior self._wd_const = Constant(32, 0) self._we_const = Constant(1, 0) self._clk_const = Constant(1, 0) # default mode to word access self._mode_const = Constant(2, 3) # ghost memory on bus to lower needed bits if default_size == 0: size = 0 elif default_size < 2: size = 1 else: # len > 2 size = int(math.floor(math.log(default_size - 1, 2) + 1)) self._address_general = Bus(size) self._address_subset = BusSubset(address, [self._address_general], [(0, size)]) # Construct generalized memory passing parameters Memory.__init__(self, default_size, 4, 0, self._address_general, self._wd_const, self._we_const, rst, self._clk_const, self._mode_const, read, default_value, Latch_Type.FALLING_EDGE, rst_type, Logic_States.ACTIVE_HIGH)
def test_from_dict(self): "Validates dictionary constructor" hooks = OrderedDict({ "i1": Constant(8, 0x0F), "o1": Bus(4), "o2": Bus(4) }) config = { "input": "i1", "outputs": ["o1", "o2"], "bounds": [[0, 4], [4, 8]] } subset = BusSubset.from_dict(config, hooks) subset.run() self.assertEqual(hooks["o1"].read(), 0xF) self.assertEqual(hooks["o2"].read(), 0x0)
class DataMemory(Memory): """ ARM specific data memory with 32-bit word size. Thsi component is to be used to store data during execution of architecture. Note to change state during operation, use modify functionality. Note that address space is ghosted if the address bus is greater than the size defined for the module. """ DEFAULT_MODE = None DEFAULT_SIZE = 4096 DEFAULT_STATE = 0x81 DEFAULT_LATCH_TYPE = Latch_Type.RISING_EDGE DEFAULT_RESET_TYPE = Logic_States.ACTIVE_HIGH DEFAULT_ENABLE_TYPE = Logic_States.ACTIVE_HIGH def __init__(self, address, write, writeEnable, reset, clock, read, mode=DEFAULT_MODE, default_size=DEFAULT_SIZE, default_value=DEFAULT_STATE, edge_type=DEFAULT_LATCH_TYPE, rst_type=DEFAULT_RESET_TYPE, memwr_type=DEFAULT_ENABLE_TYPE): """ Buses address : bus of size at least as large as size to map to cells write : word sized bus (32-bit) to write to addressed cell writeEnable : enable line to save write data to memory on clock edge reset : System reset line to clear memory clock: System clock line to store memory read : word sized bus (32-bit) to read from addressed cell mode : 2-bit bus signaling read type of memory 0 = memory off (return 0) (no write) 1 = byte access (read/write ignores upper bits) 2 = half-word access (read/write ignores upper bits) 3 = word access (default) Configuration default_size : size of program memory space in bytes default_value : byte value to load into unassigned memory cells edge_type : Store data on this clock edge rst_type : Activation state for reset line memwr_type : Activation state for storing on write clock edge """ # handle optional accessMode bus if mode is None: mode = Constant(2, 3) # ghost memory on bus to lower needed bits if default_size < 0: raise ValueError('Size must be within valid range') elif default_size == 0: size = 0 elif default_size < 2: size = 1 else: # len > 2 size = int(math.floor(math.log(default_size - 1, 2) + 1)) self._address_general = Bus(size) self._address_subset = BusSubset(address, [self._address_general], [(0, size)]) # Construct generalized memory passing parameters Memory.__init__(self, default_size, 4, 0, self._address_general, write, writeEnable, reset, clock, mode, read, default_value, edge_type, rst_type, memwr_type) def run(self, time=None): """ Update address sub-entities before calling general memory run operation """ self._address_subset.run(time) Memory.run(self, time) @classmethod def from_dict(cls, config, hooks): "Implements conversion from configuration to component" if "mode" in config: mode = hooks[config["mode"]] else: mode = DataMemory.DEFAULT_MODE if "size" in config: size = config["size"] else: size = DataMemory.DEFAULT_SIZE if "value" in config: value = config["value"] else: value = DataMemory.DEFAULT_STATE if "edge_type" in config: edge_type = Latch_Type.fromString(config["edge_type"]) else: edge_type = DataMemory.DEFAULT_LATCH_TYPE if "reset_type" in config: reset_type = Logic_States.fromString(config["reset_type"]) else: reset_type = DataMemory.DEFAULT_RESET_TYPE if "enable_type" in config: enable_type = Logic_States.fromString(config["enable_type"]) else: enable_type = DataMemory.DEFAULT_ENABLE_TYPE return DataMemory(hooks[config["address"]], hooks[config["write"]], hooks[config["write_enable"]], hooks[config["reset"]], hooks[config["clock"]], hooks[config["read"]], mode, size, value, edge_type, reset_type, enable_type)
def generate_single_cycle_architecture(): "Illustrates the necessary process to construct an architecture" # define system resources clk = Clock(10, 0) rst = Reset(0) hooks = OrderedDict([('clk', clk), ('rst', rst)]) # define input hooks and constants hooks.update({'const8': Constant(32, 8)}) hooks.update({'const4': Constant(32, 4)}) hooks.update({'const14': Constant(4, 14)}) # define buses hooks.update({'pc': Bus(32, 0)}) hooks.update({'pc8': Bus(32, 0)}) hooks.update({'pc4': Bus(32, 0)}) hooks.update({'instr': Bus(32, 0)}) hooks.update({'instr_23_0': Bus(24, 0)}) hooks.update({'instr_19_16': Bus(4, 0)}) hooks.update({'instr_3_0': Bus(4, 0)}) hooks.update({'instr_15_12': Bus(4, 0)}) hooks.update({'instr_11_8': Bus(4, 0)}) hooks.update({'instr_31_28': Bus(4, 0)}) hooks.update({'instr_27_26': Bus(2, 0)}) hooks.update({'instr_25_20': Bus(6, 0)}) hooks.update({'instr_4_4': Bus(1, 0)}) hooks.update({'imm32': Bus(32, 0)}) hooks.update({'ra1': Bus(4, 0)}) hooks.update({'ra2': Bus(4, 0)}) hooks.update({'ra3': Bus(4, 0)}) hooks.update({'rwd': Bus(32, 0)}) hooks.update({'rd1': Bus(32, 0)}) hooks.update({'rd2': Bus(32, 0)}) hooks.update({'alub': Bus(32, 0)}) hooks.update({'branch': Bus(32, 0)}) hooks.update({'aluf': Bus(32, 0)}) hooks.update({'aluc': Bus(1, 0)}) hooks.update({'aluv': Bus(1, 0)}) hooks.update({'alun': Bus(1, 0)}) hooks.update({'aluz': Bus(1, 0)}) hooks.update({'aluflag': Bus(4, 0)}) hooks.update({'flag': Bus(4, 0)}) hooks.update({'c': Bus(1, 0)}) hooks.update({'v': Bus(1, 0)}) hooks.update({'n': Bus(1, 0)}) hooks.update({'z': Bus(1, 0)}) hooks.update({'memrd': Bus(32, 0)}) hooks.update({'wdb': Bus(32, 0)}) hooks.update({'pcwb': Bus(32, 0)}) # control signals hooks.update({'pcwr': Bus(1, 0)}) hooks.update({'regsa': Bus(1, 0)}) hooks.update({'regdst': Bus(2, 0)}) hooks.update({'regwrs': Bus(2, 0)}) hooks.update({'wdbs': Bus(1, 0)}) hooks.update({'regwr': Bus(1, 0)}) hooks.update({'exts': Bus(2, 0)}) hooks.update({'alu8rcb': Bus(1, 0)}) hooks.update({'alus': Bus(4, 0)}) hooks.update({'aluflagwr': Bus(1, 0)}) hooks.update({'memwr': Bus(1, 0)}) hooks.update({'regsrc': Bus(1, 0)}) hooks.update({'pcsrc': Bus(2, 0)}) # generate components # FETCH entities = OrderedDict([('clk', clk)]) entities.update({'pc_reg': Register(32, hooks['clk'], hooks['rst'], hooks['pcwb'], hooks['pc'], 0, enable=hooks['pcwr'], edge_type=Latch_Type.FALLING_EDGE)}) entities.update({'add8': Adder(32, hooks['pc'], hooks['const8'], hooks['pc8'])}) entities.update({'add4': Adder(32, hooks['pc'], hooks['const4'], hooks['pc4'])}) entities.update({'progmem': ProgramMemory(hooks['pc'], hooks['rst'], hooks['instr'])}) # DECODE entities.update({'instr_subset': BusSubset(hooks['instr'], [hooks['instr_23_0'], hooks['instr_19_16'], hooks['instr_3_0'], hooks['instr_15_12'], hooks['instr_11_8'], hooks['instr_31_28'], hooks['instr_27_26'], hooks['instr_25_20'], hooks['instr_4_4']], [(0, 24), (16, 20), (0, 4), (12, 16), (8, 12), (28, 32), (26, 28), (20, 26), (4, 5)])}) entities.update({'controller': ControllerSingleCycle(hooks['instr_31_28'], hooks['instr_27_26'], hooks['instr_25_20'], hooks['instr_15_12'], hooks['instr_4_4'], hooks['c'], hooks['v'], hooks['n'], hooks['z'], hooks['pcsrc'], hooks['pcwr'], hooks['regsa'], hooks['regdst'], hooks['regwrs'], hooks['regwr'], hooks['exts'], hooks['alu8rcb'], hooks['alus'], hooks['aluflagwr'], hooks['memwr'], hooks['regsrc'], hooks['wdbs'])}) entities.update({'ra1_mux': Mux(4, [hooks['instr_3_0'], hooks['instr_19_16']], hooks['regsa'], hooks['ra1'])}) entities.update({'ra2_mux': Mux(4, [hooks['instr_11_8'], hooks['instr_3_0'], hooks['instr_15_12']], hooks['regdst'], hooks['ra2'])}) entities.update({'ra3_mux': Mux(4, [hooks['instr_19_16'], hooks['instr_15_12'], hooks['const14']], hooks['regwrs'], hooks['ra3'])}) entities.update({'rwd_mux': Mux(32, [hooks['wdb'], hooks['pc4']], hooks['wdbs'], hooks['rwd'])}) entities.update({'extimm': Extender(hooks['instr_23_0'], hooks['exts'], hooks['imm32'])}) entities.update({'regfile': RegisterFile(hooks['clk'], hooks['rst'], hooks['regwr'], hooks['rwd'], hooks['ra1'], hooks['ra2'], hooks['ra3'], hooks['rd1'], hooks['rd2'])}) # EXECUTE entities.update({'alu_mux': Mux(32, [hooks['imm32'], hooks['rd2']], hooks['alu8rcb'], hooks['alub'])}) entities.update({'add_br': Adder(32, hooks['pc8'], hooks['imm32'], hooks['branch'])}) entities.update({'alu': Alu(hooks['rd1'], hooks['alub'], hooks['alus'], hooks['aluf'], hooks['aluc'], hooks['aluv'], hooks['alun'], hooks['aluz'])}) entities.update({'aluflag_reg': ALUFlagRegister(hooks['aluc'], hooks['aluv'], hooks['alun'], hooks['aluz'], hooks['rst'], hooks['clk'], hooks['aluflagwr'], hooks['c'], hooks['v'], hooks['n'], hooks['z'])}) # MEMORY & WRITE-BACK entities.update({'datamem': DataMemory(hooks['aluf'], hooks['rd2'], hooks['memwr'], hooks['rst'], hooks['clk'], hooks['memrd'])}) entities.update({'wdb_mux': Mux(32, [hooks['memrd'], hooks['aluf']], hooks['regsrc'], hooks['wdb'])}) entities.update({'pcwb_mux': Mux(32, [hooks['branch'], hooks['pc4'], hooks['wdb']], hooks['pcsrc'], hooks['pcwb'])}) # place memory (Internal) hooks into hook list hooks.update({'pc_reg': entities['pc_reg']}) hooks.update({'progmem': entities['progmem']}) hooks.update({'regfile': entities['regfile']}) hooks.update({'aluflag_reg': entities['aluflag_reg']}) hooks.update({'datamem': entities['datamem']}) hooks.update({'controller': entities['controller']}) # generate simulatable architecture arch = Architecture(0.0001, clk, rst, None, hooks, entities) return arch, hooks
def test_constructor(self): "Constructor with valid and invalid configuration" c0 = Constant(16, 0xAAAA) b0 = Bus(4) b1 = Bus(8) b2 = Bus(2) b3 = Bus(2) with self.assertRaises(TypeError): bj = BusSubset(None, None, None) with self.assertRaises(TypeError): bj = BusSubset('0', None, None) with self.assertRaises(TypeError): bj = BusSubset(c0, None, None) with self.assertRaises(TypeError): bj = BusSubset(c0, [], []) with self.assertRaises(ValueError): bj = BusSubset(c0, ['0'], [(0, 1)]) with self.assertRaises(TypeError): bj = BusSubset(c0, [b0], []) with self.assertRaises(TypeError): bj = BusSubset(c0, [b0], ['0']) with self.assertRaises(TypeError): bj = BusSubset(c0, [b0], [('0', '1')]) with self.assertRaises(ValueError): bj = BusSubset(c0, [b0], [(1, 0)]) with self.assertRaises(ValueError): bj = BusSubset(c0, [b0], [(0, 1)]) with self.assertRaises(ValueError): bj = BusSubset(c0, [b0], [(0, 8)]) bs = BusSubset(c0, [b0, b1, b2, b3], [(0, 4), (4, 12), (12, 14), (14, 16)])
class ProgramMemory(Memory): """ ARM specific program memory with 32-bit word size. This component is to be used for storing a program in an architecture. Note that this device does not allow writes from inside the architecture. Note to program this memory use the modify functionality. Note that address space is ghosted if the address bus is greater than the size defined for the module. """ DEFAULT_SIZE = 4096 DEFAULT_STATE = 0 DEFAULT_RESET_TYPE = Logic_States.ACTIVE_HIGH def __init__(self, address, rst, read, default_size=DEFAULT_SIZE, default_value=DEFAULT_STATE, rst_type=DEFAULT_RESET_TYPE): """ Buses address : word sized address bus to access program memory rst : Reset bus to clear memory read : word sized bus with addressed instruction Configuration default_size : size of program memory space in bytes default_value : byte value to load into unassigned memory cells rst_type : Activation state for reset line """ # disable write behavior self._wd_const = Constant(32, 0) self._we_const = Constant(1, 0) self._clk_const = Constant(1, 0) # default mode to word access self._mode_const = Constant(2, 3) # ghost memory on bus to lower needed bits if default_size == 0: size = 0 elif default_size < 2: size = 1 else: # len > 2 size = int(math.floor(math.log(default_size - 1, 2) + 1)) self._address_general = Bus(size) self._address_subset = BusSubset(address, [self._address_general], [(0, size)]) # Construct generalized memory passing parameters Memory.__init__(self, default_size, 4, 0, self._address_general, self._wd_const, self._we_const, rst, self._clk_const, self._mode_const, read, default_value, Latch_Type.FALLING_EDGE, rst_type, Logic_States.ACTIVE_HIGH) def run(self, time=None): """ Update address sub-entities before calling general memory run operation """ self._address_subset.run(time) Memory.run(self, time) @classmethod def from_dict(cls, config, hooks): "Implements conversion from configuration to component" if "size" in config: size = config["size"] else: size = ProgramMemory.DEFAULT_SIZE if "value" in config: value = config["value"] else: value = ProgramMemory.DEFAULT_STATE if "reset_type" in config: reset_type = Logic_States.fromString(config["reset_type"]) else: reset_type = ProgramMemory.DEFAULT_RESET_TYPE return ProgramMemory(hooks[config["address"]], hooks[config["reset"]], hooks[config["read"]], size, value, reset_type)
def generate_pipeline_architecture(): "Illustrates the necessary process to construct an architecture" ########## define system resources ########## clk = Clock(10, 0) rst = Reset(0) hooks = OrderedDict([('clk', clk), ('rst', rst)]) ########## define input hooks and constants ########## hooks.update({'const4': Constant(32, 4)}) hooks.update({'const8': Constant(32, 8)}) hooks.update({'const14': Constant(4, 14)}) ########## define buses ########## hooks.update({'pc': Bus(32, 0)}) hooks.update({'pc4f': Bus(32, 0)}) hooks.update({'pc4d': Bus(32, 0)}) hooks.update({'pc4e': Bus(32, 0)}) hooks.update({'pc4m': Bus(32, 0)}) hooks.update({'pc4w': Bus(32, 0)}) hooks.update({'pc8f': Bus(32, 0)}) hooks.update({'pc8d': Bus(32, 0)}) hooks.update({'braddr': Bus(32, 0)}) hooks.update({'nextaddr': Bus(32, 0)}) hooks.update({'instrf': Bus(32, 0)}) hooks.update({'instrd': Bus(32, 0)}) hooks.update({'instrd_31_28': Bus(4, 0)}) hooks.update({'instrd_27_26': Bus(2, 0)}) hooks.update({'instrd_25_20': Bus(6, 0)}) hooks.update({'instrd_19_16': Bus(4, 0)}) hooks.update({'instrd_15_12': Bus(4, 0)}) hooks.update({'instrd_11_8': Bus(4, 0)}) hooks.update({'instrd_4': Bus(1, 0)}) hooks.update({'instrd_3_0': Bus(4, 0)}) hooks.update({'instrd_23_0': Bus(24, 0)}) hooks.update({'imm32d': Bus(32, 0)}) hooks.update({'imm32e': Bus(32, 0)}) hooks.update({'rdm': Bus(32, 0)}) hooks.update({'rdw': Bus(32, 0)}) hooks.update({'rd1': Bus(32, 0)}) hooks.update({'rd2': Bus(32, 0)}) hooks.update({'rd1d': Bus(32, 0)}) hooks.update({'rd2d': Bus(32, 0)}) hooks.update({'rd1e': Bus(32, 0)}) hooks.update({'rd2e': Bus(32, 0)}) hooks.update({'rd2m': Bus(32, 0)}) hooks.update({'ra1d': Bus(4, 0)}) hooks.update({'ra2d': Bus(4, 0)}) hooks.update({'ra3d': Bus(4, 0)}) hooks.update({'ra1e': Bus(4, 0)}) hooks.update({'ra2e': Bus(4, 0)}) hooks.update({'ra3e': Bus(4, 0)}) hooks.update({'ra3m': Bus(4, 0)}) hooks.update({'ra3w': Bus(4, 0)}) hooks.update({'fe': Bus(32, 0)}) hooks.update({'fm': Bus(32, 0)}) hooks.update({'fw': Bus(32, 0)}) hooks.update({'alub': Bus(32, 0)}) hooks.update({'aluc': Bus(1, 0)}) hooks.update({'aluv': Bus(1, 0)}) hooks.update({'alun': Bus(1, 0)}) hooks.update({'aluz': Bus(1, 0)}) hooks.update({'c': Bus(1, 0)}) hooks.update({'v': Bus(1, 0)}) hooks.update({'n': Bus(1, 0)}) hooks.update({'z': Bus(1, 0)}) hooks.update({'aluflag': Bus(4, 0)}) hooks.update({'flag': Bus(4, 0)}) hooks.update({'data': Bus(32, 0)}) hooks.update({'wd': Bus(32, 0)}) hooks.update({'wd3': Bus(32, 0)}) ########## control signals ########## # decode stage hooks.update({'pcsrcd': Bus(2, 0)}) hooks.update({'pcwrd': Bus(1, 0)}) hooks.update({'regsad': Bus(1, 0)}) hooks.update({'regdstd': Bus(2, 0)}) hooks.update({'regwrsd': Bus(2, 0)}) hooks.update({'regwrd': Bus(1, 0)}) hooks.update({'extsd': Bus(2, 0)}) hooks.update({'alusrcbd': Bus(1, 0)}) hooks.update({'alusd': Bus(4, 0)}) hooks.update({'aluflagwrd': Bus(1, 0)}) hooks.update({'memwrd': Bus(1, 0)}) hooks.update({'regsrcd': Bus(1, 0)}) hooks.update({'wd3sd': Bus(1, 0)}) # execute stage hooks.update({'regwre': Bus(1, 0)}) hooks.update({'alusrcbe': Bus(1, 0)}) hooks.update({'aluse': Bus(4, 0)}) hooks.update({'aluflagwre': Bus(1, 0)}) hooks.update({'memwre': Bus(1, 0)}) hooks.update({'regsrce': Bus(1, 0)}) hooks.update({'wd3se': Bus(1, 0)}) # memory stage hooks.update({'regwrm': Bus(1, 0)}) hooks.update({'memwrm': Bus(1, 0)}) hooks.update({'regsrcm': Bus(1, 0)}) hooks.update({'wd3sm': Bus(1, 0)}) # write back stage hooks.update({'regwrw': Bus(1, 0)}) hooks.update({'regsrcw': Bus(1, 0)}) hooks.update({'wd3sw': Bus(1, 0)}) ########## hazard control signals ########## hooks.update({'fwda': Bus(3, 0)}) hooks.update({'fwdb': Bus(3, 0)}) hooks.update({'fwds': Bus(1, 0)}) hooks.update({'stallf': Bus(1, 0)}) hooks.update({'flushf': Bus(1, 0)}) hooks.update({'flushd': Bus(1, 0)}) ########## generate components ########## entities = OrderedDict([('clk', clk)]) # memwb entities.update({ 'memwb': Memwb(hooks['pc4m'], hooks['regwrm'], hooks['regsrcm'], hooks['wd3sm'], hooks['fm'], hooks['rdm'], hooks['ra3m'], hooks['clk'], hooks['pc4w'], hooks['regwrw'], hooks['regsrcw'], hooks['wd3sw'], hooks['fw'], hooks['rdw'], hooks['ra3w']) }) # exmem entities.update({ 'exmem': Exmem(hooks['pc4e'], hooks['regwre'], hooks['memwre'], hooks['regsrce'], hooks['wd3se'], hooks['rd2'], hooks['fe'], hooks['ra3e'], hooks['clk'], hooks['pc4m'], hooks['regwrm'], hooks['memwrm'], hooks['regsrcm'], hooks['wd3sm'], hooks['fm'], hooks['rd2m'], hooks['ra3m']) }) # idex entities.update({ 'idex': Idex(hooks['pc4d'], hooks['regwrd'], hooks['alusrcbd'], hooks['alusd'], hooks['aluflagwrd'], hooks['memwrd'], hooks['regsrcd'], hooks['wd3sd'], hooks['rd1d'], hooks['rd2d'], hooks['imm32d'], hooks['ra1d'], hooks['ra2d'], hooks['ra3d'], hooks['flushd'], hooks['clk'], hooks['pc4e'], hooks['regwre'], hooks['alusrcbe'], hooks['aluse'], hooks['aluflagwre'], hooks['memwre'], hooks['regsrce'], hooks['wd3se'], hooks['rd1e'], hooks['rd2e'], hooks['imm32e'], hooks['ra1e'], hooks['ra2e'], hooks['ra3e']) }) # ifid entities.update({ 'ifid': Ifid(hooks['pc4f'], hooks['pc8f'], hooks['instrf'], hooks['stallf'], hooks['flushf'], hooks['clk'], hooks['pc4d'], hooks['pc8d'], hooks['instrd']) }) # fetch entities.update({ 'addr_mux': Mux(32, [hooks['braddr'], hooks['pc4d'], hooks['fe']], hooks['pcsrcd'], hooks['nextaddr']) }) entities.update({ 'pc_reg': Register(32, hooks['clk'], hooks['rst'], hooks['nextaddr'], hooks['pc'], 0, enable=hooks['pcwrd']) }) entities.update( {'add8': Adder(32, hooks['pc'], hooks['const8'], hooks['pc8f'])}) entities.update( {'add4': Adder(32, hooks['pc'], hooks['const4'], hooks['pc4f'])}) entities.update( {'progmem': ProgramMemory(hooks['pc'], hooks['rst'], hooks['instrf'])}) # decode entities.update({ 'instr_subset': BusSubset(hooks['instrd'], [ hooks['instrd_23_0'], hooks['instrd_31_28'], hooks['instrd_27_26'], hooks['instrd_25_20'], hooks['instrd_19_16'], hooks['instrd_15_12'], hooks['instrd_11_8'], hooks['instrd_4'], hooks['instrd_3_0'] ], [(0, 24), (28, 32), (26, 28), (20, 26), (16, 20), (12, 16), (8, 12), (4, 5), (0, 4)]) }) entities.update({ 'controller': ControllerPipeline(hooks['instrd_31_28'], hooks['instrd_27_26'], hooks['instrd_25_20'], hooks['instrd_15_12'], hooks['instrd_4'], hooks['c'], hooks['v'], hooks['n'], hooks['z'], hooks['stallf'], hooks['pcsrcd'], hooks['pcwrd'], hooks['regsad'], hooks['regdstd'], hooks['regwrsd'], hooks['regwrd'], hooks['extsd'], hooks['alusrcbd'], hooks['alusd'], hooks['aluflagwrd'], hooks['memwrd'], hooks['regsrcd'], hooks['wd3sd']) }) entities.update({ 'ra1_mux': Mux(4, [hooks['instrd_3_0'], hooks['instrd_19_16']], hooks['regsad'], hooks['ra1d']) }) entities.update({ 'ra2_mux': Mux(4, [hooks['instrd_11_8'], hooks['instrd_3_0'], hooks['instrd_15_12']], hooks['regdstd'], hooks['ra2d']) }) entities.update({ 'ra3_mux': Mux(4, [hooks['instrd_19_16'], hooks['instrd_15_12'], hooks['const14']], hooks['regwrsd'], hooks['ra3d']) }) entities.update({ 'extimm': Extender(hooks['instrd_23_0'], hooks['extsd'], hooks['imm32d']) }) entities.update({ 'add_branch': Adder(32, hooks['pc8d'], hooks['imm32d'], hooks['braddr']) }) entities.update({ 'regfile': RegisterFile(hooks['clk'], hooks['rst'], hooks['regwrw'], hooks['wd'], hooks['ra1d'], hooks['ra2d'], hooks['ra3w'], hooks['rd1d'], hooks['rd2d'], edge_type=Latch_Type.FALLING_EDGE) }) # execute entities.update({ 'hazard_controller': HazardController(hooks['ra1e'], hooks['ra2e'], hooks['ra3e'], hooks['ra3m'], hooks['ra3w'], hooks['regwrm'], hooks['regwrw'], hooks['regsrcm'], hooks['regsrcw'], hooks['memwrm'], hooks['pcsrcd'], hooks['fwda'], hooks['fwdb'], hooks['fwds'], hooks['stallf'], hooks['flushf'], hooks['flushd']) }) entities.update({ 'fwda_mux': Mux(32, [ hooks['rd1e'], hooks['fw'], hooks['fm'], hooks['rdm'], hooks['rdw'] ], hooks['fwda'], hooks['rd1']) }) entities.update({ 'fwdb_mux': Mux(32, [ hooks['rd2e'], hooks['fw'], hooks['fm'], hooks['rdm'], hooks['rdw'] ], hooks['fwdb'], hooks['rd2']) }) entities.update({ 'alu_mux': Mux(32, [hooks['imm32e'], hooks['rd2']], hooks['alusrcbe'], hooks['alub']) }) entities.update({ 'alu': Alu(hooks['rd1'], hooks['alub'], hooks['aluse'], hooks['fe'], hooks['aluc'], hooks['aluv'], hooks['alun'], hooks['aluz']) }) entities.update({ 'aluflag_join': BusJoin([hooks['aluc'], hooks['aluv'], hooks['alun'], hooks['aluz']], hooks['aluflag']) }) entities.update({ 'aluflag_reg': Register(4, hooks['clk'], hooks['rst'], hooks['aluflag'], hooks['flag'], enable=hooks['aluflagwre']) }) entities.update({ 'flag_subset': BusSubset(hooks['flag'], [hooks['c'], hooks['v'], hooks['n'], hooks['z']], [(0, 1), (1, 2), (2, 3), (3, 4)]) }) # writeback entities.update({ 'wd3_mux': Mux(32, [hooks['rdw'], hooks['fw']], hooks['regsrcw'], hooks['wd3']) }) entities.update({ 'rwd_mux': Mux(32, [hooks['wd3'], hooks['pc4w']], hooks['wd3sw'], hooks['wd']) }) # memory entities.update({ 'fwds_mux': Mux(32, [hooks['rd2m'], hooks['wd3']], hooks['fwds'], hooks['data']) }) entities.update({ 'datamem': DataMemory(hooks['fm'], hooks['data'], hooks['memwrm'], hooks['rst'], hooks['clk'], hooks['rdm']) }) # place memory (Internal) hooks into hook list hooks.update({'pc_reg': entities['pc_reg']}) hooks.update({'progmem': entities['progmem']}) hooks.update({'regfile': entities['regfile']}) hooks.update({'aluflag_reg': entities['aluflag_reg']}) hooks.update({'datamem': entities['datamem']}) hooks.update({'controller': entities['controller']}) #hooks.update({'hazard_controller': entities['hazard_controller']}) hooks.update({'ifid': entities['ifid']}) hooks.update({'idex': entities['idex']}) hooks.update({'exmem': entities['exmem']}) hooks.update({'memwb': entities['memwb']}) # generate simulatable architecture arch = Architecture(0.0001, clk, rst, None, hooks, entities) return arch, hooks
ss0_bus = Bus(8, 0) ss1_bus = Bus(8, 0) ss2_bus = Bus(8, 0) ss3_bus = Bus(8, 0) bj0 = Bus(32, 0) reg = Register(32, clk, rst, d_bus, q_bus) add = Adder(32, q_bus, c1, d_bus) regFile = Register_File(clk, rst, c2, d_bus, address, address, address, q_bus, m_bus) m = Mux(32, [q_bus, m_bus], c2, f_bus) alu = Alu(f_bus, q_bus, Bus(1, 0), r_bus, c_bus, v_bus, n_bus, z_bus) subset = BusSubset(q_bus, [ss0_bus, ss1_bus, ss2_bus, ss3_bus], [(0, 8), (8, 16), (16, 24), (24, 32)]) join = BusJoin([ss3_bus, ss2_bus, ss1_bus, ss0_bus], bj0) add.run() reg.run() regFile.run() m.run() alu.run() subset.run() join.run() while True: print('-----------------------------------------------------------') print(clk.inspect()) print(rst.inspect())
class ALUFlagRegister(Register): """ ALU Flag Register is a specific state register for ARM architecture. Developed to simplifiy design by reducing need for join and subset. """ DEFAULT_STATE = 0 DEFAULT_LATCH_TYPE = Latch_Type.RISING_EDGE DEFAULT_RESET_TYPE = Logic_States.ACTIVE_HIGH DEFAULT_ENABLE_TYPE = Logic_States.ACTIVE_HIGH def __init__(self, c_in, v_in, n_in, z_in, rst, clk, en, c_out, v_out, n_out, z_out, default_state=DEFAULT_STATE, edge_type=DEFAULT_LATCH_TYPE, reset_type=DEFAULT_RESET_TYPE, enable_type=DEFAULT_ENABLE_TYPE): """ Constructor will check for valid parameters, exception thrown on invalid Parameters c_in: 1-bit input of 'c' v_in: 1-bit input of 'v' n_in: 1-bit input of 'n' z_in: 1-bit input of 'z' rst: Register reset clk: Register clock en: Register write enable c_out: 1-bit output of 'c' v_out: 1-bit output of 'v' n_out: 1-bit output of 'n' z_out: 1-bit output of 'z' default_state: Initial 4-bit state of ALU Flag edge_type: Clock state change to store flags reset_type: Asynchronous reset to default_state value enable_type: State to allow write to register """ if not isinstance(c_in, iBusRead) or not c_in.size() == 1: raise TypeError('c in must be a 1-bit readable bus') if not isinstance(v_in, iBusRead) or not v_in.size() == 1: raise TypeError('v in must be a 1-bit readable bus') if not isinstance(n_in, iBusRead) or not n_in.size() == 1: raise TypeError('n in must be a 1-bit readable bus') if not isinstance(z_in, iBusRead) or not z_in.size() == 1: raise TypeError('z in must be a 1-bit readable bus') if not isinstance(c_out, iBusWrite) or not c_out.size() == 1: raise TypeError('c out must be a 1-bit readable bus') if not isinstance(v_out, iBusWrite) or not v_out.size() == 1: raise TypeError('v out must be a 1-bit readable bus') if not isinstance(n_out, iBusWrite) or not n_out.size() == 1: raise TypeError('n out must be a 1-bit readable bus') if not isinstance(z_out, iBusWrite) or not z_out.size() == 1: raise TypeError('z out must be a 1-bit readable bus') self._flag_in = Bus(4) self._join = BusJoin([c_in, v_in, n_in, z_in], self._flag_in) self._flag_out = Bus(4) self._subset = BusSubset(self._flag_out, [c_out, v_out, n_out, z_out], [(0, 1), (1, 2), (2, 3), (3, 4)]) Register.__init__(self, 4, clk, rst, self._flag_in, self._flag_out, default_state, edge_type, reset_type, en, enable_type) def run(self, time=None): "Timestep handler function clocks data into register and asserts output" self._join.run(time) Register.run(self, time) self._subset.run(time) @classmethod def from_dict(cls, config, hooks): "Implements conversion from configuration to component" if "value" in config: default_state = config["value"] else: default_state = ALUFlagRegister.DEFAULT_STATE if "edge_type" in config: edge_type = Latch_Type.fromString(config["edge_type"]) else: edge_type = ALUFlagRegister.DEFAULT_LATCH_TYPE if "reset_type" in config: reset_type = Logic_States.fromString(config["reset_type"]) else: reset_type = ALUFlagRegister.DEFAULT_RESET_TYPE if "enable_type" in config: enable_type = Logic_States.fromString(config["enable_type"]) else: enable_type = ALUFlagRegister.DEFAULT_ENABLE_TYPE return ALUFlagRegister(hooks[config["c_in"]], hooks[config["v_in"]], hooks[config["n_in"]], hooks[config["z_in"]], hooks[config["reset"]], hooks[config["clock"]], hooks[config["enable"]], hooks[config["c_out"]], hooks[config["v_out"]], hooks[config["n_out"]], hooks[config["z_out"]], default_state, edge_type, reset_type, enable_type)