diff --git a/srdl2sv/cli/cli.py b/srdl2sv/cli/cli.py index 464b68c..389f637 100644 --- a/srdl2sv/cli/cli.py +++ b/srdl2sv/cli/cli.py @@ -1,29 +1,46 @@ import argparse import os +import time +import logging from itertools import chain +logging_map = { + "DEBUG": logging.DEBUG, + "INFO": logging.INFO, + "WARNING": logging.WARNING, + "ERROR": logging.ERROR, + "CRITICAL": logging.CRITICAL, + "NONE": logging.NOTSET +} + class CliArguments(): + def __init__(self): self.parser = argparse.ArgumentParser( description="SystemRDL 2 SystemVerilog compiler") self.parser.add_argument( - "-v", - "--verbosity", - action="count", - help="Increase output verbosity.") + "--stream_log_level", + choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'NONE'], + default='WARNING', + help="Set verbosity level of output to shell. When set to 'NONE',\ + nothing will be printed to the shell. (default: %(default)s)") self.parser.add_argument( - "-q", - "--quiet", - action="store_true") + "--file_log_level", + choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'NONE'], + default='INFO', + help="Set verbosity level of output to log-file. When set to 'NONE',\ + nothing will be printed to the shell. (default: %(default)s)") self.parser.add_argument( "-o", "--out_dir", type=str, + default="./srdl2sv_out", help="Define output directory to dump files.\ - If directory is non-existent, it will be created.") + If directory is non-existent, it will be created.\ + (default: %(default)s)") self.parser.add_argument( "-d", @@ -49,15 +66,29 @@ class CliArguments(): def get_config(self) -> dict(): args = self.parser.parse_args() + # Create dictionary to save config in config = dict() + # Save input file and output directory to dump everything in config['input_file'] = args.IN_RDL - config['verbosity'] = args.verbosity - config['quiet'] = args.quiet + config['output_dir'] = args.out_dir + # Map logging level string to integers + config['stream_log_level'] = logging_map[args.stream_log_level] + config['file_log_level'] = logging_map[args.file_log_level] + + # Determine paths to be passed to systemrdl-compiler to search + # for include files. if args.recursive_search: config['search_paths'] = [x[0] for y in args.search_paths for x in os.walk(y)] else: config['search_paths'] = args.search_paths + # Save timestamp, so that it can be used across the compiler + config['ts'] = time.localtime() + + # Determine name of file to hold logs + ts = time.strftime('%Y%m%d_%H%M%S', config['ts']) + config['file_log_location'] = "srdl2sv_{}.log".format(ts) + return config diff --git a/srdl2sv/log/__init__.py b/srdl2sv/log/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/srdl2sv/log/log.py b/srdl2sv/log/log.py new file mode 100644 index 0000000..13d730c --- /dev/null +++ b/srdl2sv/log/log.py @@ -0,0 +1,59 @@ +import logging +from typing import Optional + +class CustomFormatter(logging.Formatter): + """Logging Formatter to add colors and count warning / errors""" + + MAPPING = { + 'DEBUG' : 37, # white + 'INFO' : 32, # green + 'WARNING' : 33, # yellow + 'ERROR' : 31, # red + 'CRITICAL': 41, # white on red bg + } + + PREFIX = '\033[' + SUFFIX = '\033[0m' + + def format(self, record): + colored_record = record + levelname = colored_record.levelname + seq = CustomFormatter.MAPPING.get(levelname, 37) # default white + colored_levelname = ('{0}{1}m{2}{3}') \ + .format( + CustomFormatter.PREFIX, + seq, + levelname, + CustomFormatter.SUFFIX) + colored_record.levelname = colored_levelname + + return logging.Formatter.format(self, colored_record) + +def create_logger ( + mod_name, + stream_log_level: int = logging.WARNING, + file_log_level: int = logging.INFO, + file_name: Optional[str] = None): + + log = logging.getLogger(mod_name) + log.setLevel(min(stream_log_level, file_log_level)) + + if file_log_level > 0 and file_name: + file_handler = logging.FileHandler(file_name) + file_handler.setLevel(file_log_level) + + file_formatter = logging.Formatter( + "%(asctime)s - %(levelname)s - %(name)s: %(message)s") + file_handler.setFormatter(file_formatter) + log.addHandler(file_handler) + + if stream_log_level > 0: + stream_handler = logging.StreamHandler() + stream_handler.setLevel(stream_log_level) + + stream_formatter = CustomFormatter( + "[%(levelname)s][%(name)s] %(message)s") + stream_handler.setFormatter(stream_formatter) + log.addHandler(stream_handler) + + return log diff --git a/srdl2sv/main.py b/srdl2sv/main.py index 815cec6..d6376f6 100755 --- a/srdl2sv/main.py +++ b/srdl2sv/main.py @@ -10,6 +10,7 @@ from systemrdl import RDLCompiler, RDLCompileError # Local modules from components.addrmap import AddrMap from cli.cli import CliArguments +from log.log import create_logger if __name__ == "__main__": # Take start timestamp @@ -33,8 +34,9 @@ if __name__ == "__main__": addrmap = AddrMap(rdlc, root.top) - print("====================================================") - print("Elapsed time: {} seconds".format(time.time() - start)) - print("====================================================") - - + logger = create_logger( + __name__, + stream_log_level=config['stream_log_level'], + file_log_level=config['file_log_level'], + file_name=config['file_log_location']) + logger.info("Elapsed time: %f seconds", time.time() - start)