Skip to content

Commit

Permalink
[util] Make version information a class
Browse files Browse the repository at this point in the history
Instead of treating version_stamp like a dictionary with specific
name entries, turn it into a class with proper accessors so that
the particular representation of the version information is
abstracted.

Signed-off-by: Amaury Pouly <[email protected]>
  • Loading branch information
pamaury committed Jan 22, 2024
1 parent 8bb743a commit f908735
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 62 deletions.
25 changes: 12 additions & 13 deletions util/reggen/gen_tock.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
import sys
import textwrap
import warnings
from datetime import datetime
from typing import Any, Dict, Optional, Set, TextIO
from typing import Any, Optional, Set, TextIO

from reggen.ip_block import IpBlock
from reggen.multi_register import MultiRegister
from reggen.params import LocalParam
from reggen.register import Register
from reggen.window import Window

from version_file import VersionInformation

REG_VISIBILITY = 'pub(crate)'
FIELD_VISIBILITY = 'pub(crate)'

Expand Down Expand Up @@ -327,7 +328,7 @@ def gen_const_interrupts(fieldout: TextIO, block: IpBlock, component: str,

def gen_tock(block: IpBlock, outfile: TextIO, src_file: Optional[str],
src_lic: Optional[str], src_copy: str,
version_stamp: Dict[str, str]) -> int:
version: VersionInformation) -> int:
rnames = block.get_rnames()

paramout = io.StringIO()
Expand Down Expand Up @@ -397,16 +398,14 @@ def gen_tock(block: IpBlock, outfile: TextIO, src_file: Optional[str],
genout(outfile, '\n')
genout(outfile, '// Generated register constants for {}.\n', block.name)

if 'BUILD_GIT_VERSION' in version_stamp:
genout(outfile, '// Built for {}\n', version_stamp['BUILD_GIT_VERSION'])
if 'BUILD_SCM_REVISION' in version_stamp:
genout(outfile, '// https://github.com/lowRISC/opentitan/tree/{}\n', version_stamp['BUILD_SCM_REVISION'])
if 'BUILD_SCM_STATUS' in version_stamp:
genout(outfile, '// Tree status: {}\n', version_stamp['BUILD_SCM_STATUS'])
if 'BUILD_TIMESTAMP' in version_stamp:
tm = int(version_stamp['BUILD_TIMESTAMP'])
dt = datetime.utcfromtimestamp(tm)
genout(outfile, '// Build date: {}\n\n', dt.isoformat())
if version.scm_version() is not None:
genout(outfile, '// Built for {}\n', version.scm_version())
if version.scm_revision() is not None:
genout(outfile, '// https://github.com/lowRISC/opentitan/tree/{}\n', version.scm_revision())
if version.scm_status() is not None:
genout(outfile, '// Tree status: {}\n', version.scm_status())
if version.build_datetime() is not None:
genout(outfile, '// Build date: {}\n\n', version.build_datetime())

if src_file:
genout(outfile, '// Original reference file: {}\n', src_file)
Expand Down
2 changes: 1 addition & 1 deletion util/regtool.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def main():
sys.exit(1)

# Extract version stamp from file
version_stamp = version_file.parse_version_file(args.version_stamp)
version_stamp = version_file.VersionInformation(args.version_stamp)

if fmt == 'doc':
with outfile:
Expand Down
6 changes: 4 additions & 2 deletions util/rom_chip_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ def read_version_file(version_info) -> int:
if the variable is not found.
"""

version = version_info.get('BUILD_SCM_REVISION', "8badF00d")
# If there is no revision information, we still need some
# number to encode in chip_info: choose a recognizable one.
version = version_info.scm_revision("8badf00d")
return int(version, base=16)


Expand Down Expand Up @@ -84,7 +86,7 @@ def main():
args = parser.parse_args()

# Extract version stamp from file
version = read_version_file(version_file.parse_version_file(args.ot_version_file))
version = read_version_file(version_file.VersionInformation(args.ot_version_file))
log.info("Version: %x" % (version, ))

generated_source = generate_chip_info_c_source(version)
Expand Down
2 changes: 1 addition & 1 deletion util/topgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ def main():
raise SystemExit(sys.exc_info()[1])

# Extract version stamp from file
version_stamp = version_file.parse_version_file(args.version_stamp)
version_stamp = version_file.VersionInformation(args.version_stamp)

# Initialize RNG for compile-time netlist constants.
# If specified, override the seed for random netlist constant computation.
Expand Down
40 changes: 12 additions & 28 deletions util/topgen/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"""This contains a class which is used to help generate `top_{name}.rs`."""
from collections import OrderedDict, defaultdict
from typing import Dict, List, Optional, Tuple
from datetime import datetime

from mako.template import Template
from reggen.ip_block import IpBlock
Expand Down Expand Up @@ -188,35 +187,20 @@ def render_definition(self):


class RustFileHeader(object):
def __init__(self, name: str, version_stamp: Dict[str, str], skip: bool):
self.name = name
def __init__(self, name: str, version_stamp):
self.data = version_stamp
self.skip = skip
tm = int(version_stamp.get('BUILD_TIMESTAMP', 0))
self.tstamp = datetime.utcfromtimestamp(tm) if tm else datetime.utcnow()

def build(self) -> str:
return self.data.get('BUILD_GIT_VERSION', '<unknown>')

def scm_sha(self) -> str:
return self.data.get('BUILD_SCM_REVISION', '<unknown>')

def scm_status(self) -> str:
return self.data.get('BUILD_SCM_STATUS', '<unknown>')

def time_stamp(self) -> str:
return self.tstamp.isoformat()

def render(self):
if self.skip:
return Template(("")).render(header=self)
else:
template = ("\n"
"// Built for ${header.build()}\n"
"// https://github.com/lowRISC/opentitan/tree/${header.scm_sha()}\n"
"// Tree status: ${header.scm_status()}\n"
"// Build date: ${header.time_stamp()}\n")
return Template(template).render(header=self)
template = "\n";
if self.data.scm_version() is not None:
template += "// Built for ${header.build()}\n"
if self.data.scm_revision() is not None:
template += "// https://github.com/lowRISC/opentitan/tree/${header.scm_sha()}\n"
if self.data.scm_status() is not None:
template += "// Tree status: ${header.scm_status()}\n"
if self.data.build_datetime() is not None:
template += "// Build date: ${header.time_stamp()}\n"
return Template(template).render(header=self)


class TopGenRust:
Expand All @@ -225,7 +209,7 @@ def __init__(self, top_info, name_to_block: Dict[str, IpBlock], version_stamp: D
self._top_name = Name(["top"]) + Name.from_snake_case(top_info["name"])
self._name_to_block = name_to_block
self.regwidth = int(top_info["datawidth"])
self.file_header = RustFileHeader("foo.tpl", version_stamp, len(version_stamp) == 0)
self.file_header = RustFileHeader(version_stamp)

self._init_plic_targets()
self._init_plic_mapping()
Expand Down
52 changes: 35 additions & 17 deletions util/version_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,40 @@
# SPDX-License-Identifier: Apache-2.0

import sys
from datetime import datetime


def parse_version_file(path):
"""
Parse a bazel version file and return a dictionary of the values.
If `path` is None, an empty dictionary is returned.
If an error occurs during parsing, an exception is raised.
"""
if path is None:
return {}
version_stamp = {}
try:
with open(path, 'rt') as f:
for line in f:
k, v = line.strip().split(' ', 1)
version_stamp[k] = v
except ValueError:
raise SystemExit(sys.exc_info()[1])
return version_stamp
class VersionInformation():
def __init__(self, path):
"""
Parse a bazel version file and store a dictionary of the values.
If `path` is None, an empty dictionary will be created.
If an error occurs during parsing, an exception is raised.
"""
self.version_stamp = {}
if path is None:
return
try:
with open(path, 'rt') as f:
for line in f:
k, v = line.strip().split(' ', 1)
self.version_stamp[k] = v
except ValueError:
raise SystemExit(sys.exc_info()[1])

def scm_version(self, default = None):
return self.version_stamp.get('BUILD_GIT_VERSION', default)

def scm_revision(self, default = None):
return self.version_stamp.get('BUILD_SCM_REVISION', default)

def scm_status(self, default = None):
return self.version_stamp.get('BUILD_SCM_STATUS', default)

def build_datetime(self, default = None):
if 'BUILD_TIMESTAMP' in self.version_stamp:
tm = int(self.version_stamp['BUILD_TIMESTAMP'])
dt = datetime.utcfromtimestamp(tm)
return dt
else:
return default

0 comments on commit f908735

Please sign in to comment.