mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 21:07:34 -04:00
Create a clean code generation script for littleRISCV called ri5cly-manage.py
This commit is contained in:
parent
7c99161125
commit
00a2c3a8fb
7 changed files with 222 additions and 15 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1 @@
|
|||
*.swp
|
||||
|
||||
|
||||
|
|
|
@ -602,7 +602,6 @@ module riscv_decoder
|
|||
{6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical
|
||||
{6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic
|
||||
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
// supported RV32M instructions
|
||||
|
@ -1096,6 +1095,9 @@ module riscv_decoder
|
|||
end
|
||||
|
||||
|
||||
// CONFIG_REGION: HWL_SUPPORT
|
||||
`ifdef HWL_SUPPORT
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// _ ___ ___ ___ ___ ____ //
|
||||
// | | | \ \ / / | / _ \ / _ \| _ \ //
|
||||
|
@ -1105,8 +1107,7 @@ module riscv_decoder
|
|||
// //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
// CONFIG_REGION: HWL_SUPPORT
|
||||
`ifdef HWL_SUPPORT
|
||||
|
||||
OPCODE_HWLOOP: begin
|
||||
hwloop_target_mux_sel_o = 1'b0;
|
||||
|
||||
|
|
|
@ -231,6 +231,9 @@ module riscv_ex_stage
|
|||
`endif // SIMPLE_ALU
|
||||
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// __ __ _ _ _ _____ ___ ____ _ ___ _____ ____ //
|
||||
// | \/ | | | | | |_ _|_ _| _ \| | |_ _| ____| _ \ //
|
||||
|
@ -240,8 +243,7 @@ module riscv_ex_stage
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
|
||||
riscv_mult mult_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
|
|
13
id_stage.sv
13
id_stage.sv
|
@ -82,7 +82,6 @@ module riscv_id_stage
|
|||
input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage
|
||||
output logic instr_req_o,
|
||||
|
||||
|
||||
// Jumps and branches
|
||||
output logic branch_in_ex_o,
|
||||
input logic branch_decision_i,
|
||||
|
@ -126,7 +125,7 @@ module riscv_id_stage
|
|||
output logic [ 4:0] bmask_b_ex_o,
|
||||
`endif // BIT_SUPPORT
|
||||
|
||||
// CONFIG_REGION: VEC_SUPPORT
|
||||
// CONFIG_REGION: VEC_SUPPORT
|
||||
`ifdef VEC_SUPPORT
|
||||
output logic [ 1:0] imm_vec_ext_ex_o,
|
||||
output logic [ 1:0] alu_vec_mode_ex_o,
|
||||
|
@ -141,7 +140,6 @@ module riscv_id_stage
|
|||
// ALU
|
||||
output logic [ALU_OP_WIDTH-1:0] alu_operator_ex_o,
|
||||
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
// MUL
|
||||
|
@ -583,6 +581,10 @@ module riscv_id_stage
|
|||
assign mult_en = mult_int_en | mult_dot_en;
|
||||
`endif // MUL_SUPPORT
|
||||
|
||||
|
||||
// CONFIG_REGION: HWL_SUPPORT
|
||||
`ifdef HWL_SUPPORT
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// _ ___ ___ ___ ___ ____ //
|
||||
// | | | \ \ / / | / _ \ / _ \| _ \ //
|
||||
|
@ -592,8 +594,7 @@ module riscv_id_stage
|
|||
// //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
// CONFIG_REGION: HWL_SUPPORT
|
||||
`ifdef HWL_SUPPORT
|
||||
|
||||
// hwloop register id
|
||||
assign hwloop_regid_int = instr[7]; // rd contains hwloop register id
|
||||
|
||||
|
@ -914,7 +915,7 @@ module riscv_id_stage
|
|||
default: mult_imm_id = '0;
|
||||
endcase
|
||||
end
|
||||
`endif // MUL_SUPPORT
|
||||
`endif // MUL_SUPPORT
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// ____ _____ ____ ___ ____ _____ _____ ____ ____ //
|
||||
|
|
|
@ -32,7 +32,15 @@
|
|||
`endif
|
||||
|
||||
|
||||
// littleRISCV configuration. Decomment to enable.
|
||||
// littleRISCV configuration.
|
||||
|
||||
// Decomment to enable.
|
||||
|
||||
// The format should be strictly followed so the ri5cly-manage tool can parse the configuration
|
||||
// A CONFIG section declares a config definition, a CONFIG_REGION enables the tool to remove disabled code
|
||||
// for export. See the ri5cly-manage.py tool help and source code in the /scripts folder for more information.
|
||||
|
||||
|
||||
|
||||
// CONFIG: MUL_SUPPORT
|
||||
// will enable RISCV32M support for multiplication, division, MAC operations. Uses a lot of multiplications
|
||||
|
@ -73,6 +81,7 @@
|
|||
|
||||
// Dependent definitions
|
||||
|
||||
// CONFIG: THREE_PORT_REG_FILE
|
||||
// enables 3r2w reg file (rather than 2r1w)
|
||||
//`define THREE_PORT_REG_FILE
|
||||
|
||||
|
@ -96,7 +105,6 @@
|
|||
// will reduce the register file to 16 words
|
||||
`define RV32E
|
||||
|
||||
|
||||
`endif
|
||||
`endif
|
||||
`endif
|
||||
|
|
2
scripts/.gitignore
vendored
Normal file
2
scripts/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
build/
|
||||
.idea/
|
195
scripts/ri5cly-manage.py
Normal file
195
scripts/ri5cly-manage.py
Normal file
|
@ -0,0 +1,195 @@
|
|||
#!/bin/python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import argparse
|
||||
|
||||
import re
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
littleRISCV_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/..") # Path to littleRISCV folder
|
||||
print(littleRISCV_path)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Can overwrite config and export clean version of littleRISCV")
|
||||
parser.add_argument('-i', dest="new_riscv_config", metavar='.../new_riscv_config.sv',
|
||||
help='path to a new config file to overwrite littleRISCV config')
|
||||
parser.add_argument('-o', dest='build_folder_path', metavar='.../build_folder_path',
|
||||
help='path to a folder to export clean version of littleRISCV without preprocessor switches')
|
||||
parser.add_argument('-z', dest='zip', action='store_true',
|
||||
help='zip the export into a tar.gz')
|
||||
args = parser.parse_args()
|
||||
|
||||
action_taken = False
|
||||
|
||||
if args.new_riscv_config is not None:
|
||||
overwriteConfig(args["new_riscv_config.sv"], littleRISCV_path)
|
||||
action_taken = True
|
||||
|
||||
if args.build_folder_path is not None:
|
||||
exportCleanVersion(args.build_folder_path, littleRISCV_path, zip=args.zip)
|
||||
action_taken = True
|
||||
|
||||
if action_taken == False:
|
||||
print("No action taken. Please see the help below for more information:")
|
||||
parser.print_help()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def overwriteConfig(new_config_path, littleRISCV_path):
|
||||
print("Overwriting current config (include/riscv_config.sv) with new one.")
|
||||
shutil.move(os.path.abspath(littleRISCV_path + "/include/riscv_config.sv"), os.path.abspath(littleRISCV_path + "/include/riscv_config.sv.bak")) # Backup
|
||||
shutil.copy(os.path.abspath(new_config_path), os.path.abspath(littleRISCV_path + "/include/riscv_config.sv")) # Copy new config to littleRISCV
|
||||
|
||||
|
||||
def parseConfig(littleRISCV_path):
|
||||
print("Trying to parse configuration.")
|
||||
definitions = []
|
||||
config = os.path.abspath(littleRISCV_path + "/include/riscv_config.sv")
|
||||
|
||||
with open(config, encoding="utf8") as f:
|
||||
nesting_counter = 0 # If we enter a not-enabled section, keep track when we leave the section again
|
||||
|
||||
content = f.readlines()
|
||||
while len(content) > 0:
|
||||
line = content.pop(0)
|
||||
|
||||
config_pattern = re.compile("^//.*CONFIG:\s(\w*)$") # Test for config declaration
|
||||
m = config_pattern.match(line)
|
||||
if m is not None and nesting_counter == 0:
|
||||
content.pop(0) # Pop description
|
||||
line = content.pop(0)
|
||||
|
||||
config_value_pattern = re.compile("^`define\s(\w*)$") # Check if config enabled and extract name
|
||||
m = config_value_pattern.match(line)
|
||||
if m is not None:
|
||||
definitions.append(m.group(1))
|
||||
else:
|
||||
ifdef_pattern = re.compile("^`ifdef\s(\w*)$") # Check if we have a dependant config
|
||||
m = ifdef_pattern.match(line)
|
||||
if m is not None:
|
||||
if m.group(1) in definitions:
|
||||
pass
|
||||
else:
|
||||
nesting_counter += 1
|
||||
|
||||
ifndef_pattern = re.compile("^`ifndef\s(\w*)$") # Check if we have a dependant config
|
||||
m = ifndef_pattern.match(line)
|
||||
if m is not None:
|
||||
if not (m.group(1) in definitions):
|
||||
pass
|
||||
else:
|
||||
nesting_counter += 1
|
||||
|
||||
endif_pattern = re.compile("^`endif.*$") # Check if we ended a block
|
||||
m = endif_pattern.match(line)
|
||||
if m is not None:
|
||||
nesting_counter -= 1
|
||||
if nesting_counter < 0:
|
||||
nesting_counter = 0
|
||||
|
||||
print("Enabled CONFIG definitions: {}".format(definitions))
|
||||
return definitions
|
||||
|
||||
def processSystemVerilog(filename, folderpath, definitions):
|
||||
print("Processing: {}".format(filename))
|
||||
|
||||
content = []
|
||||
new_content = []
|
||||
|
||||
with open(os.path.abspath(folderpath+"/"+filename), encoding="utf8") as f:
|
||||
content = f.readlines()
|
||||
|
||||
nesting_counter = 0 # If we enter a not-enabled section, keep track when we leave the section again
|
||||
is_else_true = False # at first occurence of missing declarations
|
||||
|
||||
while len(content) > 0:
|
||||
is_codeline = True
|
||||
line = content.pop(0)
|
||||
|
||||
config_pattern = re.compile("^\s*//.*CONFIG_REGION:\s(\w*)$") # Test for config region declaration
|
||||
m = config_pattern.match(line)
|
||||
if m is not None:
|
||||
is_codeline = False
|
||||
line = content.pop(0)
|
||||
|
||||
ifdef_pattern = re.compile("^\s*`ifdef\s(\w*)$") # Check if we have an ifdef
|
||||
m = ifdef_pattern.match(line)
|
||||
if m is not None:
|
||||
if m.group(1) in definitions:
|
||||
if nesting_counter == 0:
|
||||
is_else_true = False
|
||||
else:
|
||||
nesting_counter += 1
|
||||
else:
|
||||
if nesting_counter == 0:
|
||||
is_else_true = True
|
||||
nesting_counter += 1
|
||||
|
||||
|
||||
ifndef_pattern = re.compile("^\s*`ifndef\s(\w*)$") # Check if we have an ifndef
|
||||
m = ifndef_pattern.match(line)
|
||||
if m is not None:
|
||||
if not (m.group(1) in definitions):
|
||||
if nesting_counter == 0:
|
||||
is_else_true = False
|
||||
else:
|
||||
nesting_counter += 1
|
||||
else:
|
||||
if nesting_counter == 0:
|
||||
is_else_true = True
|
||||
nesting_counter += 1
|
||||
|
||||
else_pattern = re.compile("^\s*`else.*$") # Check if we have an else
|
||||
m = else_pattern.match(line)
|
||||
if m is not None:
|
||||
is_codeline = False
|
||||
if nesting_counter == 1 and is_else_true:
|
||||
nesting_counter -= 1
|
||||
if (not is_else_true) and nesting_counter == 0:
|
||||
nesting_counter += 1
|
||||
|
||||
endif_pattern = re.compile("^\s*`endif.*$") # Check if we have an endif
|
||||
m = endif_pattern.match(line)
|
||||
if m is not None:
|
||||
is_codeline = False
|
||||
nesting_counter -= 1
|
||||
if nesting_counter < 0:
|
||||
nesting_counter = 0
|
||||
|
||||
if is_codeline and nesting_counter == 0:
|
||||
new_content.append(line)
|
||||
|
||||
os.remove(os.path.abspath(folderpath+"/"+filename))
|
||||
|
||||
with open(os.path.abspath(folderpath+"/"+filename), 'w', encoding="utf8") as f:
|
||||
f.writelines(new_content)
|
||||
|
||||
|
||||
def exportCleanVersion(build_path, littleRISCV_path, zip=False):
|
||||
print("Exporting clean version of littleRISCV without preprocessor switches to defined output folder.")
|
||||
definitions = parseConfig(littleRISCV_path)
|
||||
|
||||
shutil.rmtree(os.path.abspath(build_path), ignore_errors=True)
|
||||
shutil.copytree(os.path.abspath(littleRISCV_path), os.path.abspath(build_path), ignore=shutil.ignore_patterns("*.git", "scripts", "docs"))
|
||||
|
||||
|
||||
for filename in os.listdir(os.path.abspath(build_path)):
|
||||
sv_p = re.compile("^.*\.sv")
|
||||
m = sv_p.match(filename)
|
||||
if m is not None:
|
||||
processSystemVerilog(filename, build_path, definitions)
|
||||
|
||||
with open(os.path.abspath(build_path+"/THIS_CORE_IS_AUTOMATICALLY_GENERATATED!!!.txt"), 'w', encoding="utf8") as f:
|
||||
f.write("This core export was automatically generated by ri5cly-manage.py\n\n")
|
||||
f.write("Following settings were enabled: {}".format(definitions))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue