Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass iob_soc attributes via python parameters to iob_system parent. #955

Merged
merged 3 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions iob_soc.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
def setup(py_params_dict):
attributes_dict = {
# Py2hwsw dictionary describing current core
core_dict = {
"original_name": "iob_soc",
"name": "iob_soc",
"parent": {"core_name": "iob_system", **py_params_dict},
"version": "0.1",
"parent": {"core_name": "iob_system", **py_params_dict},
}

# Dictionary of "iob_system" attributes to override/append
system_overrides = {
"ports": [
{
"name": "rs232_m",
Expand All @@ -18,35 +23,29 @@ def setup(py_params_dict):
"core_name": "iob_uart",
"instance_name": "UART0",
"instance_description": "UART peripheral",
"is_peripheral": True,
"parameters": {
"ADDR_W": "29", # TODO: Automate this with iob_system scripts
},
"peripheral_addr_w": 3,
"parameters": {},
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
# TODO: Cbus should be connected automatically
# The iob_system blocks are handled by iob_system_utils.py, but
# the iob_system scripts do not have access to info in iob_soc.py,
# nor do they have permission to modify it (even if iob_system receives info about child module, it can't modify its dictionary).
"cbus_s": "uart0_cbus",
# Cbus connected automatically
"rs232_m": "rs232_m",
},
},
{
"core_name": "iob_timer",
"instance_name": "TIMER0",
"instance_description": "Timer peripheral",
"is_peripheral": True,
"parameters": {
"ADDR_W": "29", # TODO: Automate this with iob_system scripts
},
"peripheral_addr_w": 4,
"parameters": {},
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
# TODO: Cbus should be connected automatically
"cbus_s": "timer0_cbus",
# Cbus connected automatically
},
},
],
}

return attributes_dict
# Pass system_overrides dictionary via python parameter to the parent core (iob_system)
core_dict["parent"]["system_overrides"] = system_overrides

return core_dict
11 changes: 4 additions & 7 deletions lib/hardware/clocks_resets/iob_nco/iob_nco.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ def setup(py_params_dict):
"descr": "clock, clock enable and reset",
},
{
"name": "cbus_s",
"name": "iob_s",
"interface": {
"type": "iob",
"subtype": "slave",
"ADDR_W": "ADDR_W",
"ADDR_W": "4", # Same as `IOB_NCO_CSRS_ADDR_W
"DATA_W": "DATA_W",
},
"descr": "CPU native interface",
Expand Down Expand Up @@ -80,7 +80,7 @@ def setup(py_params_dict):
"interface": {
"type": "iob",
"wire_prefix": "csrs_",
"ADDR_W": "4",
"ADDR_W": "ADDR_W",
"DATA_W": "DATA_W",
},
},
Expand Down Expand Up @@ -311,10 +311,7 @@ def setup(py_params_dict):
],
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
"control_if_s": (
"cbus_s",
"iob_addr_i[4-1:0]",
),
"control_if_s": "iob_s",
"csrs_iob_o": "csrs_iob",
# Register interfaces
"softreset": "softreset",
Expand Down
6 changes: 3 additions & 3 deletions lib/hardware/iob_system/iob_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ def setup(py_params_dict):
"core_name": "iob_uart",
"instance_name": "UART0",
"instance_description": "UART peripheral",
"is_peripheral": True,
"peripheral_addr_w": 3,
"parameters": {},
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
Expand All @@ -438,14 +438,14 @@ def setup(py_params_dict):
"core_name": "iob_timer",
"instance_name": "TIMER0",
"instance_description": "Timer peripheral",
"is_peripheral": True,
"peripheral_addr_w": 4,
"parameters": {},
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
# Cbus connected automatically
},
},
# NOTE: Instantiate other peripherals here, using the 'is_peripheral' flag
# NOTE: Instantiate other peripherals here, using the 'peripheral_addr_w' flag
#
# Modules that need to be setup, but are not instantiated directly inside
# 'iob_system' Verilog module
Expand Down
71 changes: 58 additions & 13 deletions lib/hardware/iob_system/scripts/iob_system_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import sys

#
# Functions for iob_system.py
Expand Down Expand Up @@ -27,6 +28,7 @@ def iob_system_scripts(attributes_dict, params, py_params):
:param dict params: iob_system python parameters
:param dict py_params: iob_system argument python parameters
"""
handle_system_overrides(attributes_dict, py_params)
set_build_dir(attributes_dict, py_params)
peripherals = get_iob_system_peripherals_list(attributes_dict)
connect_peripherals_cbus(attributes_dict, peripherals, params)
Expand All @@ -39,6 +41,48 @@ def iob_system_scripts(attributes_dict, params, py_params):
#


def handle_system_overrides(attributes_dict, py_params):
"""Override/append attributes given in `system_overrides` python parameter (usually by child core).
:param dict attributes_dict: iob_system attributes
:param dict py_params: Dictionary containing `system_overrides` python parameter
"""
child_attributes = py_params.get("system_overrides")
if not child_attributes:
return

for child_attribute_name, child_value in child_attributes.items():
# Don't override child-specific attributes
if child_attribute_name in ["original_name", "setup_dir", "parent"]:
continue

# Override other attributes of type string
if type(child_value) is str:
attributes_dict[child_attribute_name] = child_value
continue

# Override or append elements from list attributes
assert (
type(child_value) is list
), f"Invalid type for attribute '{child_attribute_name}': {type(child_value)}"

# Select identifier attribute. Used to compare if should override each element.
identifier = "name"
if child_attribute_name in ["blocks", "sw_modules"]:
identifier = "instance_name"

# Process each object from list
for child_obj in child_value:
# Find object and override it
for idx, obj in enumerate(attributes_dict[child_attribute_name]):
if obj[identifier] == child_obj[identifier]:
# print(f"DEBUG: Overriding {child_obj[identifier]}", file=sys.stderr)
attributes_dict[child_attribute_name][idx] = child_obj
break
else:
# Didn't override, so append it to list
attributes_dict[child_attribute_name].append(child_obj)


def set_build_dir(attributes_dict, py_params):
"""If build_dir not given in py_params, set a default one.
:param dict attributes_dict: iob_system attributes
Expand All @@ -52,14 +96,14 @@ def set_build_dir(attributes_dict, py_params):


def get_iob_system_peripherals_list(attributes_dict):
"""Parses blocks list in iob_system attributes, for blocks with the `is_peripheral` attribute set to True.
Also removes `is_peripheral` attribute from each block after adding it to the peripherals list.
"""Parses blocks list in iob_system attributes, for blocks with the `peripheral_addr_w` attribute set.
Also removes `peripheral_addr_w` attribute from each block after adding it to the peripherals list.
"""
peripherals = []
for block in attributes_dict["blocks"]:
if "is_peripheral" in block and block["is_peripheral"]:
peripherals.append(block)
block.pop("is_peripheral")
if "peripheral_addr_w" in block and block["peripheral_addr_w"]:
peripherals.append({"ref": block, "addr_w": block["peripheral_addr_w"]})
block.pop("peripheral_addr_w")
return peripherals


Expand All @@ -83,7 +127,7 @@ def connect_peripherals_cbus(attributes_dict, peripherals, params):
pbus_split["num_outputs"] = num_peripherals

for idx, peripheral in enumerate(peripherals):
peripheral_name = peripheral["instance_name"].lower()
peripheral_name = peripheral["ref"]["instance_name"].lower()
# Add peripheral cbus wire
attributes_dict["wires"].append(
{
Expand All @@ -99,9 +143,10 @@ def connect_peripherals_cbus(attributes_dict, peripherals, params):
# Connect cbus to pbus_split
pbus_split["connect"][f"output_{idx}_m"] = f"{peripheral_name}_cbus"
# Connect cbus to peripheral
peripheral["connect"]["cbus_s"] = f"{peripheral_name}_cbus"
# Set address width parameter
peripheral["parameters"]["ADDR_W"] = peripheral_addr_w
peripheral["ref"]["connect"]["cbus_s"] = (
f"{peripheral_name}_cbus",
f"{peripheral_name}_cbus_iob_addr[{peripheral['addr_w']}-1:0]",
)

# Add CLINT and PLIC wires (they are not in peripherals list)
attributes_dict["wires"] += [
Expand Down Expand Up @@ -148,8 +193,8 @@ def generate_peripheral_base_addresses(

# Include CLINT and PLIC in peripherals list
complete_peripherals_list = peripherals_list + [
{"instance_name": "CLINT0"},
{"instance_name": "PLIC0"},
{"ref": {"instance_name": "CLINT0"}},
{"ref": {"instance_name": "PLIC0"}},
]
n_slaves_w = (len(complete_peripherals_list) - 1).bit_length()

Expand All @@ -160,7 +205,7 @@ def generate_peripheral_base_addresses(
os.makedirs(os.path.dirname(out_file), exist_ok=True)
with open(out_file, "w") as f:
for idx, instance in enumerate(complete_peripherals_list):
instance_name = instance["instance_name"]
instance_name = instance["ref"]["instance_name"]
f.write(
f"#define {instance_name}_BASE (PBUS_BASE + ({idx}<<(P_BIT-{n_slaves_w})))\n"
)
Expand Down Expand Up @@ -189,7 +234,7 @@ def generate_makefile_segments(attributes_dict, peripherals, params, py_params):
# Create a list with every peripheral name, except clint, and plic
file.write(
"PERIPHERALS ?="
+ " ".join(peripheral["core_name"] for peripheral in peripherals)
+ " ".join(peripheral["ref"]["core_name"] for peripheral in peripherals)
+ "\n",
)
if params["use_ethernet"]:
Expand Down
9 changes: 3 additions & 6 deletions lib/hardware/iob_timer/iob_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def setup(py_params_dict):
"interface": {
"type": "iob",
"subtype": "slave",
"ADDR_W": "ADDR_W",
"ADDR_W": "4", # Same as `IOB_TIMER_CSRS_ADDR_W
"DATA_W": "DATA_W",
},
"descr": "CPU native interface",
Expand All @@ -56,7 +56,7 @@ def setup(py_params_dict):
"interface": {
"type": "iob",
"wire_prefix": "csrs_",
"ADDR_W": "4",
"ADDR_W": "ADDR_W",
"DATA_W": "DATA_W",
},
},
Expand Down Expand Up @@ -177,10 +177,7 @@ def setup(py_params_dict):
"csr_if": "iob",
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
"control_if_s": (
"cbus_s",
"iob_addr_i[4-1:0]",
),
"control_if_s": "cbus_s",
"csrs_iob_o": "csrs_iob",
# Register interfaces
"reset": "reset",
Expand Down
17 changes: 3 additions & 14 deletions lib/hardware/iob_uart/iob_uart.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
def setup(py_params_dict):
CSR_IF = py_params_dict["csr_if"] if "csr_if" in py_params_dict else "iob"
NAME = py_params_dict["name"] if "name" in py_params_dict else "iob_uart"

if CSR_IF == "iob":
cbus_widths = ["iob_addr_i[3-1:0]"]
elif CSR_IF == "axi":
cbus_widths = [
"axi_araddr_i[3-1:0]",
"axi_awaddr_i[3-1:0]",
]
else:
cbus_widths = []

attributes_dict = {
"original_name": "iob_uart",
"name": NAME,
Expand Down Expand Up @@ -57,7 +46,7 @@ def setup(py_params_dict):
"interface": {
"type": CSR_IF,
"subtype": "slave",
"ADDR_W": "ADDR_W",
"ADDR_W": "3", # Same as `IOB_UART_CSRS_ADDR_W
"DATA_W": "DATA_W",
},
"descr": "CPU native interface",
Expand All @@ -77,7 +66,7 @@ def setup(py_params_dict):
"interface": {
"type": "iob",
"wire_prefix": "csrs_",
"ADDR_W": "3",
"ADDR_W": "ADDR_W",
"DATA_W": "DATA_W",
},
},
Expand Down Expand Up @@ -283,7 +272,7 @@ def setup(py_params_dict):
"csr_if": CSR_IF,
"connect": {
"clk_en_rst_s": "clk_en_rst_s",
"control_if_s": ("cbus_s", *cbus_widths),
"control_if_s": "cbus_s",
"csrs_iob_o": "csrs_iob",
# Register interfaces
"softreset": "softreset",
Expand Down
4 changes: 2 additions & 2 deletions lib/scripts/default.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{ pkgs ? import <nixpkgs> {} }:

let
py2hwsw_commit = "8abbad6b93b9cfcca4fb97bdd4d09cadf8cadbe2"; # Replace with the desired commit.
py2hwsw_sha256 = "NIxU15GH3YtFYeYW1bfZJgobEs0Bk25yU7pNiXnE/IA="; # Replace with the actual SHA256 hash.
py2hwsw_commit = "db8edfe33d2790cd7d779ec9537187b1edbad5d6"; # Replace with the desired commit.
py2hwsw_sha256 = "Y4J8l5U2SCjrx692L9UXuB3VVOlXwE1tV7j7XbU/TCo="; # Replace with the actual SHA256 hash.

py2hwsw = pkgs.python3.pkgs.buildPythonPackage rec {
pname = "py2hwsw";
Expand Down