blob: 2def6a0e025998bec79d1491a9ddb7f5812999bd [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess
# helper funtion that strips trailing number from name
# TODO: this is a workaround, should solve this in validate.py
def _get_basename(name):
for (k, c) in enumerate(name[::-1]):
if not str.isdigit(c):
return name[0:len(name) - k]
return ""
class Field():
"""Field in a register.
Field class contains necessary info to generate RTL code.
It has two additional (tool generated) fields, swrdaccess and swwraccess,
which represent read and write type. This makes RTL generation code simpler.
"""
name = "" # required
msb = 31 # required
lsb = 0 # required
resval = 0 # optional
swaccess = SwAccess.NONE # optional
swrdaccess = SwRdAccess.NONE
swwraccess = SwWrAccess.NONE
hwaccess = HwAccess.HRO
hwqe = False
hwre = False
hwext = False
tags = []
shadowed = False
def __init__(self):
self.name = "" # required
self.msb = 31 # required
self.lsb = 0 # required
self.resval = 0 # optional
self.swaccess = SwAccess.NONE # optional
self.swrdaccess = SwRdAccess.NONE
self.swwraccess = SwWrAccess.NONE
self.hwaccess = HwAccess.HRO
self.hwqe = False
self.hwre = False
self.hwext = False
self.tags = []
self.shadowed = False
def get_n_bits(self, bittype=["q"]):
n_bits = 0
if "q" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
n_bits += self.msb - self.lsb + 1
if "d" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
n_bits += self.msb - self.lsb + 1
if "qe" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
n_bits += self.hwqe
if "re" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
n_bits += self.hwre
if "de" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
n_bits += not self.hwext
return n_bits
def get_fields_flat(self):
return [self]
def get_basename(self):
return _get_basename(self.name)
class Reg():
name = ""
offset = 0
hwqe = False
hwre = False
hwext = False # External register
resval = 0
dvrights = "RO" # Used by UVM REG only
regwen = ""
fields = []
width = 0 # indicate register size
ishomog = 0
tags = []
shadowed = False
def __init__(self, name=""):
self.name = name
self.offset = 0
self.hwqe = False
self.hwre = False
self.hwext = False # External register
self.resval = 0
self.dvrights = "RO" # Used by UVM REG only
self.regwen = ""
self.fields = []
self.width = 0
self.ishomog = 0
self.tags = []
self.shadowed = False
def is_multi_reg(self):
"""Returns true if this is a multireg"""
return False
def get_n_bits(self, bittype=["q"]):
"""Returns number of bits in this register (including all multiregs and
fields). By default this function counts read data bits (bittype "q"),
but other bits such as "d", qe", "re", "de" can be counted as well by
specifying them in the bittype list argument.
"""
n_bits = 0
for f in self.fields:
n_bits += f.get_n_bits(bittype)
return n_bits
def get_fields_flat(self):
"""Returns a flat list of all the fields in this register"""
fields = []
for f in self.fields:
fields += f.get_fields_flat()
return fields
def get_field_flat(self, linear_idx):
"""Returns a specific field at a linear index position in
the flattened field list"""
fields_flat = self.get_fields_flat()
return fields_flat[linear_idx]
def get_n_fields_flat(self):
"""Returns the number of fields contained in the flat field list"""
return len(self.get_fields_flat())
def get_regs_flat(self):
"""Returns a flat list containing all
registers and subregisters"""
if isinstance(self.fields[0], Field):
return [self]
else:
regs = []
for r in self.fields:
regs += r.get_regs_flat()
return regs
def get_reg_flat(self, linear_index):
"""Returns a specific register at a linear index position in
the flattened regiser list"""
regs_flat = self.get_regs_flat()
return regs_flat[linear_index]
def get_n_regs_flat(self):
"""Returns the number of registers contained in
the flat register list"""
return len(self.get_regs_flat())
def get_nested_dims(self):
"""Recursively get dimensions of nested registers (outputs a list)"""
# return length of flattened field array if this is a regular register,
# or if this is the last multiregister level in a nested multiregister
if not isinstance(self, MultiReg):
dims = [len(self.get_fields_flat())]
if isinstance(self, MultiReg) and\
not isinstance(self.fields[0], MultiReg):
if self.ishomog:
dims = [len(self.get_fields_flat())]
else:
dims = [len(self.fields)]
else:
# nested multiregister case
dims = [len(self.fields)] + self.fields[0].get_nested_dims()
return dims
def get_nested_params(self):
"""Recursively get parameters of nested registers (outputs a list)"""
params = []
if isinstance(self, MultiReg):
params += [self.param]
if isinstance(self.fields[0], MultiReg):
params += self.fields[0].get_nested_params()
return params
def get_basename(self):
return _get_basename(self.name)
class MultiReg(Reg):
param = ""
def __init__(self, name):
Reg.__init__(self, name)
self.param = ""
def is_multi_reg(self):
"""Returns true if this is a multireg"""
return True
class Window():
base_addr = 0
limit_addr = 0
n_bits = 0
tags = []
def __init__(self):
self.base_addr = 0
self.limit_addr = 0
self.n_bits = 0
self.tags = []
class Block():
width = 32
addr_width = 12
base_addr = 0
name = ""
hier_path = ""
regs = []
wins = []
blocks = []
params = []
tags = []
def __init__(self):
self.width = 32
self.addr_width = 12
self.base_addr = 0
self.name = ""
self.hier_path = ""
self.regs = []
self.wins = []
self.blocks = []
self.params = []
self.tags = []
def get_regs_flat(self):
"""Returns flattened register list
"""
regs = []
for r in self.regs:
regs += r.get_regs_flat()
return regs
def get_n_bits(self, bittype=["q"]):
"""Returns number of bits in this block (including all multiregs and
fields). By default this function counts read data bits (bittype "q"),
but other bits such as "d", qe", "re", "de" can be counted as well by
specifying them in the bittype list argument.
"""
n_bits = 0
for r in self.regs:
n_bits += r.get_n_bits(bittype)
return n_bits
def get_n_regs_flat(self):
return len(self.get_regs_flat())
def contains_multiregs(self):
"""Returns true if there are multiregs in this block
"""
for r in self.regs:
if isinstance(r, MultiReg):
return True
return False