aboutsummaryrefslogtreecommitdiffstats
path: root/backends/spice/spice.cc
blob: f260276eb931ae84d2850a4f0a7d02d0f722dcbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
.. hazmat::

Bindings
========

.. toctree::
    :maxdepth: 1

    openssl
    interfaces


Getting a Backend Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~

.. currentmodule:: cryptography.hazmat.bindings

``cryptography`` aims to support multiple backends to ensure it can provide
the widest number of supported cryptographic algorithms as well as supporting
platform specific implementations.

You can get the default backend by calling
:func:`~default_backend`.

The default backend will change over time as we implement new backends and
the libraries we use in those backends changes.


.. function:: default_backend()

    :returns: An object that provides at least
        :class:`~interfaces.CipherBackend`, :class:`~interfaces.HashBackend`, and
        :class:`~interfaces.HMACBackend`.
n260'>260 261 262 263 264 265 266 267 268 269 270
/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static string spice_id2str(IdString id)
{
	static const char *escape_chars = "$\\[]()<>=";
	string s = RTLIL::unescape_id(id);

	for (auto &ch : s)
		if (strchr(escape_chars, ch) != nullptr) ch = '_';

	return s;
}

static string spice_id2str(IdString id, bool use_inames, idict<IdString, 1> &inums)
{
	if (!use_inames && *id.c_str() == '$')
		return stringf("%d", inums(id));
	return spice_id2str(id);
}

static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter, bool use_inames, idict<IdString, 1> &inums)
{
	if (s.wire) {
		if (s.wire->port_id)
			use_inames = true;
		if (s.wire->width > 1)
			f << stringf(" %s.%d", spice_id2str(s.wire->name, use_inames, inums).c_str(), s.offset);
		else
			f << stringf(" %s", spice_id2str(s.wire->name, use_inames, inums).c_str());
	} else {
		if (s == RTLIL::State::S0)
			f << stringf(" %s", neg.c_str());
		else if (s == RTLIL::State::S1)
			f << stringf(" %s", pos.c_str());
		else
			f << stringf(" %s%d", ncpf.c_str(), nc_counter++);
	}
}

static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &buf, std::string &ncpf, bool big_endian, bool use_inames)
{
	SigMap sigmap(module);
	idict<IdString, 1> inums;
	int cell_counter = 0, conn_counter = 0, nc_counter = 0;

	for (auto cell : module->cells())
	{
		f << stringf("X%d", cell_counter++);

		std::vector<RTLIL::SigSpec> port_sigs;

		if (design->module(cell->type) == nullptr)
		{
			log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n",
					log_id(cell->type), log_id(module), log_id(cell));
			for (auto &conn : cell->connections()) {
				RTLIL::SigSpec sig = sigmap(conn.second);
				port_sigs.push_back(sig);
			}
		}
		else
		{
			RTLIL::Module *mod = design->module(cell->type);

			std::vector<RTLIL::Wire*> ports;
			for (auto wire : mod->wires()) {
				if (wire->port_id == 0)
					continue;
				while (int(ports.size()) < wire->port_id)
					ports.push_back(NULL);
				ports.at(wire->port_id-1) = wire;
			}

			for (RTLIL::Wire *wire : ports) {
				log_assert(wire != NULL);
				RTLIL::SigSpec sig(RTLIL::State::Sz, wire->width);
				if (cell->hasPort(wire->name)) {
					sig = sigmap(cell->getPort(wire->name));
					sig.extend_u0(wire->width, false);
				}
				port_sigs.push_back(sig);
			}
		}

		for (auto &sig : port_sigs) {
			for (int i = 0; i < sig.size(); i++) {
				RTLIL::SigSpec s = sig.extract(big_endian ? sig.size() - 1 - i : i, 1);
				print_spice_net(f, s, neg, pos, ncpf, nc_counter, use_inames, inums);
			}
		}

		f << stringf(" %s\n", spice_id2str(cell->type).c_str());
	}

	for (auto &conn : module->connections())
	for (int i = 0; i < conn.first.size(); i++) {
		f << (buf == "DC" ? stringf("V%d", conn_counter++) : stringf("X%d", cell_counter++));
		print_spice_net(f, conn.second.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
		print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
		f << (buf == "DC" ? " DC 0\n" : stringf(" %s\n", buf.c_str()));
	}
}

struct SpiceBackend : public Backend {
	SpiceBackend() : Backend("spice", "write design to SPICE netlist file") { }
	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    write_spice [options] [filename]\n");
		log("\n");
		log("Write the current design to an SPICE netlist file.\n");
		log("\n");
		log("    -big_endian\n");
		log("        generate multi-bit ports in MSB first order\n");
		log("        (default is LSB first)\n");
		log("\n");
		log("    -neg net_name\n");
		log("        set the net name for constant 0 (default: Vss)\n");
		log("\n");
		log("    -pos net_name\n");
		log("        set the net name for constant 1 (default: Vdd)\n");
		log("\n");
		log("    -buf DC|subckt_name\n");
		log("        set the name for jumper element (default: DC)\n");
		log("        (used to connect different nets)\n");
		log("\n");
		log("    -nc_prefix\n");
		log("        prefix for not-connected nets (default: _NC)\n");
		log("\n");
		log("    -inames\n");
		log("        include names of internal ($-prefixed) nets in outputs\n");
		log("        (default is to use net numbers instead)\n");
		log("\n");
		log("    -top top_module\n");
		log("        set the specified module as design top module\n");
		log("\n");
	}
	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
	{
		std::string top_module_name;
		RTLIL::Module *top_module = NULL;
		bool big_endian = false, use_inames = false;
		std::string neg = "Vss", pos = "Vdd", ncpf = "_NC", buf = "DC";

		log_header(design, "Executing SPICE backend.\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-big_endian") {
				big_endian = true;
				continue;
			}
			if (args[argidx] == "-inames") {
				use_inames = true;
				continue;
			}
			if (args[argidx] == "-neg" && argidx+1 < args.size()) {
				neg = args[++argidx];
				continue;
			}
			if (args[argidx] == "-pos" && argidx+1 < args.size()) {
				pos = args[++argidx];
				continue;
			}
			if (args[argidx] == "-buf" && argidx+1 < args.size()) {
				buf = args[++argidx];
				continue;
			}
			if (args[argidx] == "-nc_prefix" && argidx+1 < args.size()) {
				ncpf = args[++argidx];
				continue;
			}
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_module_name = args[++argidx];
				continue;
			}
			break;
		}
		extra_args(f, filename, args, argidx);

		if (top_module_name.empty())
			for (auto module : design->modules())
				if (module->get_bool_attribute(ID::top))
					top_module_name = module->name.str();

		*f << stringf("* SPICE netlist generated by %s\n", yosys_version_str);
		*f << stringf("\n");

		for (auto module : design->modules())
		{
			if (module->get_blackbox_attribute())
				continue;

			if (module->processes.size() != 0)
				log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module));
			if (module->memories.size() != 0)
				log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module));

			if (module->name == RTLIL::escape_id(top_module_name)) {
				top_module = module;
				continue;
			}

			std::vector<RTLIL::Wire*> ports;
			for (auto wire : module->wires()) {
				if (wire->port_id == 0)
					continue;
				while (int(ports.size()) < wire->port_id)
					ports.push_back(NULL);
				ports.at(wire->port_id-1) = wire;
			}

			*f << stringf(".SUBCKT %s", spice_id2str(module->name).c_str());
			for (RTLIL::Wire *wire : ports) {
				log_assert(wire != NULL);
				if (wire->width > 1) {
					for (int i = 0; i < wire->width; i++)
						*f << stringf(" %s.%d", spice_id2str(wire->name).c_str(), big_endian ? wire->width - 1 - i : i);
				} else
					*f << stringf(" %s", spice_id2str(wire->name).c_str());
			}
			*f << stringf("\n");
			print_spice_module(*f, module, design, neg, pos, buf, ncpf, big_endian, use_inames);
			*f << stringf(".ENDS %s\n\n", spice_id2str(module->name).c_str());
		}

		if (!top_module_name.empty()) {
			if (top_module == NULL)
				log_error("Can't find top module `%s'!\n", top_module_name.c_str());
			print_spice_module(*f, top_module, design, neg, pos, buf, ncpf, big_endian, use_inames);
			*f << stringf("\n");
		}

		*f << stringf("************************\n");
		*f << stringf("* end of SPICE netlist *\n");
		*f << stringf("************************\n");
		*f << stringf("\n");
	}
} SpiceBackend;

PRIVATE_NAMESPACE_END