Expands SystemVerilog source strings into RTL source files.
This module writes in-memory SystemVerilog sources to the application's RTL
output directory. Each source entry is keyed by its module name and is written
as a <module_name>.sv file.
expand/2 is the main entry point. It validates the top-module name, validates
all source entries, creates the RTL output directory if needed, and writes all
source files into that directory.
Module names are intentionally limited to a safe identifier subset: the name must start with an ASCII letter or underscore, followed by ASCII letters, digits, underscores, or dollar signs. Escaped SystemVerilog identifiers are not supported because module names are also used directly as file names.
The functions in this module write files to disk, but they do not invoke Verilator, compile generated files, or run a simulation.
Summary
Functions
Expands SystemVerilog source strings into the RTL output directory.
Returns the RTL output directory.
Builds the SystemVerilog source filename for module_name.
Builds the SystemVerilog source filename for module_name, raising on error.
Types
@type expand_result() :: %{ top_module: module_name(), rtl_dir: Path.t(), files: %{required(module_name()) => Path.t()} }
@type module_name() :: String.t()
@type source_map() :: %{required(module_name()) => sv_source()}
@type sv_source() :: String.t()
Functions
@spec expand(module_name(), source_map()) :: {:ok, expand_result()} | {:error, term()}
Expands SystemVerilog source strings into the RTL output directory.
top_module must be a valid module name and must exist as a key in sources.
Each entry in sources must have a valid module name as its key and a source
string as its value.
The output directory is resolved by rtl_dir/0. Each source entry is written
directly under that directory by using the filename returned by
source_filename/1. Existing files with the same names are overwritten.
Returns {:ok, result} on success. The returned map contains:
:top_module- the top-module name passed to this function:rtl_dir- the RTL output directory:files- a map from module names to written file paths
Returns one of the following error tuples:
{:error, {:invalid_arguments, top_module, sources}}whentop_moduleis not a binary orsourcesis not a map{:error, :empty_sources}whensourcesis an empty map{:error, {:invalid_source_entry, module_name, source}}when a source entry does not have a binary module name and a binary source string{:error, {:invalid_module_name, module_name}}when a module name does not satisfy the accepted identifier format{:error, {:top_module_not_found, top_module}}whensourcesdoes not containtop_module{:error, {:mkdir_failed, rtl_dir, reason}}when creating the RTL output directory fails{:error, {:write_failed, module_name, file_path, reason}}when writing a source file fails
Example
sources = %{
"Counter" => "module Counter; endmodule",
"SubMod" => "module SubMod; endmodule"
}
{:ok, result} = SvPortSim.Rtl.expand("Counter", sources)
result.top_module
#=> "Counter"
Map.keys(result.files)
#=> ["Counter", "SubMod"]
@spec rtl_dir() :: Path.t()
Returns the RTL output directory.
The directory is currently resolved as:
Application.app_dir(:sv_port_sim, "rtl")expand/2 creates this directory before writing source files. This function
only returns the path; it does not create the directory.
@spec source_filename(module_name()) :: {:ok, String.t()} | {:error, term()}
Builds the SystemVerilog source filename for module_name.
The filename is formed by appending .sv to the validated module name.
Returns {:ok, filename} on success.
Returns {:error, {:invalid_module_name, module_name}} when module_name is
not a binary or does not satisfy the accepted identifier format.
Examples
iex> SvPortSim.Rtl.source_filename("Counter")
{:ok, "Counter.sv"}
iex> SvPortSim.Rtl.source_filename("../Counter")
{:error, {:invalid_module_name, "../Counter"}}
iex> SvPortSim.Rtl.source_filename(123)
{:error, {:invalid_module_name, 123}}
@spec source_filename!(module_name()) :: String.t()
Builds the SystemVerilog source filename for module_name, raising on error.
This is the bang variant of source_filename/1.
Returns the filename when module_name is valid.
Raises ArgumentError when module_name is not a binary or does not satisfy
the accepted identifier format.
Examples
iex> SvPortSim.Rtl.source_filename!("Counter")
"Counter.sv"
iex> SvPortSim.Rtl.source_filename!("../Counter")
** (ArgumentError) {:invalid_module_name, "../Counter"}