manta: fix code generation from config file, update tests
This commit is contained in:
parent
3ba93efd2f
commit
8f45546b5a
|
|
@ -1,16 +1,16 @@
|
|||
from manta import Manta
|
||||
from manta import *
|
||||
from time import sleep
|
||||
|
||||
manta = Manta("manta.yaml")
|
||||
manta = Manta.from_config("manta.yaml")
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
# Turn each LED off
|
||||
for j in range(5):
|
||||
manta.my_io_core.set_probe(f"LED{j}", 0)
|
||||
manta.cores.my_io_core.set_probe(f"LED{j}", 0)
|
||||
|
||||
# Turn one LED back on
|
||||
manta.my_io_core.set_probe(f"LED{i}", 1)
|
||||
manta.cores.my_io_core.set_probe(f"LED{i}", 1)
|
||||
|
||||
i = (i + 1) % 5
|
||||
sleep(0.1)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from manta import Manta
|
||||
from manta import *
|
||||
|
||||
m = Manta("manta.yaml")
|
||||
manta = Manta.from_config("manta.yaml")
|
||||
|
||||
print(m.my_io_core.get_probe("sw"))
|
||||
m.my_io_core.set_probe("led", 4)
|
||||
print(manta.cores.my_io_core.get_probe("sw"))
|
||||
manta.cores.my_io_core.set_probe("led", 4)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from manta import Manta
|
||||
from manta import *
|
||||
|
||||
m = Manta("manta.yaml")
|
||||
manta = Manta.from_config("manta.yaml")
|
||||
|
||||
# Memory addresses can be written to in Python, and then be read out by
|
||||
# flipping the switches on the FPGA, and watching the LEDs update!
|
||||
|
||||
m.my_memory.write(0, 1)
|
||||
manta.cores.my_memory.write(0, 1)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
from manta import Manta
|
||||
from manta import *
|
||||
from time import sleep
|
||||
from random import randint
|
||||
|
||||
m = Manta("manta.yaml")
|
||||
manta = Manta.from_config("manta.yaml")
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
i = (i + 1) % 16
|
||||
m.my_io_core.set_probe("led", 2**i)
|
||||
manta.cores.my_io_core.set_probe("led", 2**i)
|
||||
|
||||
m.my_io_core.set_probe("led16_r", randint(0, 1))
|
||||
m.my_io_core.set_probe("led16_g", randint(0, 1))
|
||||
m.my_io_core.set_probe("led16_b", randint(0, 1))
|
||||
manta.cores.my_io_core.set_probe("led16_r", randint(0, 1))
|
||||
manta.cores.my_io_core.set_probe("led16_g", randint(0, 1))
|
||||
manta.cores.my_io_core.set_probe("led16_b", randint(0, 1))
|
||||
|
||||
print(f'Switches: {m.my_io_core.get_probe("sw")}')
|
||||
print(f'Switches: {manta.cores.my_io_core.get_probe("sw")}')
|
||||
print(f"Buttons:")
|
||||
print(f'btnu: {m.my_io_core.get_probe("btnu")}')
|
||||
print(f'btnd: {m.my_io_core.get_probe("btnd")}')
|
||||
print(f'btnr: {m.my_io_core.get_probe("btnr")}')
|
||||
print(f'btnl: {m.my_io_core.get_probe("btnl")}')
|
||||
print(f'btnc: {m.my_io_core.get_probe("btnc")}')
|
||||
print(f'btnu: {manta.cores.my_io_core.get_probe("btnu")}')
|
||||
print(f'btnd: {manta.cores.my_io_core.get_probe("btnd")}')
|
||||
print(f'btnr: {manta.cores.my_io_core.get_probe("btnr")}')
|
||||
print(f'btnl: {manta.cores.my_io_core.get_probe("btnl")}')
|
||||
print(f'btnc: {manta.cores.my_io_core.get_probe("btnc")}')
|
||||
print("")
|
||||
|
||||
sleep(0.1)
|
||||
|
|
|
|||
|
|
@ -69,13 +69,13 @@ def wrong_args():
|
|||
|
||||
|
||||
def gen(config_path, output_path):
|
||||
m = Manta(config_path)
|
||||
m.generate_verilog(output_path)
|
||||
manta = Manta.from_config(config_path)
|
||||
manta.generate_verilog(output_path)
|
||||
|
||||
|
||||
def inst(config_path):
|
||||
m = Manta(config_path)
|
||||
ports = m.get_top_level_ports()
|
||||
manta = Manta.from_config(config_path)
|
||||
ports = manta.get_top_level_ports()
|
||||
hdl = ",\n ".join([f".{p.name}({p.name})" for p in ports])
|
||||
|
||||
foo = """
|
||||
|
|
@ -88,8 +88,8 @@ manta manta_inst(
|
|||
|
||||
|
||||
def capture(config_path, logic_analyzer_name, export_paths):
|
||||
m = Manta(config_path)
|
||||
la = getattr(m, logic_analyzer_name)
|
||||
manta = Manta.from_config(config_path)
|
||||
la = getattr(manta.cores, logic_analyzer_name)
|
||||
cap = la.capture()
|
||||
|
||||
for path in export_paths:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class EthernetInterface(Elaboratable):
|
|||
self._host_ip_addr = host_ip_addr
|
||||
self._udp_port = udp_port
|
||||
self._phy = phy
|
||||
self._clk_freq = clk_freq
|
||||
self._clk_freq = float(clk_freq)
|
||||
self._additional_config = kwargs
|
||||
self._check_config()
|
||||
|
||||
|
|
@ -81,6 +81,10 @@ class EthernetInterface(Elaboratable):
|
|||
if not 0 <= int(byte) <= 255:
|
||||
raise ValueError(f"Invalid byte in FPGA IP: {byte}")
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config):
|
||||
return EthernetInterface(**config)
|
||||
|
||||
def to_config(self):
|
||||
config = {
|
||||
"fpga_ip_addr": self._fpga_ip_addr,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class IOCore(MantaCore):
|
|||
return self._max_addr
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config, base_addr, interface):
|
||||
def from_config(cls, config):
|
||||
inputs = config.get("inputs", {})
|
||||
outputs = config.get("outputs", {})
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ class IOCore(MantaCore):
|
|||
|
||||
output_signals += [Signal(width, name=name, init=initial_value)]
|
||||
|
||||
return cls(base_addr, interface, inputs=input_signals, outputs=output_signals)
|
||||
return cls(inputs=input_signals, outputs=output_signals)
|
||||
|
||||
def to_config(self):
|
||||
config = {}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ from manta.io_core import IOCore
|
|||
from manta.memory_core import MemoryCore
|
||||
from manta.logic_analyzer import LogicAnalyzerCore
|
||||
from manta.utils import *
|
||||
import yaml
|
||||
import json
|
||||
|
||||
|
||||
class Manta(Elaboratable):
|
||||
|
|
@ -25,117 +27,61 @@ class Manta(Elaboratable):
|
|||
for core in self.cores._cores.values():
|
||||
core.interface = value
|
||||
|
||||
# def __init__(self, config):
|
||||
# # Load config from either a configuration file or a dictionary.
|
||||
# # Users primarily use the config file, but the dictionary is
|
||||
# # included for internal tests.
|
||||
@classmethod
|
||||
def from_config(cls, config_path):
|
||||
|
||||
# if isinstance(config, str):
|
||||
# self._config = self._read_config_file(config)
|
||||
# Load config from either YAML or JSON
|
||||
extension = config_path.split(".")[-1]
|
||||
if extension not in ["yaml", "yml", "json"]:
|
||||
raise ValueError(f"Configuration file {config_path} has unrecognized file type.")
|
||||
|
||||
# if isinstance(config, dict):
|
||||
# self._config = config
|
||||
with open(config_path, "r") as f:
|
||||
if extension in ["yaml", "yml"]:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# self._check_config()
|
||||
elif extension in ["json"]:
|
||||
config = json.load(f)
|
||||
|
||||
# self._get_interface()
|
||||
# self._get_cores()
|
||||
# self._add_friendly_core_names()
|
||||
# Validate config
|
||||
if "cores" not in config:
|
||||
raise ValueError("No cores specified in configuration file.")
|
||||
|
||||
# def _read_config_file(self, path):
|
||||
# """
|
||||
# Takes a path to configuration file, and return the configuration as a
|
||||
# python dictionary.
|
||||
# """
|
||||
if not len(config["cores"]) > 0:
|
||||
raise ValueError("Must specify at least one core.")
|
||||
|
||||
# extension = path.split(".")[-1]
|
||||
for name, attrs in config["cores"].items():
|
||||
# Make sure core type is specified
|
||||
if "type" not in attrs:
|
||||
raise ValueError(f"No type specified for core {name}.")
|
||||
|
||||
# if "json" in extension:
|
||||
# import json
|
||||
# with open(path, "r") as f:
|
||||
# return json.load(f)
|
||||
if attrs["type"] not in ["logic_analyzer", "io", "memory"]:
|
||||
raise ValueError(f"Unrecognized core type specified for {name}.")
|
||||
|
||||
# elif "yaml" in extension or "yml" in extension:
|
||||
# import yaml
|
||||
# with open(path, "r") as f:
|
||||
# return yaml.safe_load(f)
|
||||
# Make Manta object, and configure it
|
||||
manta = Manta()
|
||||
|
||||
# else:
|
||||
# raise ValueError("Unable to recognize configuration file extension.")
|
||||
# Add interface
|
||||
if "uart" in config:
|
||||
manta.interface = UARTInterface.from_config(config["uart"])
|
||||
|
||||
# def _check_config(self):
|
||||
# if "cores" not in self._config:
|
||||
# raise ValueError("No cores specified in configuration file.")
|
||||
elif "ethernet" in config:
|
||||
manta.interface = EthernetInterface.from_config(config["ethernet"])
|
||||
|
||||
# if not len(self._config["cores"]) > 0:
|
||||
# raise ValueError("Must specify at least one core.")
|
||||
# Add cores
|
||||
for name, attrs in config["cores"].items():
|
||||
if attrs["type"] == "io":
|
||||
core = IOCore.from_config(attrs)
|
||||
|
||||
# for name, attrs in self._config["cores"].items():
|
||||
# # Make sure core type is specified
|
||||
# if "type" not in attrs:
|
||||
# raise ValueError(f"No type specified for core {name}.")
|
||||
elif attrs["type"] == "logic_analyzer":
|
||||
core = LogicAnalyzerCore.from_config(attrs)
|
||||
|
||||
# if attrs["type"] not in ["logic_analyzer", "io", "memory"]:
|
||||
# raise ValueError(f"Unrecognized core type specified for {name}.")
|
||||
elif attrs["type"] == "memory":
|
||||
core = MemoryCore.from_config(attrs)
|
||||
|
||||
# def _get_interface(self):
|
||||
# """
|
||||
# Returns an instance of an interface object (UARTInterface or
|
||||
# EthernetInterface) configured with the parameters in the
|
||||
# config file.
|
||||
# """
|
||||
# if "uart" in self._config:
|
||||
# self.interface = UARTInterface.from_config(self._config["uart"])
|
||||
setattr(manta.cores, name, core)
|
||||
|
||||
# elif "ethernet" in self._config:
|
||||
# self.interface = EthernetInterface(self._config["ethernet"])
|
||||
return manta
|
||||
|
||||
# else:
|
||||
# raise ValueError("No recognized interface specified.")
|
||||
|
||||
# def _get_cores(self):
|
||||
# """
|
||||
# Creates instances of the cores (IOCore, LogicAnalyzerCore, MemoryCore)
|
||||
# specified in the user's configuration, and returns them as a list.
|
||||
# """
|
||||
|
||||
# self._cores = {}
|
||||
# base_addr = 0
|
||||
# for name, attrs in self._config["cores"].items():
|
||||
# if attrs["type"] == "io":
|
||||
# core = IOCore.from_config(attrs, base_addr, self.interface)
|
||||
|
||||
# elif attrs["type"] == "logic_analyzer":
|
||||
# core = LogicAnalyzerCore(attrs, base_addr, self.interface)
|
||||
|
||||
# elif attrs["type"] == "memory":
|
||||
# core = MemoryCore.from_config(attrs, base_addr, self.interface)
|
||||
|
||||
# # Make sure we're not out of address space
|
||||
# if core.max_addr > (2**16) - 1:
|
||||
# raise ValueError(
|
||||
# f"Ran out of address space to allocate to core {name}."
|
||||
# )
|
||||
|
||||
# # Make the next core's base address start one address after the previous one's
|
||||
# base_addr = core.max_addr + 1
|
||||
# self._cores[name] = core
|
||||
|
||||
# def _add_friendly_core_names(self):
|
||||
# """
|
||||
# Add cores to the instance under a friendly name - ie, a core named `my_core` belonging
|
||||
# to a Manta instance `m` could be obtained with `m.cores["my_core"]`, but this allows
|
||||
# it to be obtained with `m.my_core`. Which is way nicer.
|
||||
# """
|
||||
|
||||
# for name, instance in self._cores.items():
|
||||
# if not hasattr(self, name):
|
||||
# setattr(self, name, instance)
|
||||
|
||||
# else:
|
||||
# raise ValueError(
|
||||
# "Cannot add object to Manta instance - name is already taken!"
|
||||
# )
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class MemoryCore(MantaCore):
|
|||
}
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config, base_addr, interface):
|
||||
def from_config(cls, config):
|
||||
# Check for unrecognized options
|
||||
valid_options = ["type", "depth", "width", "mode"]
|
||||
for option in config:
|
||||
|
|
@ -125,7 +125,7 @@ class MemoryCore(MantaCore):
|
|||
if mode not in ["fpga_to_host", "host_to_fpga", "bidirectional"]:
|
||||
raise ValueError("Unrecognized mode provided to memory core.")
|
||||
|
||||
return cls(mode, width, depth, base_addr, interface)
|
||||
return cls(mode, width, depth)
|
||||
|
||||
def _tie_mems_to_bus(self, m):
|
||||
for i, mem in enumerate(self._mems):
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ class CoreContainer:
|
|||
self._cores[name] = value
|
||||
value.interface = self._manta.interface
|
||||
value.base_addr = self._last_used_addr
|
||||
|
||||
if value.max_addr > (2**16)-1:
|
||||
raise ValueError(f"Ran out of address space while allocating core.")
|
||||
|
||||
self._last_used_addr = value.max_addr + 1
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue