aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/anlogic/anlogic_fixcarry.cc
blob: 87164d375f2aa6b22cdb82245ccec6edf476e59b (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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2019  Miodrag Milanovic <miodrag@symbioticeda.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/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static SigBit get_bit_or_zero(const SigSpec &sig)
{
	if (GetSize(sig) == 0)
		return State::S0;
	return sig[0];
}

static void fix_carry_chain(Module *module)
{
	SigMap sigmap(module);

	pool<SigBit> ci_bits;
	dict<SigBit, SigBit> mapping_bits;

	for (auto cell : module->cells())
	{
		if (cell->type == "\\AL_MAP_ADDER") {
			if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
			SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
			SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
			if (bit_i0 == State::S0 && bit_i1== State::S0) {
				SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
				SigSpec o = cell->getPort("\\o");
				if (GetSize(o) == 2) {
					SigBit bit_o = o[0];
					ci_bits.insert(bit_ci);				
					mapping_bits[bit_ci] = bit_o;				
				}
			}
		}
	}
	vector<Cell*> adders_to_fix_cells;
	for (auto cell : module->cells())
	{
		if (cell->type == "\\AL_MAP_ADDER") {
			if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
			SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
			SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
			SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));			
			SigBit canonical_bit = sigmap(bit_ci);
			if (!ci_bits.count(canonical_bit))
				continue;			
			if (bit_i0 == State::S0 && bit_i1== State::S0) 
				continue;

			adders_to_fix_cells.push_back(cell);
			log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
		}
	}

	for (auto cell : adders_to_fix_cells)
	{
		SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
		SigBit canonical_bit = sigmap(bit_ci);
		auto bit = mapping_bits.at(canonical_bit);
		log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
		Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
		SigBit new_bit = module->addWire(NEW_ID);
		SigBit dummy_bit = module->addWire(NEW_ID);
		SigSpec bits;
		bits.append(dummy_bit);
		bits.append(new_bit);
		c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
		c->setPort("\\a", bit);
		c->setPort("\\b", State::S0);
		c->setPort("\\c", State::S0);
		c->setPort("\\o", bits);
		
		cell->setPort("\\c", new_bit);
	}
	
}

struct AnlogicCarryFixPass : public Pass {
	AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    anlogic_fixcarry [options] [selection]\n");
		log("\n");
		log("Add Anlogic adders to fix carry chain if needed.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
		
		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			break;
		}
		extra_args(args, argidx, design);

		Module *module = design->top_module();

		if (module == nullptr)
			log_cmd_error("No top module found.\n");

		fix_carry_chain(module);		
	}
} AnlogicCarryFixPass;

PRIVATE_NAMESPACE_END
cret key, either ``128``, ``192``, or ``256`` bits. This must be kept secret. .. class:: Camellia(key) Camellia is a block cipher approved for use by CRYPTREC and ISO/IEC. It is considered to have comparable security and performance to AES, but is not as widely studied or deployed. :param bytes key: The secret key, either ``128``, ``192``, or ``256`` bits. This must be kept secret. .. class:: TripleDES(key) Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a block cipher standardized by NIST. Triple DES has known crypto-analytic flaws, however none of them currently enable a practical attack. Nonetheless, Triples DES is not recommended for new applications because it is incredibly slow; old applications should consider moving away from it. :param bytes key: The secret key, either ``64``, ``128``, or ``192`` bits (note that DES functionally uses ``56``, ``112``, or ``168`` bits of the key, there is a parity byte in each component of the key), in some materials these are referred to as being up to three separate keys (each ``56`` bits long), they can simply be concatenated to produce the full key. This must be kept secret. .. class:: CAST5(key) CAST5 (also known as CAST-128) is a block cipher approved for use in the Canadian government by their Communications Security Establishment. It is a variable key length cipher and supports keys from 40-128 bits in length. :param bytes key: The secret key, 40-128 bits in length (in increments of 8). This must be kept secret. Weak Ciphers ------------ .. warning:: These ciphers are considered weak for a variety of reasons. New applications should avoid their use and existing applications should strongly consider migrating away. .. class:: Blowfish(key) Blowfish is a block cipher developed by Bruce Schneier. It is known to be susceptible to attacks when using weak keys. The author has recommended that users of Blowfish move to newer algorithms, such as :class:`AES`. :param bytes key: The secret key, 32-448 bits in length (in increments of 8). This must be kept secret. .. class:: ARC4(key) ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its initial stream output. Its use is strongly discouraged. ARC4 does not use mode constructions. :param bytes key: The secret key, ``40``, ``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` bits in length. This must be kept secret. .. doctest:: >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes >>> from cryptography.hazmat.backends import default_backend >>> algorithm = algorithms.ARC4(key) >>> cipher = Cipher(algorithm, mode=None, backend=default_backend()) >>> encryptor = cipher.encryptor() >>> ct = encryptor.update(b"a secret message") >>> decryptor = cipher.decryptor() >>> decryptor.update(ct) 'a secret message' .. _symmetric-encryption-modes: Modes ~~~~~ .. currentmodule:: cryptography.hazmat.primitives.ciphers.modes .. class:: CBC(initialization_vector) CBC (Cipher block chaining) is a mode of operation for block ciphers. It is considered cryptographically strong. :param bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the same number of bytes as the ``block_size`` of the cipher. Each time something is encrypted a new ``initialization_vector`` should be generated. Do not reuse an ``initialization_vector`` with a given ``key``, and particularly do not use a constant ``initialization_vector``. A good construction looks like: .. doctest:: >>> import os >>> from cryptography.hazmat.primitives.ciphers.modes import CBC >>> iv = os.urandom(16) >>> mode = CBC(iv) While the following is bad and will leak information: .. doctest:: >>> from cryptography.hazmat.primitives.ciphers.modes import CBC >>> iv = "a" * 16 >>> mode = CBC(iv) .. class:: CTR(nonce) .. warning:: Counter mode is not recommended for use with block ciphers that have a block size of less than 128-bits. CTR (Counter) is a mode of operation for block ciphers. It is considered cryptographically strong. It transforms a block cipher into a stream cipher. :param bytes nonce: Should be random bytes. It is critical to never reuse a ``nonce`` with a given key. Any reuse of a nonce with the same key compromises the security of every message encrypted with that key. Must be the same number of bytes as the ``block_size`` of the cipher with a given key. The nonce does not need to be kept secret and may be included alongside the ciphertext. .. class:: OFB(initialization_vector) OFB (Output Feedback) is a mode of operation for block ciphers. It transforms a block cipher into a stream cipher. :param bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the same number of bytes as the ``block_size`` of the cipher. Do not reuse an ``initialization_vector`` with a given ``key``. .. class:: CFB(initialization_vector) CFB (Cipher Feedback) is a mode of operation for block ciphers. It transforms a block cipher into a stream cipher. :param bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the same number of bytes as the ``block_size`` of the cipher. Do not reuse an ``initialization_vector`` with a given ``key``. .. class:: GCM(initialization_vector, tag=None) .. danger:: When using this mode you MUST not use the decrypted data until :meth:`~cryptography.hazmat.primitives.interfaces.CipherContext.finalize` has been called. GCM provides NO guarantees of ciphertext integrity until decryption is complete. GCM (Galois Counter Mode) is a mode of operation for block ciphers. An AEAD (authenticated encryption with additional data) mode is a type of block cipher mode that encrypts the message as well as authenticating it (and optionally additional data that is not encrypted) simultaneously. Additional means of verifying integrity (like :doc:`HMAC </hazmat/primitives/hmac>`) are not necessary. :param bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). NIST `recommends 96-bit IV length`_ for performance critical situations, but it can be up to 2\ :sup:`64` - 1 bits. Do not reuse an ``initialization_vector`` with a given ``key``. .. note:: Cryptography will emit a 128-bit tag when finalizing encryption. You can shorten a tag by truncating it to the desired length, but this is **not recommended** as it lowers the security margins of the authentication (`NIST SP-800-38D`_ recommends 96-bits or greater). If you must shorten the tag the minimum allowed length is 4 bytes (32-bits). Applications **must** verify the tag is the expected length to guarantee the expected security margin. :param bytes tag: The tag bytes to verify during decryption. When encrypting this must be None. .. doctest:: >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes >>> from cryptography.hazmat.backends import default_backend >>> cipher = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend()) >>> encryptor = cipher.encryptor() >>> encryptor.authenticate_additional_data(b"authenticated but not encrypted payload") >>> ct = encryptor.update(b"a secret message") + encryptor.finalize() >>> tag = encryptor.tag >>> cipher = Cipher(algorithms.AES(key), modes.GCM(iv, tag), backend) >>> decryptor = cipher.decryptor() >>> decryptor.authenticate_additional_data(b"authenticated but not encrypted payload") >>> decryptor.update(ct) + decryptor.finalize() 'a secret message' Insecure Modes -------------- .. warning:: These modes are insecure. New applications should never make use of them, and existing applications should strongly consider migrating away. .. class:: ECB() ECB (Electronic Code Book) is the simplest mode of operation for block ciphers. Each block of data is encrypted in the same way. This means identical plaintext blocks will always result in identical ciphertext blocks, and thus result in information leakage .. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html .. _`recommends 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf .. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf