Torii v0.X to v1.0 Migration Guide¶
Todo
This document is a work in progress and should be updated as the progression v1.0 progresses
General¶
HDL Constructs Imported From Root torii
Namespace¶
The Previous versions of Torii let you do a general glob import of all of the core HDL constructs (Signal
et. al.) from the root torii
module namespace.
These must now be imported from the torii.hdl
module namespace, and while glob imports are discouraged, they will still work as intended previously.
# OLD (<1.0.0)
from torii import *
# NEW (>=1.0.0)
from torii.hdl import *
Importing YosysError
from torii.back.cxxrtl
and torii.back.verilog
¶
The ability to directly import YosysError
from the torii.back.cxxrtl
and torii.back.verilog
modules has been removed, as it made little sense logically.
It must now be directly imported from torii.tools.yosys
itself.
# OLD (<1.0.0)
from torii.back.cxxrtl import YosysError
# -- OR --
from torii.back.verilog import YosysError
# NEW (>=1.0.0)
from torii.tools.yosys import YosysError
DIR_FANIN
/DIR_FANOUT
/DIR_NONE
from torii.hdl.rec
¶
The DIR_FANIN
, DIR_FANOUT
, and DIR_NONE
constant aliases have been removed in favor of using the Direction
enumeration directly.
# OLD (<1.0.0)
from torii.hdl.rec import DIR_FANIN, DIR_FANOUT, DIR_NONE
rec = Record([
('a', 1, DIR_FANIN),
('b', 1, DIR_FANOUT),
('c', 1, DIR_NONE),
])
# NEW (>=1.0.0)
from torii.hdl.rec import Direction
rec = Record([
('a', 1, Direction.FANIN),
('b', 1, Direction.FANOUT),
('c', 1, Direction.NONE),
])
While it is a touch more wordy, we feel it give more context and is generally more descriptive.
build_cxx
from torii.tools.cxx
¶
The build_cxx
function from torii.tools.cxx
has been removed in favor of the compile_cxx
, which offers more control and capabilities.
# OLD (<1.0.0)
from torii.tools.cxx import build_cxx
build_dir, output_file = build_cxx(
cxx_sources = {
'foo.cc': '/* Source Code for foo */'
},
output_name = 'foo',
include_dirs = [],
macros = []
)
# NEW (>=1.0.0)
from torii.tools.cxx import compile_cxx
output_file = compile_cxx(
'foo',
build_dir,
None,
source_listings = {
'foo.cc': '/* Source for foo */'
}
)
For more information see the full documentation on compile_cxx
for all of it’s capabilities and examples of more advanced usage.
The equivalent functionality can be maintained with a little bit of scaffolding:
def build_cxx(
cxx_sources: dict[str, str], output_name: str, include_dirs: list[str], macros: list[str]
) -> tuple[TemporaryDirectory[str], str]:
build_dir = TemporaryDirectory(prefix = 'torii_cxx_')
output_dir = Path(build_dir.name)
output_file = compile_cxx(
output_name, output_dir, None, include_paths = include_dirs, defines = {
k: v for (k, v) in (macro.strip().split('=', 2) for macro in macros)
},
source_listings = cxx_sources
)
return (build_dir, output_file.name)
@extend
from torii.util.decorators
¶
The @extend
decorator from the torii.util.decorators
module has been removed outright. There is no replacement for this as it involved injecting things into other classes which breaks the type system and in general was a bad idea.
@memoize
from torii.util.decorators
¶
The @memoize
decorator from torii.util.decorators
has been removed and should be replaced with functools.cache
.
Library Changes¶
torii.lib.soc.memory
¶
The contents of the torii.lib.soc.memory
module have been moved to torii.lib.mem
, as they are generally useful for non-SoC designs as well as SoC designs.
More specifically the MemoryMap
, ResourceInfo
, and _RangeMap
have been moved to torii.lib.mem.map
.
# OLD (<1.0.0)
from torii.lib.soc.memory import MemoryMap, ResourceInfo
# NEW (>=1.0.0)
from torii.lib.mem.map import MemoryMap, ResourceInfo
torii.lib.soc.wishbone
¶
The wishbone
module has been removed from torii.lib.soc
and moved to torii.lib.bus.wishbone
, as it is generally useful for non-SoC designs as well as SoC designs, and is not the only bus type supported.
# OLD (<1.0.0)
from torii.lib.soc.wishbone import Arbiter, Interface, ...
# -- OR --
from torii.lib.soc.wishbone.bus import Arbiter, Interface, ...
# NEW (>=1.0.0)
from torii.lib.bus.wishbone import Arbiter, Interface, ...
Module Changes¶
DomainRenamer
from torii.hdl.xfrm
¶
In past versions of Torii, you could use the DomainRenamer
in two ways, the first was to pass a single string into it, which would be used to re-map the sync
domain in the wrapped elaboratables to that domain, or pass a dictionary literally to map one or more domains.
These have been replaced with using kwargs
to more directly display the intent of the renamer over passing a single string, and also to clean up visual noise when passing a dictionary.
from torii.hdl import DomainRenamer
# OLD (<1.0.0)
a = DomainRenamer('meow')(elab)
# -- OR --
a = DomainRenamer({'sync': 'meow'})(elab)
# NEW (>=1.0.0)
a = DomainRenamer(sync = 'meow')(elab)
If you need to pass a dictionary that is built at runtime to the domain renamer, then you can simply un-pack the dictionary into the constructor like so:
from torii.hdl import DomainRenamer
domain_map = {
'sync': 'meow',
# ...
}
# OLD (<1.0.0)
a = DomainRenamer(domain_map)(elab)
# NEW (>=1.0.0)
a = DomainRenamer(**domain_map)(elab)
StreamInterface
from torii.lib.stream.simple
¶
The StreamInterface
from torii.lib.stream.simple
has had the connect
method removed in favor of the attach
method. In addition the payload
signal has been removed in favor of the data
signal.
from torii.lib.stream.simple import StreamInterface
foo = Signal(8)
stream_a = StreamInterface()
stream_b = StreamInterface()
# OLD (<1.0.0)
stream_a.connect(stream_b)
# ...
m.d.comb += [
foo.eq(stream_a.payload),
]
# NEW (>=1.0.0)
stream_a.attach(stream_a)
# ...
m.d.comb += [
foo.eq(stream_a.data),
]
AsyncSerialRX
from torii.lib.stdio.serial
¶
The AsyncSerialRX
from torii.lib.stdio.serial
has had the rdy
and ack
signals removed in favor of the done
and start
signals respectively.
This was done to match them more logically to what they actually do in order to avoid common pitfalls and confusion when using the module.
from torii.lib.stdio.serial import AsyncSerialRX
uart_rx = AsyncSerialRX(...)
# OLD (<1.0.0)
with m.FSM(name = 'rx') as fsm:
m.d.comb += [ uart_rx.ack.eq(fsm.ongoing('IDLE')), ]
with m.State('IDLE'):
with m.If(uart_rx.rdy):
m.d.sync += [ data_rx.eq(uart_rx.data), ]
m.next = 'CMD'
# NEW (>=1.0.0)
with m.FSM(name = 'rx') as fsm:
m.d.comb += [ uart_rx.start.eq(fsm.ongoing('IDLE')), ]
with m.State('IDLE'):
with m.If(uart_rx.done):
m.d.sync += [ data_rx.eq(uart_rx.data), ]
m.next = 'CMD'