scope refactoring
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import glob
|
||||
|
||||
config_location = 'configs'
|
||||
|
||||
name_template = '{clusters}cl-{cores}c-{warps}w-{threads}t-{l2}Kl2-{dcache}Kd-{icache}Ki{name_suffix}.sh'
|
||||
|
||||
template = """
|
||||
|
||||
export V_NT={threads}
|
||||
export V_NW={warps}
|
||||
export V_NUM_CORES_PER_CLUSTER={cores}
|
||||
export V_NUM_CLUSTERS={clusters}
|
||||
export V_DCACHE_SIZE_BYTES={dcachek}
|
||||
export V_ICACHE_SIZE_BYTES={icachek}
|
||||
|
||||
# L2 Cache size
|
||||
export V_L2CACHE_SIZE_BYTES={l2k}
|
||||
|
||||
{codegen}
|
||||
|
||||
"""
|
||||
|
||||
# cluster, cores, warps, threads, l2, dcache, icache
|
||||
configs = [
|
||||
(1, 2, 8, 4, 8, 4, 1),
|
||||
(1, 2, 8, 8, 8, 4, 1),
|
||||
(1, 2, 8, 8, 16, 8, 1),
|
||||
|
||||
(1, 4, 8, 8, 16, 4, 1),
|
||||
(1, 4, 8, 8, 16, 8, 1),
|
||||
(1, 4, 16, 8, 16, 8, 1),
|
||||
|
||||
(2, 4, 8, 4, 8, 4, 1),
|
||||
(2, 4, 8, 8, 16, 8, 1),
|
||||
]
|
||||
|
||||
files = glob.glob(config_location + '/*.sh')
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
|
||||
for clusters, cores, warps, threads, l2, dcache, icache in configs:
|
||||
l2k, dcachek, icachek = 1024 * l2, 1024 * dcache, 1024 * icache
|
||||
name_suffix = ''
|
||||
with open(config_location + '/' + name_template.format(**locals()), 'w') as f:
|
||||
codegen = ''
|
||||
f.write(template.format(**locals()))
|
||||
161
hw/scripts/scope.json
Normal file
161
hw/scripts/scope.json
Normal file
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"version": 1,
|
||||
"includes":[
|
||||
"../rtl/VX_config.vh",
|
||||
"../rtl/VX_platform.vh",
|
||||
"../rtl/VX_define.vh",
|
||||
"../rtl/cache/VX_cache_config.vh"
|
||||
],
|
||||
"parameters": {
|
||||
"L3_ENABLE": "`L3_ENABLE",
|
||||
"L2_ENABLE": "`L2_ENABLE",
|
||||
"NUM_CLUSTERS": "`NUM_CLUSTERS",
|
||||
"NUM_CORES": "`NUM_CORES",
|
||||
"DNUM_BANKS": "`DNUM_BANKS",
|
||||
"INUM_BANKS": "`INUM_BANKS",
|
||||
"SNUM_BANKS": "`SNUM_BANKS",
|
||||
"L2NUM_BANKS": "`L2NUM_BANKS",
|
||||
"L3NUM_BANKS": "`L3NUM_BANKS"
|
||||
},
|
||||
"taps": {
|
||||
"top::SCOPE_SIGNALS_AFU": {
|
||||
"!scope_dram_req_valid": 1,
|
||||
"scope_dram_req_addr": 32,
|
||||
"scope_dram_req_rw": 1,
|
||||
"scope_dram_req_byteen": "`VX_DRAM_BYTEEN_WIDTH",
|
||||
"scope_dram_req_data": "`VX_DRAM_LINE_WIDTH",
|
||||
"scope_dram_req_tag": "`VX_DRAM_TAG_WIDTH",
|
||||
"!scope_dram_req_ready": 1,
|
||||
"!scope_dram_rsp_valid": 1,
|
||||
"scope_dram_rsp_data": 128,
|
||||
"scope_dram_rsp_tag": "`VX_DRAM_TAG_WIDTH",
|
||||
"!scope_dram_rsp_ready": 1,
|
||||
"!scope_snp_req_valid": 1,
|
||||
"scope_snp_req_addr": 32,
|
||||
"scope_snp_req_invalidate": 1,
|
||||
"scope_snp_req_tag": "`VX_SNP_TAG_WIDTH",
|
||||
"!scope_snp_req_ready": 1,
|
||||
"!scope_snp_rsp_valid": 1,
|
||||
"scope_snp_rsp_tag": "`VX_SNP_TAG_WIDTH",
|
||||
"!scope_snp_rsp_ready": 1,
|
||||
"scope_busy": 1
|
||||
},
|
||||
"core::SCOPE_SIGNALS_ISTAGE": {
|
||||
"!scope_icache_req_valid": 1,
|
||||
"scope_icache_req_wid": "`NW_BITS",
|
||||
"scope_icache_req_addr": 32,
|
||||
"scope_icache_req_tag": "`ICORE_TAG_ID_BITS",
|
||||
"!scope_icache_req_ready": 1,
|
||||
"!scope_icache_rsp_valid": 1,
|
||||
"scope_icache_rsp_data": 32,
|
||||
"scope_icache_rsp_tag": "`ICORE_TAG_ID_BITS",
|
||||
"!scope_icache_rsp_ready": 1
|
||||
},
|
||||
"core::SCOPE_SIGNALS_LSU": {
|
||||
"!scope_dcache_req_valid": "`NUM_THREADS",
|
||||
"scope_dcache_req_wid": "`NW_BITS",
|
||||
"scope_dcache_req_pc": 32,
|
||||
"scope_dcache_req_addr": "`NUM_THREADS * 32",
|
||||
"scope_dcache_req_rw": 1,
|
||||
"scope_dcache_req_byteen": "`NUM_THREADS * 4",
|
||||
"scope_dcache_req_data": "`NUM_THREADS * 32",
|
||||
"scope_dcache_req_tag": "`DCORE_TAG_ID_BITS",
|
||||
"!scope_dcache_req_ready": 1,
|
||||
"!scope_dcache_rsp_valid": "`NUM_THREADS",
|
||||
"scope_dcache_rsp_data": "`NUM_THREADS * 32",
|
||||
"scope_dcache_rsp_tag": "`DCORE_TAG_ID_BITS",
|
||||
"!scope_dcache_rsp_ready": 1
|
||||
},
|
||||
"core::SCOPE_SIGNALS_ISSUE": {
|
||||
"!scope_issue_valid": 1,
|
||||
"scope_issue_wid": "`NW_BITS",
|
||||
"scope_issue_tmask": "`NUM_THREADS",
|
||||
"scope_issue_pc": 32,
|
||||
"scope_issue_ex_type": "`EX_BITS",
|
||||
"scope_issue_op_type": "`OP_BITS",
|
||||
"scope_issue_op_mod": "`MOD_BITS",
|
||||
"scope_issue_wb": 1,
|
||||
"scope_issue_rd": "`NR_BITS",
|
||||
"scope_issue_rs1": "`NR_BITS",
|
||||
"scope_issue_rs2": "`NR_BITS",
|
||||
"scope_issue_rs3": "`NR_BITS",
|
||||
"scope_issue_imm": 32,
|
||||
"scope_issue_rs1_is_pc": 1,
|
||||
"scope_issue_rs2_is_imm": 1,
|
||||
"!scope_issue_ready": 1,
|
||||
"!scope_gpr_rsp_valid": 1,
|
||||
"scope_gpr_rsp_wid": "`NW_BITS",
|
||||
"scope_gpr_rsp_pc": 32,
|
||||
"scope_gpr_rsp_a": "`NUM_THREADS * 32",
|
||||
"scope_gpr_rsp_b": "`NUM_THREADS * 32",
|
||||
"scope_gpr_rsp_c": "`NUM_THREADS * 32",
|
||||
"!scope_gpr_delay": 1,
|
||||
"!scope_writeback_valid": 1,
|
||||
"scope_writeback_wid": "`NW_BITS",
|
||||
"scope_writeback_pc": 32,
|
||||
"scope_writeback_rd": "`NR_BITS",
|
||||
"scope_writeback_data": "`NUM_THREADS * 32",
|
||||
"!scope_scoreboard_delay": 1,
|
||||
"!scope_execute_delay": 1
|
||||
},
|
||||
"core::SCOPE_SIGNALS_EXECUTE": {},
|
||||
"bank::SCOPE_SIGNALS_BANK": {
|
||||
"!scope_bank_valid_st0": 1,
|
||||
"!scope_bank_valid_st1": 1,
|
||||
"!scope_bank_valid_st2": 1,
|
||||
"scope_bank_addr_st0": 32,
|
||||
"scope_bank_addr_st1": 32,
|
||||
"scope_bank_addr_st2": 32,
|
||||
"scope_bank_is_mrvq_st1": 1,
|
||||
"scope_bank_miss_st1": 1,
|
||||
"scope_bank_dirty_st1": 1,
|
||||
"!scope_bank_force_miss_st1": 1,
|
||||
"!scope_bank_stall_pipe": 1
|
||||
}
|
||||
},
|
||||
"triggers": [
|
||||
["scope_dram_req_valid", "scope_dram_req_ready"],
|
||||
["scope_dram_rsp_valid", "scope_dram_rsp_ready"],
|
||||
["scope_snp_req_valid", "scope_snp_req_ready"],
|
||||
["scope_snp_rsp_valid", "scope_snp_rsp_ready"],
|
||||
|
||||
["scope_icache_req_valid_top", "scope_icache_req_ready_top"],
|
||||
["scope_icache_rsp_valid_top", "scope_icache_rsp_ready_top"],
|
||||
["scope_dcache_req_valid_top", "scope_dcache_req_ready_top"],
|
||||
["scope_dcache_rsp_valid_top", "scope_dcache_rsp_ready_top"],
|
||||
|
||||
["scope_bank_valid_st0_l3_top"],
|
||||
["scope_bank_valid_st1_l3_top"],
|
||||
["scope_bank_valid_st2_l3_top"],
|
||||
["scope_bank_stall_pipe_l3_top"],
|
||||
|
||||
["scope_bank_valid_st0_l2_top"],
|
||||
["scope_bank_valid_st1_l2_top"],
|
||||
["scope_bank_valid_st2_l2_top"],
|
||||
["scope_bank_stall_pipe_l2_top"],
|
||||
|
||||
["scope_bank_valid_st0_l1d_top"],
|
||||
["scope_bank_valid_st1_l1d_top"],
|
||||
["scope_bank_valid_st2_l1d_top"],
|
||||
["scope_bank_stall_pipe_l1d_top"],
|
||||
|
||||
["scope_bank_valid_st0_l1i_top"],
|
||||
["scope_bank_valid_st1_l1i_top"],
|
||||
["scope_bank_valid_st2_l1i_top"],
|
||||
["scope_bank_stall_pipe_l1i_top"],
|
||||
|
||||
["scope_bank_valid_st0_l1s_top"],
|
||||
["scope_bank_valid_st1_l1s_top"],
|
||||
["scope_bank_valid_st2_l1s_top"],
|
||||
["scope_bank_stall_pipe_l1s_top"],
|
||||
|
||||
["scope_issue_valid_top", "scope_issue_ready_top"],
|
||||
["scope_gpr_rsp_valid_top"],
|
||||
["scope_scoreboard_delay_top"],
|
||||
["scope_gpr_delay_top"],
|
||||
["scope_execute_delay_top"],
|
||||
|
||||
["scope_busy"]
|
||||
]
|
||||
}
|
||||
|
||||
630
hw/scripts/scope.py
Executable file
630
hw/scripts/scope.py
Executable file
@@ -0,0 +1,630 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import argparse
|
||||
import math
|
||||
|
||||
vl_include_re = re.compile(r"^\s*`include\s+\"(.+)\"")
|
||||
vl_define_re = re.compile(r"^\s*`define\s+(\w+)(\([\w\s,]*\))?(.*)")
|
||||
vl_ifdef_re = re.compile(r"^\s*`(ifdef|ifndef|elsif)\s+(\w+)\s*$")
|
||||
vl_endif_re = re.compile(r"^\s*`(endif|else)\s*$")
|
||||
vl_expand_re = re.compile(r"`([0-9a-zA-Z_]+)")
|
||||
|
||||
parameters = []
|
||||
exclude_files = []
|
||||
include_dirs = []
|
||||
macros = []
|
||||
br_stack = []
|
||||
|
||||
def parse_func_args(text):
|
||||
args = []
|
||||
arg = ''
|
||||
l = len(text)
|
||||
if text[0] != '(':
|
||||
raise Exception("missing leading parenthesis: " + text)
|
||||
paren = 1
|
||||
for i in range(1, l):
|
||||
c = text[i]
|
||||
|
||||
if c == '(':
|
||||
paren += 1
|
||||
elif c == ')':
|
||||
if paren == 0:
|
||||
raise Exception("mismatched parenthesis: (" + i + ") " + text)
|
||||
paren -= 1
|
||||
if paren == 0:
|
||||
l = i
|
||||
break
|
||||
|
||||
if c == ',' and paren == 1:
|
||||
if arg.strip():
|
||||
args.append(arg)
|
||||
arg = ''
|
||||
else:
|
||||
arg += c
|
||||
|
||||
if paren != 0:
|
||||
raise Exception("missing closing parenthesis: " + text)
|
||||
|
||||
if arg.strip():
|
||||
args.append(arg)
|
||||
|
||||
return (args, l)
|
||||
|
||||
def resolve_include_path(filename, parent_dir):
|
||||
if os.path.basename(filename) in exclude_files:
|
||||
return None
|
||||
if os.path.isfile(filename):
|
||||
return os.path.abspath(filename)
|
||||
search_dirs = include_dirs
|
||||
if parent_dir:
|
||||
search_dirs.append(parent_dir)
|
||||
for dir in search_dirs:
|
||||
filepath = os.path.join(dir, filename)
|
||||
if os.path.isfile(filepath):
|
||||
return os.path.abspath(filepath)
|
||||
raise Exception("couldn't find include file: " + filename)
|
||||
|
||||
def remove_comments(text):
|
||||
text = re.sub(re.compile("/\*.*?\*/",re.DOTALL ), "", text) # multiline
|
||||
text = re.sub(re.compile("//.*?\n" ), "\n", text) # singleline
|
||||
return text
|
||||
|
||||
def add_macro(name, args, value):
|
||||
macro = (name, args, value)
|
||||
macros.append(macro)
|
||||
if not args is None:
|
||||
print("*** token: " + name + "(", end='')
|
||||
for i in range(len(args)):
|
||||
if i > 0:
|
||||
print(', ', end='')
|
||||
print(args[i], end='')
|
||||
print(")=" + value)
|
||||
else:
|
||||
print("*** token: " + name + "=" + value)
|
||||
|
||||
def find_macro(name):
|
||||
for macro in macros:
|
||||
if macro[0] == name:
|
||||
return macro
|
||||
return None
|
||||
|
||||
def expand_text(text):
|
||||
|
||||
class DoRepl(object):
|
||||
def __init__(self):
|
||||
self.expanded = False
|
||||
self.has_func = False
|
||||
def __call__(self, match):
|
||||
name = match.group(1)
|
||||
macro = find_macro(name)
|
||||
if macro:
|
||||
if not macro[1] is None:
|
||||
self.has_func = True
|
||||
else:
|
||||
self.expanded = True
|
||||
return macro[2]
|
||||
return "`" + name
|
||||
|
||||
class DoRepl2(object):
|
||||
def __init__(self, args, f_args):
|
||||
map = {}
|
||||
for i in range(len(args)):
|
||||
map[args[i]] = f_args[i]
|
||||
self.map = map
|
||||
def __call__(self, match):
|
||||
for key in match.groups():
|
||||
return self.map[key]
|
||||
return group
|
||||
|
||||
def repl_func_macro(text):
|
||||
expanded = False
|
||||
match = re.search(vl_expand_re, text)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
macro = find_macro(name)
|
||||
if macro:
|
||||
args = macro[1]
|
||||
value = macro[2]
|
||||
if not args is None:
|
||||
str_args = text[match.end():].strip()
|
||||
f_args = parse_func_args(str_args)
|
||||
if len(args) == 0:
|
||||
if len(f_args[0]) != 0:
|
||||
raise Exception("invalid argments for macro '" + name + "': value=" + text)
|
||||
else:
|
||||
if len(args) != len(f_args[0]):
|
||||
raise Exception("mismatch number of argments for macro '" + name + "': actual=" + len(f_args[0]) + ", expected=" + len(args))
|
||||
|
||||
pattern = "(?<![0-9a-zA-Z_])("
|
||||
for i in range(len(args)):
|
||||
if i > 0:
|
||||
pattern += "|"
|
||||
pattern += args[i]
|
||||
pattern += ")(?![0-9a-zA-Z_])"
|
||||
|
||||
dorepl = DoRepl2(args, f_args[0])
|
||||
value = re.sub(pattern, dorepl, value)
|
||||
|
||||
str_head = text[0:match.start()]
|
||||
str_tail = text[match.end() + f_args[1]+1:]
|
||||
text = str_head + value + str_tail
|
||||
expanded = True
|
||||
if expanded:
|
||||
return text
|
||||
return None
|
||||
|
||||
changed = False
|
||||
iter = 0
|
||||
|
||||
while True:
|
||||
if iter > 99:
|
||||
raise Exception("Macro recursion!")
|
||||
has_func = False
|
||||
while True:
|
||||
do_repl = DoRepl()
|
||||
new_text = re.sub(vl_expand_re, do_repl, text)
|
||||
has_func = do_repl.has_func
|
||||
if not do_repl.expanded:
|
||||
break
|
||||
text = new_text
|
||||
changed = True
|
||||
if not has_func:
|
||||
break
|
||||
expanded = repl_func_macro(text)
|
||||
if not expanded:
|
||||
break
|
||||
text = expanded
|
||||
changed = True
|
||||
iter += 1
|
||||
|
||||
if changed:
|
||||
return text
|
||||
return None
|
||||
|
||||
def parse_include(filename, nesting):
|
||||
if nesting > 99:
|
||||
raise Exception("include recursion!")
|
||||
print("*** parsing '" + filename + "'...")
|
||||
content = None
|
||||
with open(filename, "r") as f:
|
||||
content = f.read()
|
||||
# remove comments
|
||||
content = remove_comments(content)
|
||||
# parse content
|
||||
prev_line = None
|
||||
for line in content.splitlines(False):
|
||||
# skip empty lines
|
||||
if re.match(re.compile(r'^\s*$'), line):
|
||||
continue
|
||||
# merge multi-line lines
|
||||
if line.endswith('\\'):
|
||||
if prev_line:
|
||||
prev_line += line[:len(line) - 1]
|
||||
else:
|
||||
prev_line = line[:len(line) - 1]
|
||||
continue
|
||||
if prev_line:
|
||||
line = prev_line + line
|
||||
prev_line = None
|
||||
# parse ifdef
|
||||
m = re.match(vl_ifdef_re, line)
|
||||
if m:
|
||||
key = m.group(1)
|
||||
cond = m.group(2)
|
||||
taken = find_macro(cond) is not None
|
||||
if key == 'ifndef':
|
||||
taken = not taken
|
||||
elif key == '"elsif':
|
||||
br_stack.pop()
|
||||
br_stack.append(taken)
|
||||
print("*** " + key + "(" + cond + ") => " + str(taken))
|
||||
continue
|
||||
# parse endif
|
||||
m = re.match(vl_endif_re, line)
|
||||
if m:
|
||||
key = m.group(1)
|
||||
top = br_stack.pop()
|
||||
if key == 'else':
|
||||
br_stack.append(not top)
|
||||
print("*** " + key)
|
||||
continue
|
||||
# skip disabled blocks
|
||||
if not all(br_stack):
|
||||
continue
|
||||
|
||||
# parse include
|
||||
m = re.match(vl_include_re, line)
|
||||
if m:
|
||||
include = m.group(1)
|
||||
include = resolve_include_path(include, os.path.dirname(filename))
|
||||
if include:
|
||||
parse_include(include, nesting + 1)
|
||||
continue
|
||||
# parse define
|
||||
m = re.match(vl_define_re, line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
args = m.group(2)
|
||||
if args:
|
||||
args = args[1:len(args)-1].strip()
|
||||
if args != '':
|
||||
args = args.split(',')
|
||||
for i in range(len(args)):
|
||||
args[i] = args[i].strip()
|
||||
else:
|
||||
args = []
|
||||
value = m.group(3)
|
||||
add_macro(name, args, value.strip())
|
||||
continue
|
||||
|
||||
def parse_includes(includes):
|
||||
# change current directory to include directory
|
||||
old_dir = os.getcwd()
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
os.chdir(script_dir)
|
||||
|
||||
for include in includes:
|
||||
parse_include(include, 0)
|
||||
|
||||
# restore current directory
|
||||
os.chdir(old_dir)
|
||||
|
||||
def load_include_dirs(dirs):
|
||||
for dir in dirs:
|
||||
print("*** include dir: " + dir)
|
||||
include_dirs.append(dir)
|
||||
|
||||
def load_defines(defines):
|
||||
for define in defines:
|
||||
key_value = define.split('=', 2)
|
||||
name = key_value[0]
|
||||
value = ''
|
||||
if len(key_value) == 2:
|
||||
value = key_value[1]
|
||||
add_macro(name, None, value)
|
||||
|
||||
def load_config(filename):
|
||||
with open(filename, "r") as f:
|
||||
config = json.load(f)
|
||||
print("condfig=", config)
|
||||
return config
|
||||
|
||||
def gen_cc_header(file, ports):
|
||||
|
||||
header = '''
|
||||
#pragma once\n
|
||||
struct scope_signal_t {
|
||||
int width;
|
||||
const char* name;
|
||||
};\n
|
||||
inline constexpr int __clog2(int n) { return (n > 1) ? 1 + __clog2((n + 1) >> 1) : 0; }\n
|
||||
static constexpr scope_signal_t scope_signals[] = {'''
|
||||
|
||||
footer = "};"
|
||||
|
||||
def eval_macro(text):
|
||||
expanded = expand_text(text)
|
||||
if expanded:
|
||||
text = expanded
|
||||
text = text.replace('$clog2', '__clog2')
|
||||
return text
|
||||
|
||||
def asize_name(asize):
|
||||
def Q(arr, ss, asize, idx, N):
|
||||
for i in range(asize[idx]):
|
||||
tmp = ss + "_" + str(i)
|
||||
if (idx + 1) < N:
|
||||
Q(arr, tmp, asize, idx + 1, N)
|
||||
else:
|
||||
arr.append(tmp)
|
||||
|
||||
l = len(asize)
|
||||
if l == 0:
|
||||
return [""]
|
||||
arr = []
|
||||
Q(arr, "", asize, 0, l)
|
||||
return arr
|
||||
|
||||
with open(file, 'w') as f:
|
||||
print(header, file=f)
|
||||
i = 0
|
||||
for port in ports:
|
||||
name = port[0]
|
||||
size = eval_macro(str(port[1]))
|
||||
for ss in asize_name(port[2]):
|
||||
if i > 0:
|
||||
print(",", file=f)
|
||||
print("\t{" + size + ", \"" + name + ss + "\"}", file=f, end='')
|
||||
i += 1
|
||||
print("", file=f)
|
||||
print(footer, file=f)
|
||||
|
||||
def gen_vl_header(file, taps, triggers):
|
||||
|
||||
header = '''
|
||||
`ifndef VX_SCOPE_DEFS
|
||||
`define VX_SCOPE_DEFS
|
||||
'''
|
||||
footer = '`endif'
|
||||
|
||||
def signal_size(size, asize):
|
||||
str_asize = ""
|
||||
for s in asize:
|
||||
if type(s) == int:
|
||||
str_asize += "[" + str(s-1) + ":0]"
|
||||
else:
|
||||
str_asize += "[" + str(s) + "-1:0]"
|
||||
|
||||
if type(size) == int:
|
||||
size1 = (size-1)
|
||||
if size1 != 0:
|
||||
return str_asize + "[" + str(size1) + ":0]"
|
||||
else:
|
||||
return str_asize
|
||||
else:
|
||||
return str_asize + "[(" + size + ")-1:0]"
|
||||
|
||||
def generate_ports(tclass, tap, ports, new_taps):
|
||||
|
||||
def emit_io(tap, ports, prefix, asize, return_list, new_taps, is_enabled):
|
||||
stap = tap + "_IO"
|
||||
new_taps.append(stap)
|
||||
print("`define " + stap + " \\", file=f)
|
||||
if is_enabled:
|
||||
for key in ports:
|
||||
size = ports[key]
|
||||
name = key
|
||||
is_trigger = False
|
||||
if name[0] == '!':
|
||||
name = name[1:]
|
||||
is_trigger = True
|
||||
if not return_list is None:
|
||||
return_list.append((name + prefix, size, asize, is_trigger))
|
||||
print("\toutput wire" + signal_size(size, asize) + " " + name + prefix + ", \\", file=f)
|
||||
print("", file=f)
|
||||
emit_bind(tap, ports, prefix, prefix, new_taps, is_enabled)
|
||||
|
||||
def emit_bind(tap, ports, from_prefix, to_prefix, new_taps, is_enabled):
|
||||
stap = tap + "_BIND"
|
||||
new_taps.append(stap)
|
||||
print("`define " + stap + " \\", file=f)
|
||||
for key in ports:
|
||||
name = key
|
||||
if name[0] == '!':
|
||||
name = name[1:]
|
||||
if is_enabled:
|
||||
print("\t." + name + to_prefix + " (" + name + from_prefix + "), \\", file=f)
|
||||
else:
|
||||
if (from_prefix != to_prefix):
|
||||
print("\t`UNUSED_PIN (" + name + to_prefix + "), \\", file=f)
|
||||
print("", file=f)
|
||||
|
||||
def emit_select(tap, ports, from_prefix, to_prefix, new_taps, is_enabled):
|
||||
stap = tap + "_SELECT(__i__)"
|
||||
new_taps.append(stap)
|
||||
print("`define " + stap + " \\", file=f)
|
||||
if is_enabled:
|
||||
for key in ports:
|
||||
name = key
|
||||
if name[0] == '!':
|
||||
name = name[1:]
|
||||
print("\t." + name + to_prefix + " (" + name + from_prefix + "[__i__]), \\", file=f)
|
||||
print("", file=f)
|
||||
|
||||
def do_top(tap, ports, new_taps):
|
||||
out_ports = []
|
||||
for p in ports:
|
||||
name = p
|
||||
is_trigger = False
|
||||
if name[0] == '!':
|
||||
name = name[1:]
|
||||
is_trigger = True
|
||||
out_ports.append((name, ports[p], [], is_trigger))
|
||||
return out_ports
|
||||
|
||||
def do_core(tap, ports, new_taps):
|
||||
out_ports = []
|
||||
nclusters = parameters["NUM_CLUSTERS"]
|
||||
ncores = parameters["NUM_CORES"]
|
||||
emit_io(tap + "_TOP", ports, "_top", [nclusters, ncores], out_ports, new_taps, True)
|
||||
emit_io(tap + "_CLUSTER", ports, "_cluster", [ncores], None, new_taps, True)
|
||||
emit_io(tap + "", ports, "", [], None, new_taps, True)
|
||||
emit_select(tap + "_CLUSTER", ports, "_top", "_cluster", new_taps, True)
|
||||
emit_select(tap + "", ports, "_cluster", "", new_taps, True)
|
||||
return out_ports
|
||||
|
||||
def do_bank(tap, ports, new_taps):
|
||||
out_ports = []
|
||||
|
||||
nclusters = parameters["NUM_CLUSTERS"]
|
||||
ncores = parameters["NUM_CORES"]
|
||||
has_l3 = (parameters["L3_ENABLE"] != 0)
|
||||
has_l2 = (parameters["L2_ENABLE"] != 0)
|
||||
|
||||
emit_io(tap + "_L3_TOP", ports, "_l3_cache", [parameters["L3NUM_BANKS"]], out_ports, new_taps, has_l3)
|
||||
emit_io(tap + "_L2_TOP", ports, "_l2_top", [nclusters, parameters["L2NUM_BANKS"]], out_ports, new_taps, has_l2)
|
||||
emit_io(tap + "_L1D_TOP", ports, "_l1d_top", [nclusters, ncores, parameters["DNUM_BANKS"]], out_ports, new_taps, True)
|
||||
emit_io(tap + "_L1I_TOP", ports, "_l1i_top", [nclusters, ncores, parameters["INUM_BANKS"]], out_ports, new_taps, True)
|
||||
emit_io(tap + "_L1S_TOP", ports, "_l1s_top", [nclusters, ncores, parameters["SNUM_BANKS"]], out_ports, new_taps, True)
|
||||
|
||||
emit_io(tap + "_L2_CLUSTER", ports, "_l2_cache", [parameters["L2NUM_BANKS"]], None, new_taps, has_l2)
|
||||
emit_io(tap + "_L1D_CLUSTER", ports, "_l1d_cluster", [ncores, parameters["DNUM_BANKS"]], None, new_taps, True)
|
||||
emit_io(tap + "_L1I_CLUSTER", ports, "_l1i_cluster", [ncores, parameters["INUM_BANKS"]], None, new_taps, True)
|
||||
emit_io(tap + "_L1S_CLUSTER", ports, "_l1s_cluster", [ncores, parameters["SNUM_BANKS"]], None, new_taps, True)
|
||||
|
||||
emit_io(tap + "_L1D_CORE", ports, "_l1d_cache", [parameters["DNUM_BANKS"]], None, new_taps, True)
|
||||
emit_io(tap + "_L1I_CORE", ports, "_l1i_cache", [parameters["INUM_BANKS"]], None, new_taps, True)
|
||||
emit_io(tap + "_L1S_CORE", ports, "_l1s_cache", [parameters["SNUM_BANKS"]], None, new_taps, True)
|
||||
|
||||
emit_io(tap + "_CACHE", ports, "_cache", ["NUM_BANKS"], None, new_taps, True)
|
||||
emit_io(tap + "", ports, "", [], None, new_taps, True)
|
||||
|
||||
emit_select(tap + "_L2_CLUSTER", ports, "_l2_top", "_l2_cache", new_taps, has_l2)
|
||||
emit_select(tap + "_L1D_CLUSTER", ports, "_l1d_top", "_l1d_cluster", new_taps, True)
|
||||
emit_select(tap + "_L1I_CLUSTER", ports, "_l1i_top", "_l1i_cluster", new_taps, True)
|
||||
emit_select(tap + "_L1S_CLUSTER", ports, "_l1s_top", "_l1s_cluster", new_taps, True)
|
||||
|
||||
emit_select(tap + "_L1D_CORE", ports, "_l1d_cluster", "_l1d_cache", new_taps, True)
|
||||
emit_select(tap + "_L1I_CORE", ports, "_l1i_cluster", "_l1i_cache", new_taps, True)
|
||||
emit_select(tap + "_L1S_CORE", ports, "_l1s_cluster", "_l1s_cache", new_taps, True)
|
||||
|
||||
emit_bind(tap + "_L3_CACHE", ports, "_l3_cache", "_cache", new_taps, has_l3)
|
||||
emit_bind(tap + "_L2_CACHE", ports, "_l2_cache", "_cache", new_taps, has_l2)
|
||||
emit_bind(tap + "_L1D_CACHE", ports, "_l1d_cache", "_cache", new_taps, True)
|
||||
emit_bind(tap + "_L1I_CACHE", ports, "_l1i_cache", "_cache", new_taps, True)
|
||||
emit_bind(tap + "_L1S_CACHE", ports, "_l1s_cache", "_cache", new_taps, True)
|
||||
|
||||
emit_select(tap + "", ports, "_cache", "", new_taps, True)
|
||||
|
||||
return out_ports
|
||||
|
||||
callbacks = {
|
||||
"top": do_top,
|
||||
"core": do_core,
|
||||
"bank": do_bank
|
||||
}
|
||||
|
||||
return callbacks[tclass](tap, ports, new_taps)
|
||||
|
||||
def trigger_size(name, ports):
|
||||
for port in ports:
|
||||
if port[0] == name:
|
||||
return (port[1], port[2])
|
||||
return None
|
||||
|
||||
def trigger_prefices(asize):
|
||||
def Q(arr, ss, asize, idx, N):
|
||||
for i in range(asize[idx]):
|
||||
tmp = ss + '[' + str(i) + ']'
|
||||
if (idx + 1) < N:
|
||||
Q(arr, tmp, asize, idx + 1, N)
|
||||
else:
|
||||
arr.append(tmp)
|
||||
|
||||
l = len(asize)
|
||||
if l == 0:
|
||||
return [""]
|
||||
arr = []
|
||||
Q(arr, "", asize, 0, l)
|
||||
return arr
|
||||
|
||||
def trigger_name(name, size):
|
||||
if type(size) == int:
|
||||
size1 = (size-1)
|
||||
if size1 != 0:
|
||||
return "(| " + name + ")"
|
||||
else:
|
||||
return name
|
||||
else:
|
||||
return "(| " + name + ")"
|
||||
|
||||
with open(file, 'w') as f:
|
||||
print(header, file=f)
|
||||
|
||||
all_ports = []
|
||||
new_taps = []
|
||||
|
||||
for key in taps:
|
||||
[tclass, tap] = key.split('::')
|
||||
ports = generate_ports(tclass, tap, taps[key], new_taps)
|
||||
for port in ports:
|
||||
all_ports.append(port)
|
||||
|
||||
print("`define SCOPE_SIGNALS_DECL \\", file=f)
|
||||
i = 0
|
||||
for port in all_ports:
|
||||
if i > 0:
|
||||
print(" \\", file=f)
|
||||
print("\twire" + signal_size(port[1], port[2]) + " " + port[0] + ";", file=f, end='')
|
||||
i += 1
|
||||
print("", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print("`define SCOPE_SIGNALS_DATA_LIST \\", file=f)
|
||||
i = 0
|
||||
for port in all_ports:
|
||||
if port[3]:
|
||||
continue
|
||||
if i > 0:
|
||||
print(", \\", file=f)
|
||||
print("\t" + port[0], file=f, end='')
|
||||
i += 1
|
||||
print("", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print("`define SCOPE_SIGNALS_UPD_LIST \\", file=f)
|
||||
i = 0
|
||||
for port in all_ports:
|
||||
if not port[3]:
|
||||
continue
|
||||
if i > 0:
|
||||
print(", \\", file=f)
|
||||
print("\t" + port[0], file=f, end='')
|
||||
i += 1
|
||||
print("", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print("`define SCOPE_TRIGGERS \\", file=f)
|
||||
i = 0
|
||||
for trigger in triggers:
|
||||
arr = trigger_size(trigger[0], all_ports)
|
||||
if arr is None:
|
||||
continue
|
||||
[size, asize] = arr
|
||||
for prefix in trigger_prefices(asize):
|
||||
if i > 0:
|
||||
print(" | \\", file=f)
|
||||
print("\t(", file=f, end='')
|
||||
for j in range(len(trigger)):
|
||||
if j > 0:
|
||||
print(" && ", file=f, end='')
|
||||
print(trigger_name(trigger[j] + prefix, size), file=f, end='')
|
||||
print(")", file=f, end='')
|
||||
i += 1
|
||||
print("", file=f)
|
||||
print("", file=f)
|
||||
|
||||
print(footer, file=f)
|
||||
|
||||
return all_ports
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Scope headers generator.')
|
||||
parser.add_argument('-vl', nargs='?', default='scope-defs.vh', metavar='file', help='Output Verilog header')
|
||||
parser.add_argument('-cc', nargs='?', default='scope-defs.h', metavar='file', help='Output C++ header')
|
||||
parser.add_argument('-D', nargs='?', action='append', metavar='macro[=value]', help='define macro')
|
||||
parser.add_argument('-I', nargs='?', action='append', metavar='<includedir>', help='include directory')
|
||||
parser.add_argument('config', help='Json config file')
|
||||
args = parser.parse_args()
|
||||
print("args=", args)
|
||||
|
||||
global parameters
|
||||
global exclude_files
|
||||
global include_dirs
|
||||
global macros
|
||||
global br_stack
|
||||
|
||||
if args.I:
|
||||
load_include_dirs(args.I)
|
||||
|
||||
if args.D:
|
||||
load_defines(args.D)
|
||||
|
||||
config = load_config(args.config)
|
||||
|
||||
exclude_files.append(os.path.basename(args.vl))
|
||||
|
||||
if "includes" in config:
|
||||
parse_includes(config["includes"])
|
||||
|
||||
parameters = config["parameters"]
|
||||
for key in parameters:
|
||||
parameters[key] = int(eval(expand_text(str(parameters[key]))))
|
||||
|
||||
ports = gen_vl_header(args.vl, config["taps"], config["triggers"])
|
||||
gen_cc_header(args.cc, ports)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user