summaryrefslogtreecommitdiff
path: root/CodingReadme
blob: b64e79178c6df48844cb656ce8d784eb11909df2 (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
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
This file contains some very brief documentation on things like programming APIs.
Also consult the Yosys manual and the section about programming in the presentation.
(Both can be downloaded as PDF from the yosys webpage.)


--snip-- only the lines below this mark are included in the yosys manual --snip--
Getting Started
===============


Outline of a Yosys command
--------------------------

Here is a the C++ code for a "hello_world" Yosys command (hello.cc):

	#include "kernel/yosys.h"

	USING_YOSYS_NAMESPACE
	PRIVATE_NAMESPACE_BEGIN

	struct HelloWorldPass : public Pass {
		HelloWorldPass() : Pass("hello_world") { }
		void execute(vector<string>, Design*) override {
			log("Hello World!\n");
		}
	} HelloWorldPass;

	PRIVATE_NAMESPACE_END

This can be built into a Yosys module using the following command:

	yosys-config --exec --cxx --cxxflags --ldflags -o hello.so -shared hello.cc --ldlibs

Or short:

	yosys-config --build hello.so hello.cc

And then executed using the following command:

	yosys -m hello.so -p hello_world


Yosys Data Structures
---------------------

Here is a short list of data structures that you should make yourself familiar
with before you write C++ code for Yosys. The following data structures are all
defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used.

  1. Yosys Container Classes

Yosys uses dict<K, T> and pool<T> as main container classes. dict<K, T> is
essentially a replacement for std::unordered_map<K, T> and pool<T> is a
replacement for std::unordered_set<T>. The main characteristics are:

	- dict<K, T> and pool<T> are about 2x faster than the std containers

	- references to elements in a dict<K, T> or pool<T> are invalidated by
	  insert and remove operations (similar to std::vector<T> on push_back()).

	- some iterators are invalidated by erase(). specifically, iterators
	  that have not passed the erased element yet are invalidated. (erase()
	  itself returns valid iterator to the next element.)

	- no iterators are invalidated by insert(). elements are inserted at
	  begin(). i.e. only a new iterator that starts at begin() will see the
	  inserted elements.

	- the method .count(key, iterator) is like .count(key) but only
	  considers elements that can be reached via the iterator.

	- iterators can be compared. it1 < it2 means that the position of t2
	  can be reached via t1 but not vice versa.

	- the method .sort() can be used to sort the elements in the container
	  the container stays sorted until elements are added or removed.

	- dict<K, T> and pool<T> will have the same order of iteration across
	  all compilers, standard libraries and architectures.

In addition to dict<K, T> and pool<T> there is also an idict<K> that
creates a bijective map from K to the integers. For example:

	idict<string, 42> si;
	log("%d\n", si("hello"));      // will print 42
	log("%d\n", si("world"));      // will print 43
	log("%d\n", si.at("world"));   // will print 43
	log("%d\n", si.at("dummy"));   // will throw exception
	log("%s\n", si[42].c_str()));  // will print hello
	log("%s\n", si[43].c_str()));  // will print world
	log("%s\n", si[44].c_str()));  // will throw exception

It is not possible to remove elements from an idict.

Finally mfp<K> implements a merge-find set data structure (aka. disjoint-set or
union-find) over the type K ("mfp" = merge-find-promote).

  2. Standard STL data types

In Yosys we use std::vector<T> and std::string whenever applicable. When
dict<K, T> and pool<T> are not suitable then std::map<K, T> and std::set<T>
are used instead.

The types std::vector<T> and std::string are also available as vector<T>
and string in the Yosys namespace.

  3. RTLIL objects

The current design (essentially a collection of modules, each defined by a
netlist) is stored in memory using RTLIL object (declared in kernel/rtlil.h,
automatically included by kernel/yosys.h). You should glance over at least
the declarations for the following types in kernel/rtlil.h:

	RTLIL::IdString
		This is a handle for an identifier (e.g. cell or wire name).
		It feels a lot like a std::string, but is only a single int
		in size. (The actual string is stored in a global lookup
		table.)

	RTLIL::SigBit
		A single signal bit. I.e. either a constant state (0, 1,
		x, z) or a single bit from a wire.

	RTLIL::SigSpec
		Essentially a vector of SigBits.

	RTLIL::Wire
	RTLIL::Cell
		The building blocks of the netlist in a module.

	RTLIL::Module
	RTLIL::Design
		The module is a container with connected cells and wires
		in it. The design is a container with modules in it.

All this types are also available without the RTLIL:: prefix in the Yosys
namespace.

  4. SigMap and other Helper Classes

There are a couple of additional helper classes that are in wide use
in Yosys. Most importantly there is SigMap (declared in kernel/sigtools.h).

When a design has many wires in it that are connected to each other, then a
single signal bit can have multiple valid names. The SigMap object can be used
to map SigSpecs or SigBits to unique SigSpecs and SigBits that consistently
only use one wire from such a group of connected wires. For example:

	SigBit a = module->addWire(NEW_ID);
	SigBit b = module->addWire(NEW_ID);
	module->connect(a, b);

	log("%d\n", a == b); // will print 0

	SigMap sigmap(module);
	log("%d\n", sigmap(a) == sigmap(b)); // will print 1


Using the RTLIL Netlist Format
------------------------------

In the RTLIL netlist format the cell ports contain SigSpecs that point to the
Wires. There are no references in the other direction. This has two direct
consequences:

(1) It is very easy to go from cells to wires but hard to go in the other way.

(2) There is no danger in removing cells from the netlists, but removing wires
can break the netlist format when there are still references to the wire
somewhere in the netlist.

The solution to (1) is easy: Create custom indexes that allow you to make fast
lookups for the wire-to-cell direction. You can either use existing generic
index structures to do that (such as the ModIndex class) or write your own
index. For many application it is simplest to construct a custom index. For
example:

	SigMap sigmap(module);
	dict<SigBit, Cell*> sigbit_to_driver_index;

	for (auto cell : module->cells())
		for (auto &conn : cell->connections())
			if (cell->output(conn.first))
				for (auto bit : sigmap(conn.second))
					sigbit_to_driver_index[bit] = cell;

Regarding (2): There is a general theme in Yosys that you don't remove wires
from the design. You can rename them, unconnect them, but you do not actually remove
the Wire object from the module. Instead you let the "clean" command take care
of the dangling wires. On the other hand it is safe to remove cells (as long as
you make sure this does not invalidate a custom index you are using in your code).


Example Code
------------

The following yosys commands are a good starting point if you are looking for examples
of how to use the Yosys API:

	manual/CHAPTER_Prog/stubnets.cc
	manual/PRESENTATION_Prog/my_cmd.cc


Notes on the existing codebase
------------------------------

For historical reasons not all parts of Yosys adhere to the current coding
style. When adding code to existing parts of the system, adhere to this guide
for the new code instead of trying to mimic the style of the surrounding code.



Coding Style
============


Formatting of code
------------------

- Yosys code is using tabs for indentation. Tabs are 8 characters.

- A continuation of a statement in the following line is indented by
  two additional tabs.

- Lines are as long as you want them to be. A good rule of thumb is
  to break lines at about column 150.

- Opening braces can be put on the same or next line as the statement
  opening the block (if, switch, for, while, do). Put the opening brace
  on its own line for larger blocks, especially blocks that contains
  blank lines.

- Otherwise stick to the Linux Kernel Coding Style:
    https://www.kernel.org/doc/Documentation/CodingStyle


C++ Language
-------------

Yosys is written in C++11. At the moment only constructs supported by
gcc 4.8 are allowed in Yosys code. This will change in future releases.

In general Yosys uses "int" instead of "size_t". To avoid compiler
warnings for implicit type casts, always use "GetSize(foobar)" instead
of "foobar.size()". (GetSize() is defined in kernel/yosys.h)

Use range-based for loops whenever applicable.


--snap-- only the lines above this mark are included in the yosys manual --snap--


Creating the Visual Studio Template Project
===========================================

1. Create an empty Visual C++ Win32 Console App project

	Microsoft Visual Studio Express 2013 for Windows Desktop
	Open New Project Wizard (File -> New Project..)

	Project Name: YosysVS
	Solution Name: YosysVS
	[X] Create directory for solution
	[ ] Add to source control

	[X] Console applications
	[X] Empty Project
	[ ] SDL checks

2. Open YosysVS Project Properties

	Select Configuration: All Configurations

	C/C++ -> General -> Additional Include Directories
		Add: ..\yosys

	C/C++ -> Preprocessor -> Preprocessor Definitions
		Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS

3. Resulting file system tree:

	YosysVS/
	YosysVS/YosysVS
	YosysVS/YosysVS/YosysVS.vcxproj
	YosysVS/YosysVS/YosysVS.vcxproj.filters
	YosysVS/YosysVS.sdf
	YosysVS/YosysVS.sln
	YosysVS/YosysVS.v12.suo

4. Zip YosysVS as YosysVS-Tpl-v1.zip



Checklist for adding internal cell types
========================================

Things to do right away:

	- Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
	- Add to InternalCellChecker::check() in kernel/rtlil.cc
	- Add to techlibs/common/simlib.v
	- Add to techlibs/common/techmap.v

Things to do after finalizing the cell interface:

	- Add support to kernel/satgen.h for the new cell type
	- Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
	- Maybe add support to the Verilog backend for dumping such cells as expression



Checklist for creating Yosys releases
=====================================

Update the CHANGELOG file:

	cd ~yosys
	gitk &
	vi CHANGELOG


Update and check documentation:

	cd ~yosys
	make update-manual
	make manual
	- sanity check the figures in the appnotes and presentation
	    - if there are any odd things -> investigate
	    - make cosmetic changes to the .tex files if necessary

	cd ~yosys
	vi README CodingReadme
	- is the information provided in those file still up to date


Then with default config setting:

	cd ~yosys
	make vgtest

	cd ~yosys
	./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
	./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
	./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
	./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v

	cd ~yosys/examples/cmos
	bash testbench.sh

	cd ~yosys/examples/basys3
	bash run.sh


Test building plugins with various of the standard passes:

	yosys-config --build test.so equiv_simple.cc
	- also check the code examples in CodingReadme


And if a version of the verific library is currently available:

	cd ~yosys
	cat frontends/verific/build_amd64.txt
	- follow instructions

	cd frontends/verific
	../../yosys test_navre.ys


Finally run all tests with "make config-{clang,gcc,gcc-4.8}":

	cd ~yosys
	make clean
	make test
	make ystests
	make vloghtb
	make install

	cd ~yosys-bigsim
	make clean
	make full

	cd ~vloghammer
	make purge gen_issues gen_samples
	make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
	chromium-browser report.html


Release:

	- set YOSYS_VER to x.y.z in Makefile
	- update version string in CHANGELOG
	git commit -am "Yosys x.y.z"

	- push tag to github
	- post changelog on github
	- post short release note on reddit


Updating the website:

	cd ~yosys
	make manual
	make install

	- update pdf files on the website

	cd ~yosys-web
	make update_cmd
	make update_show
	git commit -am update
	make push



Cross-Building for Windows with MXE
===================================

Check http://mxe.cc/#requirements and install all missing requirements.

As root (or other user with write access to /usr/local/src):

	cd /usr/local/src
	git clone https://github.com/mxe/mxe.git
	cd mxe

	make -j$(nproc) MXE_PLUGIN_DIRS="plugins/tcl.tk" \
			MXE_TARGETS="i686-w64-mingw32.static" \
			gcc tcl readline

Then as regular user in some directory where you build stuff:

	git clone https://github.com/cliffordwolf/yosys.git yosys-win32
	cd yosys-win32
	make config-mxe
	make -j$(nproc) mxebin



How to add unit test
====================

Unit test brings some advantages, briefly, we can list some of them (reference
[1](https://en.wikipedia.org/wiki/Unit_testing)):

* Tests reduce bugs in new features;
* Tests reduce bugs in existing features;
* Tests are good documentation;
* Tests reduce the cost of change;
* Tests allow refactoring;

With those advantages in mind, it was required to choose a framework which fits
well with C/C++ code.  Hence, it was chosen (google test)
[https://github.com/google/googletest], because it is largely used and it is
relatively easy learn.

Install and configure google test (manually)
--------------------------------------------

In this section, you will see a brief description of how to install google
test. However, it is strongly recommended that you take a look to the official
repository (https://github.com/google/googletest) and refers to that if you
have any problem to install it. Follow the steps below:

* Install: cmake and pthread
* Clone google test project from: https://github.com/google/googletest and
  enter in the project directory
* Inside project directory, type:

```
cmake -DBUILD_SHARED_LIBS=ON .
make
```

* After compilation, copy all "*.so" inside directory "googlemock" and
  "googlemock/gtest" to "/usr/lib/"
* Done! Now you can compile your tests.

If you have any problem, go to the official repository to find help.

Ps.: Some distros already have googletest packed. If your distro supports it,
you can use it instead of compile.

Create new unit test
--------------------

If you want to add new unit tests for Yosys, just follow the steps below:

* Go to directory "yosys/test/unit/"
* In this directory you can find something similar Yosys's directory structure.
  To create your unit test file you have to follow this pattern:
  fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the
  unit test for kernel/celledges.cc, you will need to create a file like this:
  tests/unit/kernel/celledgesTest.cc;
* Implement your unit test

Run unit test
-------------

To compile and run all unit tests, just go to yosys root directory and type:
```
make unit-test
```

If you want to remove all unit test files, type:
```
make clean-unit-test
```