blob: 7f60c08e2934056aeee69b93d44062d178ae6749 [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import logging as log
from copy import deepcopy
from pathlib import Path
import hjson
import re
def is_ipcfg(ip: Path) -> bool: # return bool
log.info("IP Path: %s" % repr(ip))
ip_name = ip.parents[1].name
hjson_name = ip.name
log.info("IP Name(%s) and HJSON name (%s)" % (ip_name, hjson_name))
if ip_name + ".hjson" == hjson_name or ip_name + "_reg.hjson" == hjson_name:
return True
return False
def search_ips(ip_path): # return list of config files
# list the every hjson file
p = ip_path.glob('*/data/*.hjson')
# filter only ip_name/data/ip_name{_reg|''}.hjson
ips = [x for x in p if is_ipcfg(x)]
log.info("Filtered-in IP files: %s" % repr(ips))
return ips
def is_xbarcfg(xbar_obj):
if "type" in xbar_obj and xbar_obj["type"] == "xbar":
return True
return False
def get_hjsonobj_xbars(xbar_path):
""" Search crossbars hjson files from given path.
Search every hjson in the directory and check hjson type.
It could be type: "top" or type: "xbar"
returns [(name, obj), ... ]
"""
p = xbar_path.glob('*.hjson')
try:
xbar_objs = [hjson.load(x.open('r'), use_decimal=True) for x in p]
except ValueError:
raise Systemexit(sys.exc_info()[1])
xbar_objs = [x for x in xbar_objs if is_xbarcfg(x)]
return xbar_objs
def get_module_by_name(top, name):
"""Search in top["module"] by name
"""
module = None
for m in top["module"]:
if m["name"] == name:
module = m
break
return module
def get_signal_by_name(module, name):
"""Return the signal struct with the type input/output/inout
"""
result = None
for s in module["available_input_list"] + module[
"available_output_list"] + module["available_inout_list"]:
if s["name"] == name:
result = s
break
return result
def add_prefix_to_signal(signal, prefix):
"""Add prefix to module signal format { name: "sig_name", width: NN }
"""
result = deepcopy(signal)
if not "name" in signal:
raise SystemExit("signal {} doesn't have name field".format(signal))
result["name"] = prefix + "_" + signal["name"]
return result
def get_ms_name(name):
"""Split module_name.signal_name to module_name , signal_name
"""
tokens = name.split('.')
if len(tokens) == 0:
raise SystemExit("This to be catched in validate.py")
module = tokens[0]
signal = None
if len(tokens) == 2:
signal = tokens[1]
return module, signal
def parse_pad_field(padstr):
"""Parse PadName[NN...NN] or PadName[NN] or just PadName
"""
match = re.match(r'^([A-Za-z0-9_]+)(\[([0-9]+)(\.\.([0-9]+))?\]|)', padstr)
return match.group(1), match.group(3), match.group(5)
def get_pad_list(padstr):
pads = []
pad, first, last = parse_pad_field(padstr)
if first is None:
first = 0
last = 0
elif last is None:
last = first
first = int(first, 0)
last = int(last, 0)
width = first - last + 1
for p in range(first, last + 1):
pads.append({"name": pad, "index": p})
return pads
# Template functions
def ljust(x, width):
return "{:<{width}}".format(x, width=width)
def bitarray(d, width):
"""Print Systemverilog bit array
@param d the bit width of the signal
@param width max character width of the signal group
For instance, if width is 4, the max d value in the signal group could be
9999. If d is 2, then this function pads 3 spaces at the end of the bit
slice.
"[1:0] " <- d:=2, width=4
"[9999:0]" <- max d-1 value
If d is 1, it means array slice isn't necessary. So it returns empty spaces
"""
if d <= 0:
log.error("lib.bitarray: Given value {} is smaller than 1".format(d))
raise ValueError
if d == 1:
return " " * (width + 4) # [x:0] needs 4 more space than char_width
out = "[{}:0]".format(d - 1)
return out + (" " * (width - len(str(d))))
def parameterize(text):
"""Return the value wrapping with quote if not integer nor bits
"""
if re.match('(\d+\'[hdb]\s*[0-9a-f_A-F]+|[0-9]+)', text) == None:
return "\"{}\"".format(text)
return text