adjust some ergonomics found while playtesting

This commit is contained in:
Fischer Moseley 2024-01-21 00:23:07 -08:00
parent ab0909d06b
commit b8de6339aa
9 changed files with 60 additions and 43 deletions

View File

@ -58,34 +58,19 @@ This Manta instance has an IO Core and a Logic Analyzer, each containing a numbe
## Example Instantiation
The Verilog file generated by `manta gen` contains some information at the top of the file. This includes an example instantiation for the `manta` module that's been configured, which you can copy paste into your source code. Here's what that looks like for the configuration above:
```c
/*
This module was generated with Manta v0.0.5 on 11 Sep 2023 at 17:52:28 by fischerm
If this breaks or if you've got spicy formal verification memes, contact fischerm [at] mit.edu
Provided under a GNU GPLv3 license. Go wild.
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
this into your source!
Lastly, we Manta can automatically generate a copy-pasteable Verilog snippet to instantiate Manta in your design. This is done by running `manta inst` with the path to the configuration file describing the Manta core you'd like to instantiate. For example, the following snippet is generated for the configuration above:
```verilog
manta manta_inst (
.clk(clk),
.rst(rst)
.rx(rx),
.tx(tx),
.probe_0_in(probe_0_in),
.probe_1_in(probe_1_in),
.probe_2_out(probe_2_out),
.probe_3_out(probe_3_out),
.larry(larry),
.curly(curly),
.moe(moe));
*/
```

View File

@ -116,7 +116,7 @@ If the file `manta.yaml` contained the configuration above, then running:
manta capture manta.yaml my_logic_analyzer capture.v
```
Generates a Verilog module at `capture.v` which can then be instantiated in the testbench or FPGA design in which it is needed. An example instantiation is provided at the top of the output verilog, so a simple copy-paste into the testbench is all that's necessary to use the module.
Generates a Verilog module at `capture.v` which can then be instantiated in the testbench or FPGA design in which it is needed.
This is useful for two situations in particular:

View File

@ -1,5 +1,5 @@
from .manta import Manta
from warnings import warn
from .utils import *
from sys import argv
from pkg_resources import get_distribution
@ -37,6 +37,10 @@ Usage:
Generate a verilog file specifying the Manta module from a given
configuration file, and save to the provided path.
inst [config_file]
Generate a copy-pasteable Verilog snippet to instantiate Manta
in your design.
capture [config_file] [la_core_name] [vcd_file] [verilog_file]
Start a capture on the specified core, and save the results to a .vcd
or .v file at the provided path(s).
@ -61,6 +65,7 @@ def version():
def wrong_args():
print('Wrong number of arguments, run "manta help" for usage.')
exit(1)
def gen(config_path, output_path):
@ -79,9 +84,23 @@ def gen(config_path, output_path):
)
def inst(config_path):
m = Manta(config_path)
ports = m.get_top_level_ports()
hdl = ",\n ".join([f".{p.name}({p.name})" for p in ports])
foo = """
manta manta_inst(
.clk(clk),
.rst(rst),
"""
print(foo + hdl + ");\n")
def capture(config_path, logic_analyzer_name, export_paths):
m = Manta(config_path)
la = getattr(s, logic_analyzer_name)
la = getattr(m, logic_analyzer_name)
cap = la.capture()
for path in export_paths:
@ -129,20 +148,16 @@ def main():
wrong_args()
gen(argv[2], argv[3])
elif argv[1] == "inst":
if len(argv) != 3:
wrong_args()
inst(argv[2])
elif argv[1] == "capture":
if len(argv) < 5:
wrong_args()
capture(argv[2], argv[3], argv[4])
elif argv[1] == "playback":
if len(argv) != 5:
wrong_args()
playback(argv[2], argv[3], argv[4])
elif argv[1] == "mmap":
if len(argv) != 3:
wrong_args()
mmap(argv[2])
capture(argv[2], argv[3], argv[4:])
elif argv[1] == "ports":
ports()

View File

@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .utils import *
from math import ceil

View File

@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from ..utils import *
from .trigger_block import LogicAnalyzerTriggerBlock
from .fsm import LogicAnalyzerFSM, States, TriggerModes
@ -306,7 +305,11 @@ class LogicAnalyzerCapture:
----------
The trigger location as an `int`.
"""
return self.config["trigger_location"]
if "trigger_location" in self.config:
return self.config["trigger_location"]
else:
return self.config["sample_depth"] // 2
def get_trace(self, probe_name):
"""Gets the value of a single probe over the capture.
@ -373,7 +376,10 @@ class LogicAnalyzerCapture:
clock = writer.register_var("manta", "clk", "wire", size=1)
# include a trigger signal such would be meaningful (ie, we didn't trigger immediately)
if self.config["trigger_mode"] != "immediate":
if (
"trigger_mode" not in self.config
or self.config["trigger_mode"] == "single_shot"
):
trigger = writer.register_var("manta", "trigger", "wire", size=1)
# add the data to each probe in the vcd file
@ -382,7 +388,10 @@ class LogicAnalyzerCapture:
writer.change(clock, timestamp, timestamp % 2 == 0)
# set the trigger (if there is one)
if self.config["trigger_mode"] != "immediate":
if (
"trigger_mode" not in self.config
or self.config["trigger_mode"] == "single_shot"
):
triggered = (timestamp // 2) >= self.get_trigger_location()
writer.change(trigger, timestamp, triggered)

View File

@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .uart import UARTInterface
# from .ethernet import EthernetInterface
@ -70,7 +69,7 @@ class Manta(Elaboratable):
return EthernetInterface(self.config["ethernet"])
else:
raise ValueError("Unrecognized interface specified.")
raise ValueError("No recognized interface specified.")
def get_cores(self):
""" """

View File

@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .utils import *
from math import ceil

View File

@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from ..utils import *
from .receiver import UARTReceiver
from .receive_bridge import ReceiveBridge

View File

@ -5,13 +5,25 @@ import os
class InternalBus(data.StructLayout):
"""Describes the layout of Manta's internal bus, such that signals of
the appropriate dimension can be instantiated with Signal(InternalBus())."""
"""
Describes the layout of Manta's internal bus, such that signals of
the appropriate dimension can be instantiated with Signal(InternalBus()).
"""
def __init__(self):
super().__init__({"addr": 16, "data": 16, "rw": 1, "valid": 1})
def warn(message):
"""
Prints a warning to the user's terminal. Originally the warn() method
from the builtin warnings module was used for this, but I don't think the
way it outputs on the command line is the most helpful for the users.
(They don't care about the stacktrace or the filename/line number, for example.)
"""
print("Warning: " + message)
def words_to_value(data):
"""
Takes a list of integers, interprets them as 16-bit integers, and