adjust some ergonomics found while playtesting
This commit is contained in:
parent
ab0909d06b
commit
b8de6339aa
|
|
@ -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));
|
||||
|
||||
*/
|
||||
```
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from amaranth import *
|
||||
from warnings import warn
|
||||
from .utils import *
|
||||
from math import ceil
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
""" """
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from amaranth import *
|
||||
from warnings import warn
|
||||
from .utils import *
|
||||
from math import ceil
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from amaranth import *
|
||||
from warnings import warn
|
||||
from ..utils import *
|
||||
from .receiver import UARTReceiver
|
||||
from .receive_bridge import ReceiveBridge
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue