Skip to content

Commit

Permalink
adjust some ergonomics found while playtesting
Browse files Browse the repository at this point in the history
  • Loading branch information
fischermoseley committed Jan 21, 2024
1 parent ab0909d commit b8de633
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 42 deletions.
21 changes: 3 additions & 18 deletions doc/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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));
*/
```
2 changes: 1 addition & 1 deletion doc/logic_analyzer_core.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
39 changes: 27 additions & 12 deletions src/manta/cli.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -37,6 +37,10 @@
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).
Expand All @@ -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):
Expand All @@ -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:
Expand Down Expand Up @@ -129,20 +148,16 @@ def main():
wrong_args()
gen(argv[2], argv[3])

elif argv[1] == "capture":
if len(argv) < 5:
elif argv[1] == "inst":
if len(argv) != 3:
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])
inst(argv[2])

elif argv[1] == "mmap":
if len(argv) != 3:
elif argv[1] == "capture":
if len(argv) < 5:
wrong_args()
mmap(argv[2])
capture(argv[2], argv[3], argv[4:])

elif argv[1] == "ports":
ports()
Expand Down
1 change: 0 additions & 1 deletion src/manta/io_core.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .utils import *
from math import ceil

Expand Down
17 changes: 13 additions & 4 deletions src/manta/logic_analyzer/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -306,7 +305,11 @@ def get_trigger_location(self):
----------
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.
Expand Down Expand Up @@ -373,7 +376,10 @@ def export_vcd(self, path):
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
Expand All @@ -382,7 +388,10 @@ def export_vcd(self, path):
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)

Expand Down
3 changes: 1 addition & 2 deletions src/manta/manta.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .uart import UARTInterface

# from .ethernet import EthernetInterface
Expand Down Expand Up @@ -70,7 +69,7 @@ def get_interface(self):
return EthernetInterface(self.config["ethernet"])

else:
raise ValueError("Unrecognized interface specified.")
raise ValueError("No recognized interface specified.")

def get_cores(self):
""" """
Expand Down
1 change: 0 additions & 1 deletion src/manta/memory_core.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from .utils import *
from math import ceil

Expand Down
1 change: 0 additions & 1 deletion src/manta/uart/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from amaranth import *
from warnings import warn
from ..utils import *
from .receiver import UARTReceiver
from .receive_bridge import ReceiveBridge
Expand Down
16 changes: 14 additions & 2 deletions src/manta/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@


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
Expand Down

0 comments on commit b8de633

Please sign in to comment.