def gen_mmio_size(regs): if regs is None: return CINT(0x100, 16, 3) # legacy default else: reg_range = get_reg_range(regs) digits = int(log(reg_range, 16)) + 1 return CINT(reg_range, 16, digits)
def __init__( self, size, # None or "gap" named registers are not backed by a state field name=None, access="rw", reset=0, full_name=None, # write mask (None corresponds 0b11...11. I.e. all bits are writable). wmask=None, # Write after read (WAR) bits. 1 marks the bit as WAR. None # corresponds to 0b00...00, all bits can be written without reading. warbits=None): super(Register, self).__init__(size, name) self.access = access self.reset = None if reset is None else CINT(reset, 16, size * 2) self.full_name = full_name if wmask is None: wmask = (1 << (size * 8)) - 1 self.wmask = CINT(wmask, 2, size * 8) if warbits is None: warbits = 0 self.warbits = CINT(warbits, 2, size * 8)
def gen_mmio_size(regs): if regs is None: return CINT(0x100, 16, 3) # legacy default elif isinstance(regs, MemoryLeafNode): return regs.size else: reg_range = get_reg_range(regs) digits = int(log(reg_range, 16)) + 1 return CINT(reg_range, 16, digits)
def test_0b11100111(self): # If difference of digits amount in two CINT does not affects # string form, then it is negligible. # Right CINT requires at least 0 digits, It does not result in leading # zeros. Left CINT requires 8 digits, according to original string # form. It has no leading zeros, apparently. So, CINTs are considered # equal. self.assertEqual(CINT("0b11100111"), CINT(231, 2, 0)) # Right CINT has 1 leading zero, CINTs are not equal. self.assertNotEqual(CINT("0b11100111"), CINT(231, 2, 9))
def __init__(self, name, size, var_base="mem", **kw): Node.__init__(self, var_base=var_base, **kw) self.name = CSTR(name) self.size = None if size is None else CINT(size) self.parent = None self.offset = CINT(0, base=16) self.may_overlap = True self.priority = CINT(1) self.children = [] self.alias_to = None self.alias_offset = CINT(0, base=16)
def __repr__(self, *args, **kwargs): # TODO: adapt and utilize PyGenerator.gen_args for this use case ret = type(self).__name__ size = self.size ret += "(" + repr(size) name = self.name if name is not None: ret += ", name = " + repr(name) access = self.access if access != "rw": ret += ", access = " + repr(access) reset = self.reset if reset != CINT(0, 16, size): ret += ", reset = " + repr(reset) fn = self.full_name if fn is not None: ret += ", full_name = " + repr(fn) wm = self.wmask if (wm.v != (1 << (size * 8)) - 1 or wm.b != 2 or wm.d != size * 8): ret += ", wmask = " + repr(wm) warb = self.warbits if (warb.v != 0 or warb.b != 2 or warb.d != size * 8): ret += ", warbits = " + repr(warb) ret += ")" return ret
def test_0x18(self): self.assertEqual(CINT("0x18"), CINT(24, 16, 2))
def test(self): self.assertEqual(CINT("0"), 0)
def test(self): self.assertRaises(ValueError, lambda: CINT(""))
def gen_reg_cases(regs, access, offset_name, val, ret, s): reg_range = get_reg_range(regs) cases = [] digits = int(log(reg_range, 16)) + 1 offset = 0 for reg in regs: size = reg.size name = reg.name if name is None or name == "gap": offset += size continue if size == 1: case_cond = CINT(offset, base = 16, digits = digits) else: case_cond = ( CINT(offset, base = 16, digits = digits), CINT(offset + size - 1, base = 16, digits = digits) ) offset += size case = SwitchCase(case_cond) comment = name if reg.full_name: # neither `None` nor empty string comment += ", " + reg.full_name case(Comment(comment)) if access in reg.access: qtn = QemuTypeName(name) s_deref_war = lambda : OpSDeref( s, qtn.for_id_name + "_war" ) s_deref = OpSDeref( s, qtn.for_id_name ) if access == "r": case( OpAssign( ret, s_deref ) ) warb = reg.warbits if warb.v: # neither None nor zero # There is at least one write-after-read bit in the reg. wm = reg.wmask if wm.v == (1 << (size * 8)) - 1: # no read only bits: set WAR mask to 0xF...F case( OpAssign( s_deref_war(), OpNot(0) ) ) else: # writable bits, read only bits: init WAR mask with # write mask case( OpAssign( s_deref_war(), wm ) ) elif access == "w": wm = reg.wmask warb = reg.warbits if warb.v and wm.v: # WAR bits, writable, read only bits: use WAR mask as # dynamic write mask case( OpAssign( s_deref, OpOr( OpAnd( val, s_deref_war(), parenthesis = True ), OpAnd( s_deref, OpNot( s_deref_war() ), parenthesis = True ) ) ) ) elif wm.v == (1 << (size * 8)) - 1: # no WAR bits, no read only bits # write mask does not affect the value being assigned case( OpAssign( s_deref, val ) ) elif wm.v: # no WAR bits, writable bits, read only bits: use static # write mask case( OpAssign( s_deref, OpOr( OpAnd( val, wm, parenthesis = True ), OpAnd( s_deref, OpNot( wm ), parenthesis = True ) ) ) ) else: case( Call( "fprintf", MCall("stderr"), StrConcat( CSTR( "%%s: %s 0x%%0%d" % ("Reading from" if access == "r" else "Writing to", digits) ), MCall("HWADDR_PRIx"), CSTR("\\n"), delim = "@s" ), MCall("__func__"), offset_name ) ) cases.append(case) return cases
def __init__(self, name, size, alias_to, offset=CINT(0), **kw): MemoryLeafNode.__init__(self, name, size, **kw) self.alias_to = alias_to self.alias_offset = CINT(offset)
def gen_reg_cases(regs, access, offset_name, val, ret, s): reg_range = get_reg_range(regs) cases = [] digits = int(log(reg_range, 16)) + 1 offset = 0 for reg in regs: size = reg.size if size == 1: case_cond = CINT(offset, base = 16, digits = digits) else: case_cond = ( CINT(offset, base = 16, digits = digits), CINT(offset + size - 1, base = 16, digits = digits) ) offset += size case = SwitchCase(case_cond) name = reg.name if name is not None: case.add_child(Comment(reg.name)) if access in reg.access: qtn = QemuTypeName(name) s_deref_war = OpSDeref( s, qtn.for_id_name + "_war" ) s_deref = OpSDeref( s, qtn.for_id_name ) if access == "r": case.add_child( OpAssign( ret, s_deref ) ) warb = reg.warbits if warb.v: # neither None nor zero # There is at least one write-after-read bit in the reg. wm = reg.wmask if wm.v == (1 << (size * 8)) - 1: # no read only bits: set WAR mask to 0xF...F case.add_child( OpAssign( s_deref_war, OpNot(0) ) ) else: # writable bits, read only bits: init WAR mask with # write mask case.add_child( OpAssign( s_deref_war, wm ) )