File: ql_dsp_io_regs.cc

package info (click to toggle)
yosys 0.52-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 69,796 kB
  • sloc: ansic: 696,955; cpp: 239,736; python: 14,617; yacc: 3,529; sh: 2,175; makefile: 1,945; lex: 697; perl: 445; javascript: 323; tcl: 162; vhdl: 115
file content (157 lines) | stat: -rw-r--r-- 4,214 bytes parent folder | download
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright 2020-2022 F4PGA Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 */

#include "kernel/sigtools.h"
#include "kernel/yosys.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#define MODE_BITS_REGISTER_INPUTS_ID 92
#define MODE_BITS_OUTPUT_SELECT_START_ID 81
#define MODE_BITS_OUTPUT_SELECT_WIDTH 3

// ============================================================================

struct QlDspIORegs : public Pass {
	SigMap sigmap;

	// ..........................................

	QlDspIORegs() : Pass("ql_dsp_io_regs", "change types of QL_DSP2 depending on configuration") {}

	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    ql_dsp_io_regs [options] [selection]\n");
		log("\n");
		log("This pass looks for QL_DSP2 cells and changes their cell type depending on their\n");
		log("configuration.\n");
	}

	void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override
	{
		log_header(a_Design, "Executing QL_DSP_IO_REGS pass.\n");

		size_t argidx;
		for (argidx = 1; argidx < a_Args.size(); argidx++) {
			break;
		}
		extra_args(a_Args, argidx, a_Design);

		for (auto module : a_Design->selected_modules()) {
			ql_dsp_io_regs_pass(module);
		}
	}

	void ql_dsp_io_regs_pass(RTLIL::Module *module)
	{
		static const std::vector<IdString> ports2del_mult = {ID(load_acc), ID(subtract), ID(acc_fir), ID(dly_b),
														ID(saturate_enable), ID(shift_right), ID(round)};
		static const std::vector<IdString> ports2del_mult_acc = {ID(acc_fir), ID(dly_b)};


		sigmap.set(module);

		for (auto cell : module->cells()) {
			if (cell->type != ID(QL_DSP2))
				continue;

			// If the cell does not have the "is_inferred" attribute set
			// then don't touch it.
			if (!cell->get_bool_attribute(ID(is_inferred)))
				continue;

			// Get DSP configuration
			for (auto cfg_port : {ID(register_inputs), ID(output_select)})
			if (!cell->hasPort(cfg_port) || !sigmap(cell->getPort(cfg_port)).is_fully_const())
				log_error("Missing or non-constant '%s' port on DSP cell %s\n",
						  log_id(cfg_port), log_id(cell));
			int reg_in_i = sigmap(cell->getPort(ID(register_inputs))).as_int();
			int out_sel_i = sigmap(cell->getPort(ID(output_select))).as_int();

			// Get the feedback port
			if (!cell->hasPort(ID(feedback)))
				log_error("Missing 'feedback' port on %s", log_id(cell));
			SigSpec feedback = sigmap(cell->getPort(ID(feedback)));

			// Check the top two bits on 'feedback' to be constant zero.
			// That's what we are expecting from inference.
			if (feedback.extract(1, 2) != SigSpec(0, 2))
				log_error("Unexpected feedback configuration on %s\n", log_id(cell));

			// Build new type name
			std::string new_type = "\\QL_DSP2_MULT";

			// Decide if we should be deleting the clock port
			bool del_clk = true;

			switch (out_sel_i) {
				case 1:
				case 2:
				case 3:
				case 5:
				case 7:
					del_clk = false;
					new_type += "ACC";
					break;
				default:
					break;
			}

			if (reg_in_i) {
				del_clk = false;
				new_type += "_REGIN";
			}

			if (out_sel_i > 3) {
				del_clk = false;
				new_type += "_REGOUT";
			}

			// Set new type name
			cell->type = RTLIL::IdString(new_type);

			std::vector<std::string> ports2del;

			if (del_clk)
				cell->unsetPort(ID(clk));

			switch (out_sel_i) {
			case 0:
			case 4:
			case 6:
				for (auto port : ports2del_mult)
					cell->unsetPort(port);
				break;
			case 1:
			case 2:
			case 3:
			case 5:
			case 7:
				for (auto port : ports2del_mult_acc)
					cell->unsetPort(port);
				break;
			}
		}
	}
} QlDspIORegs;

PRIVATE_NAMESPACE_END