0% found this document useful (0 votes)
14 views

Guide To Computer Processor Architecture A Riscv Approach With Highlevel Synthesis Bernard Goossens instant download

Ebook access

Uploaded by

ithanroela32
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Guide To Computer Processor Architecture A Riscv Approach With Highlevel Synthesis Bernard Goossens instant download

Ebook access

Uploaded by

ithanroela32
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 82

Guide To Computer Processor Architecture A Riscv

Approach With Highlevel Synthesis Bernard


Goossens download

https://ebookbell.com/product/guide-to-computer-processor-
architecture-a-riscv-approach-with-highlevel-synthesis-bernard-
goossens-47592970

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Guide To Computer Network Security Second Edition 2nd Joseph Migga


Kizza

https://ebookbell.com/product/guide-to-computer-network-security-
second-edition-2nd-joseph-migga-kizza-46254568

Guide To Computer Network Security Texts In Computer Science 5th Ed


2020 Kizza

https://ebookbell.com/product/guide-to-computer-network-security-
texts-in-computer-science-5th-ed-2020-kizza-55026446

Guide To Computer Network Security Fourth Edition 4th Edition Joseph


Migga Kizza

https://ebookbell.com/product/guide-to-computer-network-security-
fourth-edition-4th-edition-joseph-migga-kizza-23686616

Guide To Computer Forensics And Investigations 4th Edition Bill Nelson

https://ebookbell.com/product/guide-to-computer-forensics-and-
investigations-4th-edition-bill-nelson-2371338
Guide To Computer Forensics And Investigations Standalone Book 6th
Edition Nelson

https://ebookbell.com/product/guide-to-computer-forensics-and-
investigations-standalone-book-6th-edition-nelson-34793068

Guide To Computer Network Security 3rd Edition Joseph Migga Kizza Auth

https://ebookbell.com/product/guide-to-computer-network-security-3rd-
edition-joseph-migga-kizza-auth-4971614

Guide To Computer Forensics And Investigations Processing Digital


Evidence Fifth Edition Nelson

https://ebookbell.com/product/guide-to-computer-forensics-and-
investigations-processing-digital-evidence-fifth-edition-
nelson-7162250

Guide To Computer Animation For Tv Games Multimedia And Web 1st


Edition Marcia Kuperberg

https://ebookbell.com/product/guide-to-computer-animation-for-tv-
games-multimedia-and-web-1st-edition-marcia-kuperberg-978606

Guide To Computer Network Security 6th Edition Joseph Migga Kizza

https://ebookbell.com/product/guide-to-computer-network-security-6th-
edition-joseph-migga-kizza-231928442
Undergraduate Topics in Computer Science

Bernard Goossens

Guide to Computer
Processor
Architecture
A RISC-V Approach,
with High-Level Synthesis
Undergraduate Topics in Computer
Science

Series Editor
Ian Mackie, University of Sussex, Brighton, UK

Advisory Editors
Samson Abramsky , Department of Computer Science, University of Oxford,
Oxford, UK
Chris Hankin , Department of Computing, Imperial College London, London, UK
Mike Hinchey , Lero—The Irish Software Research Centre, University of
Limerick, Limerick, Ireland
Dexter C. Kozen, Department of Computer Science, Cornell University, Ithaca,
NY, USA
Andrew Pitts , Department of Computer Science and Technology, University of
Cambridge, Cambridge, UK
Hanne Riis Nielson , Department of Applied Mathematics and Computer Science,
Technical University of Denmark, Kongens Lyngby, Denmark
Steven S. Skiena, Department of Computer Science, Stony Brook University, Stony
Brook, NY, USA
Iain Stewart , Department of Computer Science, Durham University, Durham,
UK
Joseph Migga Kizza, College of Engineering and Computer Science,
The University of Tennessee-Chattanooga, Chattanooga, TN, USA
‘Undergraduate Topics in Computer Science’ (UTiCS) delivers high-quality
instructional content for undergraduates studying in all areas of computing and
information science. From core foundational and theoretical material to final-year
topics and applications, UTiCS books take a fresh, concise, and modern approach
and are ideal for self-study or for a one- or two-semester course. The texts are all
authored by established experts in their fields, reviewed by an international advisory
board, and contain numerous examples and problems, many of which include fully
worked solutions.
The UTiCS concept relies on high-quality, concise books in softback format, and
generally a maximum of 275–300 pages. For undergraduate textbooks that are
likely to be longer, more expository, Springer continues to offer the highly regarded
Texts in Computer Science series, to which we refer potential authors.
Bernard Goossens

Guide to Computer
Processor Architecture
A RISC-V Approach, with High-Level
Synthesis

123
Bernard Goossens
Université de Perpignan
Perpignan, France

ISSN 1863-7310 ISSN 2197-1781 (electronic)


Undergraduate Topics in Computer Science
ISBN 978-3-031-18022-4 ISBN 978-3-031-18023-1 (eBook)
https://doi.org/10.1007/978-3-031-18023-1
© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature
Switzerland AG 2023
This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether
the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and
transmission or information storage and retrieval, electronic adaptation, computer software, or by similar
or dissimilar methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this
publication does not imply, even in the absence of a specific statement, that such names are exempt from
the relevant protective laws and regulations and therefore free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this
book are believed to be true and accurate at the date of publication. Neither the publisher nor the
authors or the editors give a warranty, expressed or implied, with respect to the material contained
herein or for any errors or omissions that may have been made. The publisher remains neutral with regard
to jurisdictional claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
Preface

Processor Architecture: A Do-It-Yourself Approach

This book is a new textbook on processor architecture. What is new is not the topic,
even though actual multicore and multithreaded designs are depicted, but the way
processor architecture is presented.
This book can be related to the famous Douglas Comer textbook on Operating
System (OS) [1, 2]. As Douglas Comer did to present the design of an OS, I use a
DIY approach to present processor designs.
In his book, Douglas Comer builds a full OS from scratch, with C source code.
In the present book, I aim to make you build your own processors, also from scratch
and also with C source code.
All you need is a computer, an optional development board, and a set of freely
available softwares to transform C programs into equivalent FPGA implementa-
tions (field-programmable gate array).
If you don’t have a development board, you can still simulate the processors
presented in the book though.
In the 70s (of the twentieth century of course), it became possible for a single
person to build a full OS (Kenneth L. Thompson created Unix in 1970), and better
than that, to write a How-To book giving a complete recipe to implement a
Unix-like OS (Douglas Comer published Xinu in 1984).
Two improvements in computer hardware and software made it eventually
feasible: the availability of personal computers and the C programming language.
They give the full access to the hardware.
Nowadays, an FPGA plays the role of the personal computer of the 70s: It
gives access to the logic gates. The High-Level Synthesis tool (HLS) plays the role
of the C compiler of the 70s: It gives access to the FPGA through a high-level
language.

v
vi Preface

RISC-V Open-Source Processor Designs

The Douglas Comer book explained how to build an OS using a self-made example
named Xinu. Even though Xinu was claimed not to be Unix (Xinu is a recursive
acronym meaning “Xinu Is Not Unix”), it would behave very likely, giving the reader
and implementer the opportunity to compare his/her own realization to the Unix
reference.
In the same idea, I have chosen a reference processor to be able to compare the
FPGA-based processor proposed in the book to real RISC-V industrial products.
RISC-V is an open-source Instruction Set Architecture (ISA), which means that
you can build a RISC-V processor, use it, and even sell it, without the permission of
any computer constructor. It would not be so for Intel’s X86 or ARM’s v7 or v8.
Moreover, RISC-V defines multiple gigogne ISA subsets. A processor may
implement any level of the matriochka organization of the ISA.
In this book, you will implement one of the most basic subsets, namely RV32I
(a set of machine instructions to compute on 32-bits integer words). But you will
know enough to be able to expand your processor to 64-bits words, to add a
floating-point computation subset and many more, according to the RISC-V
specification [3].
Moreover, the subset you will be implementing is enough to boot an OS like
Linux (which is not part of this book though).

A Very Practical Introduction to Computer Architecture


for Undergraduate Students

This book is also a very practical introduction to computer architecture. It can be


seen as an application of more complete reference books of the domain (see for
example the most recent editions of the famous books on computer architecture by
J. L. Hennessy and D. A. Patterson [4, 5]).
Along the chapters, you will implement different processor organizations:
• Basic (e.g., Intel 4004. The Intel 4004 was the first microprocessor introduced in
1971, i.e., the first processor to fit in a single integrated circuit.) [6, 7].
• Slightly pipelined (e.g., RISC-I. The RISC-I processor was the first pipelined
microprocessor, introducing the Reduced Instruction Set Computer or RISC
concept in 1980.) [8].
• Moderately pipelined (e.g., MIPS. The MIPS or microprocessor without Inter-
locked Pipeline Stages was a concurrent of RISC-I, adding techniques to better
fill the pipeline.) [9].
• Pipeline for multicycle operations (or multicycle pipeline). This is an
enhancement of the pipeline to handle multiple cycle memory accesses, integer
multiplication and division, or floating-point operations.
Preface vii

• Multiple threads (e.g., SMT. The SMT or simultaneous multithreading is an


enhancement to share the pipeline between multiple threads and so, fill it better.
This technique is also known as Hyper Threading, as named by Intel.) [10].
• Multiple cores (e.g., IBM Power-4. The Power-4 was the first multicore
processor, introduced in 2001. It had two cores.) [11].
Even though you stay at the simulation level because you do not have a
development board, the designs have been tested on an FPGA and they respect
hardware constraints.

A Teaching Tool for Instructors With a GitHub Support

All the processors designed in this book are provided as open-source projects
(either to build the simulation only version or the full FPGA-based projects to be
tested on a Xilinx-based development board) available in the goossens-book-
ip-projects repository of the https://github.com/goossens-springer github.
A full chapter of the book is devoted to the installation of the RISC-V tools (gnu
toolchain including the RISC-V cross-compiler, spike simulator, gdb debugger, and
the RISC-V-tests official test and benchmarks suite provided by the RISC-V
international organization (https://riscv.org/).
The implementations proposed in the book are compared from a performance
perspective, applying the famous Hennessy–Patterson “quantitative approach” [4].
The book presents an adaptation of a benchmark suite to the development board
no-OS environment.
The same benchmark suite is used throughout the book to test and compare the
performance of the successive designs. These comparisons highlight the cycle per
instruction (CPI) term in the processor performance equation.
Such comparisons based on really implemented softcores are more convincing
for students than similar evaluations relying on simulation with no real hardware
constraints.
The different microarchitectures described in the book introduce the general
concepts related to pipelining: branch delay and cancelation, bypassing in-flight
values, load delay, multicycle operators, and more generally, filling the pipeline
stages.
The chapter devoted to the RISC-V RV32I is also an introduction to assembly
programming. RISC-V codes are obtained from the compilation of C patterns
(expressions, tests, loops, and functions) and analyzed.
Throughout the book, some exercises are proposed which can serve as semester
projects, like extending the given implementations to the RISC-V M or F ISA
subsets.
viii Preface

Such a box signals some experimentation the reader can do from the
resources available in the goossens-book-ip-projects/2022.1 folder in the
https://github.com/goossens-springer github.
The Vitis_HLS projects are pre-built (you just need to select the testbench
file you want to use for your IP simulation) (IP means Intellectual Property,
i.e., your component).
The Vivado projects are also pre-built with drivers to directly test your IPs
on the development board. The expected results are in the book.

A Practical and Detailed Introduction to High-Level Synthesis


and to RISC-V for FPGA Engineers

The book is a very detailed introduction to High-Level Synthesis. HLS will cer-
tainly become the standard way to produce RTL, progressively replacing
Verilog/VHDL, as in the 50s and 60s, high-level languages progressively replaced
the assembly language.
Chapter 2 of the book presents the Xilinx HLS environment in the Vitis tool
suite. Based on an IP implementation example, it travels through all the steps from
HLS to the Xilinx IP integrator Vivado and the Xilinx Vitis IDE (Integrated Design
Environment) to upload the bitstream on the FPGA.
The book explains how to implement, simulate, synthesize, run on FPGA, and
even debug HLS softcore projects without the need to go down to Verilog/VHDL
or chronograms. HLS is today a matured tool which gives engineers the ability to
quickly develop FPGA prototypes. The development of a RISC-V processor in
HLS is a one engineer-month duty, when implementing an ARM processor in
VHDL was more like a year job, thanks to HLS and thanks to the simplicity of the
RV32I instruction nucleus in the RISC-V ISA.
The book explains the major pragmas used by the HLS synthesizer (ARRAY
PARTITION, DEPENDENCE, INTERFACE, INLINE, LATENCY, PIPELINE,
UNROLL).
Part I of the book concerns individual IPs, and Part II is devoted to System-
on-Chips built from multiples core and memory IPs interconnected by an AXI
interconnection component.
The book is also an introduction to RISC-V. A full chapter is devoted to the
presentation of the RV32I ISA.
The market growth of RISC-V processors is already impressive in the domain of
embedded computing. The future of RISC-V might be the same as what was the
progression of Unix in the domain of operating systems. At least, the first steps are
comparable, with a no-constructor and open-source philosophy.
Preface ix

What the Book Does Not Contain

However, this book does not contain any implementation of the techniques found in
the most advanced processors, like superscalar execution, out-of-order execution,
speculation, branch prediction, or value prediction (however, these concepts are at
least defined).
The reason is that these microarchitectural features are too complex to fit in a
small FPGA like the one I used. For example, a cost-effective out-of-order design
requires a superscalar pipeline, an advanced branch predictor, and a hierarchical
memory altogether.
There is no implementation of advanced parallel management units like a shared
memory management (i.e., cache coherency) for the same reason.
The book does not include any implementation of caches or complex arithmetic
operators (multiplication, division, or floating-point unit). They can fit on the FPGA
(at least in a single core and single thread processor). They are left as an exercise for
the reader.

An Organization in Two Parts: Single Core Designs, Multiple


Core Designs

The book is divided into two parts and 14 chapters, including an introduction and a
conclusion. Part I, from Chaps. 1 to 10, is devoted to single core processors. Part II,
from Chaps. 11 to 14, presents some multicore implementations.
Chapter 1 is the introduction. It presents what an FPGA is and how HLS works
to transform a C program into a bitstream to configure the FPGA.
The two following chapters give the necessary indications to build the full
environment used in the book to develop the RISC-V processors.
Chapter 2 is related to the Xilinx Vitis FPGA tools (the Vitis_HLS FPGA
synthesizer, the Vivado FPGA integrator, and the Vitis IDE FPGA programmer).
Chapter 3 presents the RISC-V tools (the Gnu toolchain, the Spike simulator,
and the OpenOCD/gdb debugger), their installation, and the way to use them.
Chapter 4 presents the RISC-V architecture (more precisely, the RV32I ISA) and
the assembly language programming.
Chapter 5 shows the three main steps in building a processor: fetching, decoding,
and executing. The construction is incremental.
The general principles of HLS programming, in contrast to classic programming,
are explained in the first section of Chap. 5.
Chapter 6 completes chapter five with the addition of a data memory to fulfill the
first RISC-V processor IP. The implemented microarchitecture has the most simple
non-pipelined organization.
x Preface

Chapter 7 explains how you should test your processor IPs, using small RISC-V
codes to check each instruction format individually, also using the official
RISC-V-tests pieces of codes provided by the RISC-V organization. Eventually,
you should run some benchmarks to test your IP behavior on real applications.
I have combined the RISC-V-tests and the mibench benchmarks [12] to form a
suite which is used both to test and to compare the different implementations
throughout the book.
At the end of Chap. 7, you will find many hints on how to debug HLS codes and
IPs on the FPGA.
Chapter 8 describes pipelined microarchitectures, starting with a two-stage
pipeline and ending with a four-stage pipeline.
Chapter 9 pushes pipelining a step further to handle multicycle instructions. The
multicycle pipeline RISC-V IP has six stages. It is a necessary improvement in the
pipeline organization to run RISC-V multicycle instructions like the ones found in
the F and D floating-point extensions, or to implement cache levels building
hierarchized memories.
Chapter 10 presents a multiple hart IP (a hart is a HARdware Thread). Mul-
tithreading is a technique to help filling the pipeline and improve the processor
throughput. The implemented IP is able to run from two to eight threads
simultaneously.
Chapter 11 starts the second part. It describes the AXI interconnection system
and how multiple IPs can be connected together in Vivado and exchange data on
the FPGA.
Chapter 12 presents a multicore IP based on the multicycle six-stage pipeline.
The IP can host from two to eight cores running either independent applications or
parallelized ones.
Chapter 13 shows a multicore multihart IP. The IP can host two cores with four
harts each or four cores with two harts each.
Chapter 14 concludes by showing how you can use your RISC-V processor
implementations to play with your development board, lighting LEDs (Light-
Emitting Diode) as push buttons are pressed.
An acronym section is added in the Frontmatter to give the meaning of the
abbreviations used in the book.
A few exercises are proposed in the book (with no given solution) which should
be viewed by professors as project or laboratory suggestions.

Perpignan, France Bernard Goossens

References

1. Comer, D.: Operating System Design: The Xinu Approach. Prentice Hall International,
Englewood Cliffs, New Jersey (1984)
2. Comer, D.: Operating System Design: The Xinu Approach, Second Edition. Chapman and
Hall, CRC Press (2015)
Preface xi

3. https://riscv.org/specifications/isa-spec-pdf/
4. Hennessy, J.L., Patterson, D.A.: Computer Architecture, A quantitative Approach, 6th edition,
Morgan Kaufmann (2017)
5. Hennessy, J.L., Patterson, D.A.: Computer Organization and Design: The Hardware/Software
Interface, 6th edition, Morgan Kaufmann (2020)
6. Faggin, F.: The Birth of the Microprocessor. Byte, Vol.17, No.3, pp. 145–150 (1992)
7. Faggin, F.: The Making of the First Microprocessor. IEEE Solid-State Circuits Magazine,
(2009) https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=4776530
8. Patterson, D., Ditzel, D.: The Case for the Reduced Instruction Set Computer.
ACM SIGARCH Computer Architecture News, Vol.8, No.6, pp. 5–33 (1980)
9. Chow, P., Horowitz, M.: Architectural tradeoffs in the design of MIPS-X, ISCA’87 (1987)
10. Tullsen, D.M., Eggers, S.J., Levy, H.M.: Simultaneous multithreading: Maximizing on-chip
parallelism. 22nd Annual International Symposium on Computer Architecture. IEEE.
pp. 392–403 (1995).
11. Tendler, J. M., Dodson, J. S., Fields Jr., J. S., Le, H., Sinharoy, B.: POWER4 system
microarchitecture, IBM Journal of Research and Development, Vol.46, No 1, pp. 5–26 (2002)
12. https://vhosts.eecs.umich.edu/mibench/
Acknowledgements

I want to thank my reviewers for the invaluable selfless work they have done,
reading and correcting an always changing manuscript. They were all great!
So, the only order of presentation which is acceptable is the alphabetical one
(based on the last name). If you find some mistakes in the textbook, they are all
mine of course.
Yves Benhamou is a computer engineer in a domain not at all related to pro-
cessor architecture. I asked Yves to be the neophyte reader, going through the steps
of the first constructions like installing the softwares and make the first example run
on the Pynq-Z2 board I had given him. Moreover, Yves mainly works on Windows
and he had to start with a fresh new Ubuntu installation, so he could give me a lot of
very important remarks for the reader in the same situation, with missing
commands, files, and needed environment preparations. Yves, I hope you had fun
discovering FPGA, softcore designs, and HLS! On my side, I was very happy to see
that again you were eager to make it run!
Johannes Schoder is a Ph.D. student at Friedrich Schiller University, Jena,
Germany. He contacted me in June 2021 to ask for a free access to my
“Out-of-Order RISC-V Core Developed with HLS” which I had presented at the
second RISCV-week in Paris in October 2019. I was already writing the book, but it
was still at a very preliminary stage. Later, after Johannes had been through the
code of what is in the book the “multicycle_pipeline_ip”, I proposed him to review
a part of the textbook. He accepted enthusiastically. Johannes, you did a great job!
Arnaud Tisserand is “Directeur de Recherche” in the French CNRS (Centre
National de la Recherche Scientifique). He is an expert in architecture, focusing his
research work on chip accelerators in arithmetic and cryptography. I asked him to
review the FPGA part of the textbook. It turns out that Arnaud wants to use HLS
more intensely for his future designs (mainly because HLS produces prototypes
very quickly; this speed in production is invaluable for PhD students), so he pro-
posed to review a bit more stuffs and even try some of the proposed implemen-
tations. Thank you so much Arnaud for your help!
I also want to thank the XUP (Xilinx University Program) and more specifically,
his manager Cathal Mac Cabe. Cathal is an engineer at Xilinx/AMD. I have been in
contact with him through mail, as all the members of the XUP are, asking him many
questions on HLS and Vitis. Cathal does a great job at XUP. He is very helpful to

xiii
xiv Acknowledgements

all the worldwide academic community of Xilinx product users. The XUP program
is crucial for many little research teams like mine. When a professor has the project
to teach FPGAs or HLS to undergraduate students, he/she must convince his/her
colleagues that devoting a few thousand of euros on the yearly budget to buy
development boards is worth the spending. This is where XUP plays a major role.
By providing free boards, it helps the pedagogical teams to set preliminary
experimentations which can serve as persuasive arguments for the faculty members
who are not in the computer science domain. So, thank you again Cathal for the
great supporting job (and for the free boards)!
There are many more people who directly or indirectly influenced the textbook.
Of course, my colleagues of the LIRMM laboratory (Laboratoire d’Informatique,
Robotique et Microélectronique de Montpellier) and more particularly the actual
members of the DALI team (Digits, Architecture et Logiciels Informatiques) in
Perpignan: Dushan Bikov, Matthieu Carrère, Youssef Fakhreddine, Philippe Lan-
glois, Kenelm Louetsi, Christophe Nègre, David Parello, Guillaume Révy, and
Vincent Zucca.
Last but not least, I thank my wife, Urszula, for her every day support. It is not
easy for the family to accept sacrificing so much time, including weekends and
holidays, to this kind of long ongoing project. Urszula, you took a so important part
in the realization of this book!
Contents

Part I Single Core Processors


1 Introduction: What Is an FPGA, What Is High-Level Synthesis
or HLS? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. 3
1.1 What Hardware to Put in an FPGA? . . . . . . . . . . . . . . . . . . .. 3
1.2 Look-Up Table (LUT): A Piece of Hardware to Store
a Truth Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Combining LUTs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4 The Structure of an FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5 Programming an FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE
Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..... 13
2.1 Getting the Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . ..... 13
2.2 Getting the Software: The Xilinx Vitis Tool . . . . . . . . . . ..... 14
2.3 Installing the Development Board Definition in the Vitis
Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4 Installing the Book Resources . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5 Using the Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5.1 Creating a Project . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5.2 Creating an IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.5.3 Simulating an IP . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.5.4 Synthesizing an IP . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.6 Creating a Design with Vivado . . . . . . . . . . . . . . . . . . . . . . . . 35
2.7 Loading the IP and Running the FPGA with Vitis . . . . . . . . . . 68
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3 Installing and Using the RISC-V Tools . . . . . . . . . . . . . . . . . . . . . . 87
3.1 Installing a RISC-V Toolchain and an Emulator/Debugger . . . . 87
3.1.1 Installing the RISC-V Toolchain . . . . . . . . . . . . . . . . 88
3.1.2 The Spike Simulator . . . . . . . . . . . . . . . . . . . . . . . . 89
3.1.3 Building Executable Code For the RISC-V FPGA
Based Processors . . . . . . . . . . . . . . . . . . . . . . . . ... 93

xv
xvi Contents

3.2 Debugging With Gdb . . . . . . . . . . . . . . . . . . . . . . ......... 95


3.2.1 Installing Gdb . . . . . . . . . . . . . . . . . . . . ......... 95
3.2.2 Installing OpenOCD . . . . . . . . . . . . . . . ......... 96
3.2.3 Defining a Linker Script File Compatible
With the Spike Simulated Machine . . . . . ......... 96
3.2.4 Using the Linker Script File to Compile . ......... 96
3.2.5 Defining a Spike Configuration File
for OpenOCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.2.6 Connecting Spike, OpenOCD, and Gdb . . . . . . . . . 97
3.2.7 A Debugging Session . . . . . . . . . . . . . . . . . . . . . . . . 98
3.3 Debugging a Complex Code with Gdb . . . . . . . . . . . . . . . . . . 100
4 The RISC-V Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.1 The RISC-V Instruction Set Architecture . . . . . . . . . . . . . . . . . 105
4.1.1 The RV32I Registers and the RISC-V Application
Binary Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.1.2 The RV32I Instructions . . . . . . . . . . . . . . . . . . . . . . 107
4.1.3 The RV32I Instruction Formats . . . . . . . . . . . . . . . . . 109
4.1.4 The Assembler Syntax . . . . . . . . . . . . . . . . . . . . . . . 114
4.2 Code Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
4.2.1 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
4.2.2 Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
4.2.3 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2.4 Function Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5 Building a Fetching, Decoding, and Executing Processor . . . . . . . . 123
5.1 General Programming Concepts for HLS . . . . . . . . . . . . . . . . . 123
5.1.1 The Critical Path . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.1.2 Computing More to Reduce the Critical Path . . . . . . . 125
5.1.3 Parallel Execution . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.2 The Fundamental Execution Time Equation for a Processor . . . 126
5.3 First Step: Build the Path to Update PC . . . . . . . . . . . . . . . . . 127
5.3.1 The Fetching_ip Design . . . . . . . . . . . . . . . . . . . . . 127
5.3.2 The Fetching_ip Top Function . . . . . . . . . . . . . . . . . 128
5.3.3 The Fetch Function . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.3.4 The Execute Function . . . . . . . . . . . . . . . . . . . . . . . 135
5.3.5 The IP Running Condition . . . . . . . . . . . . . . . . . . . . 136
5.3.6 The IP Simulation with the Testbench . . . . . . . . . . . . 136
5.3.7 The Simulation Prints . . . . . . . . . . . . . . . . . . . . . . . . 137
5.3.8 The Fetching_ip Synthesis . . . . . . . . . . . . . . . . . . . . 137
5.3.9 The Z1_fetching_ip Vivado Project . . . . . . . . . . . . . 140
5.3.10 The Helloworld.c Program to Drive the Fetching_
ip on the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Contents xvii

5.4 Second Step: Add a Bit of Decoding to Compute


the Next PC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
5.4.1 The RISC-V Instruction Encoding . . . . . . . . . . . . . . . 143
5.4.2 The Fetching_decoding_ip . . . . . . . . . . . . . . . . . . . 146
5.4.3 The Fetching_decoding_ip.h File . . . . . . . . . . . . . . 148
5.4.4 The Fetch Function and the Running_cond_
update Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
5.4.5 The Decode Function . . . . . . . . . . . . . . . . . . . . . . . 151
5.4.6 The Instruction Execution (Computing Next PC) . . . . 154
5.4.7 The Fetching_decoding_ip Simulation with
the Testbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.4.8 The Fetching_decoding_ip Synthesis . . . . . . . . . . . 156
5.4.9 The Z1_fetching_decoding_ip Vivado Project . . . . . 158
5.4.10 The Helloworld.c Code to Drive the Fetching_
decoding_ip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5.5 Third Step: Filling the Execute Stage to Build the Register
Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5.5.1 A Fetching, Decoding, and Executing IP: The Fde_
ip Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
5.5.2 Two Debugging Tools: Register File Dump
and Code Disassembling . . . . . . . . . . . . . . . . . . . . . . 162
5.5.3 The IP Running Condition . . . . . . . . . . . . . . . . . . . . 163
5.5.4 The Fde_ip.h File . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.5.5 The Decode Function and the Execute Function . . . 165
5.5.6 The Register File . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
5.5.7 Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
5.5.8 Simulating the Fde_ip With the Testbench . . . . . . . . 172
5.5.9 The Fde_ip Synthesis . . . . . . . . . . . . . . . . . . . . . . . 178
5.5.10 The Z1_fde_ip Vivado Project . . . . . . . . . . . . . . . . . 179
5.5.11 The Helloworld.c Program to Drive the Fde_ip
on the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6 Building a RISC-V Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.1 The Rv32i_npp_ip Top Function . . . . . . . . . . . . . . . . . . . . . . 183
6.1.1 The Rv32i_npp_ip Top Function Prototype,
Local Declarations, and Initializations . . . . . . . . . . . . 183
6.1.2 The Do ... While Loop . . . . . . . . . . . . . . . . . . . . . . . 185
6.2 Decoding Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.3 Data Memory Accesses: Alignment and Endianness . . . . . . . . . 186
6.4 The Execute Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
6.4.1 The Computation of the Accessed Address . . . . . . . . 188
6.4.2 The Compute_result Function . . . . . . . . . . . . . . . . . 188
6.4.3 The Mem_store Function . . . . . . . . . . . . . . . . . . . . 189
xviii Contents

6.4.4 The Mem_load Function . . . . . . . . . . . . . . . . . . . . . 191


6.4.5 The Write_reg Function . . . . . . . . . . . . . . . . . . . . . . 192
6.5 Simulating the Rv32i_npp_ip With the Testbench . . . . . . . . . . 193
6.6 Synthesis of the Rv32i_npp_ip . . . . . . . . . . . . . . . . . . . . . . . . 198
6.7 The Z1_rv32i_npp_ip Vivado Project . . . . . . . . . . . . . . . . . . . 198
6.8 The Helloworld.c Program to Drive the Rv32i_npp_ip
on the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
7 Testing Your RISC-V Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
7.1 Testing the Rv32i_npp_ip Processor with my Test
Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
7.2 More Testing with the Official Riscv-Tests . . . . . . . . . . . . . . . 202
7.2.1 Running the Riscv-Tests With Spike . . . . . . . . . . . . 202
7.2.2 The Riscv-Tests Structure . . . . . . . . . . . . . . . . . . . . 203
7.2.3 Adapting the Riscv-Tests Structure to the Vitis_
HLS Environment . . . . . . . . . . . . . . . . . . . . . . . . . . 206
7.2.4 Adding a _start.S Program to Glue All the Tests
Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
7.2.5 The Testbench to Simulate the Tests in Vitis_HLS . . . 209
7.2.6 Running the Riscv-Tests in the Vitis_HLS
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
7.2.7 Running the Tests on the FPGA . . . . . . . . . . . . . . . . 215
7.3 Running a Benchmark Suite on the Rv32i_npp_ip
Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
7.3.1 The Basicmath_small Benchmark From
the Mibench Suite . . . . . . . . . . . . . . . . . . . . . . . . . . 217
7.3.2 Running the Basicmath_Small Benchmark
on the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
7.3.3 The Other Benchmarks of the Mibench Suite . . . . . . 225
7.3.4 The Mibench and Riscv-Tests Benchmarks
Execution Times on the Rv32i_npp_ip
Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
7.4 Proposed Exercises: The RISC-V M and F Instruction
Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
7.4.1 Adapt the Rv32i_npp_ip Design to the RISC-V
M Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
7.4.2 Adapt the Rv32i_npp_ip Design to the RISC-V
F Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
7.5 Debugging Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
7.5.1 Synthesis Is Not Simulation: You Can Disactivate
Some Parts of the Simulation . . . . . . . . . . . . . . . . . . 229
7.5.2 Infinite Simulation: Replace the “Do ... While”
Loop By a “For” Loop . . . . . . . . . . . . . . . . . . . . . . . 229
7.5.3 Frozen IP on the FPGA: Check Ap_int
and Ap_uint Variables . . . . . . . . . . . . . . . . . . . . . . . 229
Contents xix

7.5.4 Frozen IP on the FPGA: Check Computations


Inside #Ifndef __SYNTHESIS__ . . . . . . . . . . . . . . . 230
7.5.5 Frozen IP on the FPGA: Replace the “While
(!IsDone(...));” Loop By a “For” Loop . . . . . . . . . . . 230
7.5.6 Frozen IP on the FPGA: Reduce the RISC-V
Code Run . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
7.5.7 Non Deterministic Behaviour on the FPGA: Check
Initializations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
7.5.8 Debugging Prints Along the Run on the FPGA . . . . . 231
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
8 Building a Pipelined RISC-V Processor . . . . . . . . . . . . . . . . . . . . . 233
8.1 First Step: Control a Pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . 233
8.1.1 The Difference Between a Non-pipelined
and a Pipelined Microarchitecture . . . . . . . . . . . . . . . 233
8.1.2 The Inter-stage Connection Structures . . . . . . . . . . . . 235
8.1.3 The IP Top Function . . . . . . . . . . . . . . . . . . . . . . . . 236
8.1.4 Control Flow Instructions Handling
in the Pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
8.1.5 The Fetch_decode Pipeline Stage . . . . . . . . . . . . . . 239
8.1.6 The Execute_wb Pipeline Stage . . . . . . . . . . . . . . . . 240
8.1.7 The Simulation and Synthesis of the IP . . . . . . . . . . . 242
8.1.8 The Vivado Project Using the IP . . . . . . . . . . . . . . . . 243
8.1.9 The Execution of the Vivado Project
on the Development Board . . . . . . . . . . . . . . . . . . . . 243
8.1.10 Further Testing of the Simple_pipeline_ip . . . . . . . . 245
8.1.11 Comparison of the Non-pipelined Design
with the Pipelined One . . . . . . . . . . . . . . . . . . . . . . . 246
8.2 Second Step: Slice a Pipeline into Stages . . . . . . . . . . . . . . . . . 247
8.2.1 A 4-Stage Pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . 247
8.2.2 The Inter-stage Connections . . . . . . . . . . . . . . . . . . . 247
8.2.3 The Decode Part of the Fetch_decode Stage . . . . . . 249
8.2.4 The IP Top Function . . . . . . . . . . . . . . . . . . . . . . . . 249
8.2.5 The Bypass Mechanism in the Execute Stage . . . . . . . 251
8.2.6 The Execute Stage . . . . . . . . . . . . . . . . . . . . . . . . . . 253
8.2.7 Memory Load Hazards . . . . . . . . . . . . . . . . . . . . . . . 257
8.2.8 The Memory Access Stage . . . . . . . . . . . . . . . . . . . . 258
8.2.9 The Writeback Stage . . . . . . . . . . . . . . . . . . . . . . . . 259
8.2.10 The Testbench Function . . . . . . . . . . . . . . . . . . . . . . 260
8.2.11 The IP Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
8.2.12 The Vivado Project . . . . . . . . . . . . . . . . . . . . . . . . . 261
8.2.13 The Execution of the Vivado Project
on the Development Board . . . . . . . . . . . . . . . . . . . . 262
8.2.14 Further Testing of the Rv32i_pp_ip . . . . . . . . . . . . . 264
xx Contents

8.3 The Comparison of the 2-Stage Pipeline with the 4-Stage


One . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
9 Building a RISC-V Processor with a Multicycle Pipeline . . . . . . . . 267
9.1 The Difference Between a Pipeline and a Multicycle
Pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
9.1.1 The Wait Signal to Freeze Stages . . . . . . . . . . . . . . . 267
9.1.2 The Valid Input and Output Bits . . . . . . . . . . . . . . . . 268
9.1.3 Fetching and Computing the Next PC . . . . . . . . . . . . 269
9.1.4 The Safe Structure of a Multicycle Stage . . . . . . . . . . 270
9.1.5 Multiple Multicycle Stages . . . . . . . . . . . . . . . . . . . . 270
9.2 The IP Top Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
9.3 The Pipeline Stages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
9.3.1 The Fetch Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
9.3.2 The Decode Stage . . . . . . . . . . . . . . . . . . . . . . . . . . 277
9.3.3 The Issue Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
9.3.4 The Execute Stage . . . . . . . . . . . . . . . . . . . . . . . . . . 285
9.3.5 The Memory Access Stage . . . . . . . . . . . . . . . . . . . . 289
9.3.6 The Writeback Stage . . . . . . . . . . . . . . . . . . . . . . . . 291
9.4 Simulating, Synthesizing, and Running the IP . . . . . . . . . . . . . 292
9.4.1 Simulating and Synthesizing the IP . . . . . . . . . . . . . . 292
9.4.2 The Vivado Project and the Implementation
Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
9.4.3 Running the IP on the Development Board . . . . . . . . 293
9.4.4 Further Testing of the Multicycle_pipeline_ip . . . . . . 295
9.5 Comparing the Multicycle Pipeline to the 4-Stage Pipeline . . . . 295
9.6 Proposed Exercise: Reduce II to 1 . . . . . . . . . . . . . . . . . . . . . . 297
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
10 Building a RISC-V Processor with a Multiple Hart Pipeline . . . . . 301
10.1 Handling Multiple Threads Simultaneously with a Multiple
Hart Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
10.2 A Multiple Hart Memory Model . . . . . . . . . . . . . . . . . . . . . . . 303
10.3 The Multihart Pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
10.3.1 The Number of Harts . . . . . . . . . . . . . . . . . . . . . . . . 307
10.3.2 The Multihart Stage States . . . . . . . . . . . . . . . . . . . . 307
10.3.3 The Occupation Arrays . . . . . . . . . . . . . . . . . . . . . . . 311
10.3.4 The Multihart_ip Top Function . . . . . . . . . . . . . . . . . 312
10.3.5 The New_cycle Function to Copy the _to_
Structures Into the _from_ Ones . . . . . . . . . . . . . . . . 319
10.3.6 The Multihart Fetch Stage . . . . . . . . . . . . . . . . . . . . . 320
10.3.7 The Decode Stage . . . . . . . . . . . . . . . . . . . . . . . . . . 323
10.3.8 The Issue Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
10.3.9 The Execute Stage . . . . . . . . . . . . . . . . . . . . . . . . . . 327
Contents xxi

10.3.10 The Memory Access Stage . . . . . . . . . . . . . . . . . . . . 328


10.3.11 The Writeback Stage . . . . . . . . . . . . . . . . . . . . . . . . 332
10.3.12 The Lock_unlock_update Function . . . . . . . . . . . . . 334
10.3.13 The Running_cond_update Function . . . . . . . . . . . 335
10.4 Simulating the Multihart_ip . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
10.4.1 Filling Harts with Independent Codes . . . . . . . . . . . . 336
10.4.2 Filling Harts with a Parallelized Code . . . . . . . . . . . . 337
10.5 Synthesizing the IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
10.6 The Vivado Project and the Implementation Report . . . . . . . . . 342
10.7 Running the Multihart_ip on the Development Board . . . . . . . . 345
10.7.1 Running Independent Codes . . . . . . . . . . . . . . . . . . . 345
10.7.2 Running a Parallelized Application . . . . . . . . . . . . . . 346
10.7.3 Further Testing of the Multihart_ip . . . . . . . . . . . . . . 348
10.8 Comparing the Multihart_ip to the 4-stage Pipeline . . . . . . . . . 348
10.8.1 Two Harts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
10.8.2 Four Harts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
10.8.3 Eight Harts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351

Part II Multiple Core Processors


11 Connecting IPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
11.1 The AXI Interconnection System . . . . . . . . . . . . . . . . . . . . . . . 355
11.2 The Non Pipelined RISC-V Processor with External Memory
IPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
11.2.1 The Top Function with a Bram Interface . . . . . . . . . . 357
11.2.2 The IP Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
11.2.3 The Vivado Project . . . . . . . . . . . . . . . . . . . . . . . . . 358
11.2.4 Running the IP on the Development Board . . . . . . . . 363
11.3 Connecting Multiple CPUs and Multiple RAMs Through
an AXI Interconnect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
11.3.1 The Multiple IPs Design . . . . . . . . . . . . . . . . . . . . . . 365
11.3.2 The CPU Top Function . . . . . . . . . . . . . . . . . . . . . . 365
11.3.3 The CPU Header File and the Testbench Code . . . . . 366
11.4 Simulating, Synthesizing, and Running a Multiple IP
Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
11.4.1 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
11.4.2 Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
11.4.3 The Vivado Project . . . . . . . . . . . . . . . . . . . . . . . . . 369
11.4.4 Running the Multiple IP Design . . . . . . . . . . . . . . . . 375
12 A Multicore RISC-V Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
12.1 An Adaptation of the Multicycle_pipeline_ip to Multicore . . . . 377
12.1.1 Adding an IP Number to the Top Function
Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
xxii Contents

12.1.2 The IP Top Function Declarations . . . . . . . . . . . . . . . 379


12.1.3 The IP Top Function Initializations . . . . . . . . . . . . . . 380
12.1.4 The IP Top Function Main Loop . . . . . . . . . . . . . . . . 381
12.1.5 The Register File Initialization . . . . . . . . . . . . . . . . . 382
12.1.6 The Memory Access . . . . . . . . . . . . . . . . . . . . . . . . . 382
12.2 Simulating the IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
12.2.1 Simulating Independent Programs on the Different
IPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
12.2.2 Simulating a Parallelized Program . . . . . . . . . . . . . . . 389
12.3 Synthesizing the IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
12.4 The Vivado Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
12.5 Running the IPs on the Development Board . . . . . . . . . . . . . . . 394
12.5.1 Running Independent Programs . . . . . . . . . . . . . . . . . 395
12.5.2 Running a Parallelized Program . . . . . . . . . . . . . . . . 397
12.6 Evaluating the Parallelism Efficiency of the Multicore IP . . . . . 398
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
13 A Multicore RISC-V Processor with Multihart Cores . . . . . . . . . . . 401
13.1 An Adaptation of the Multihart_ip to Multicore . . . . . . . . . . . . 401
13.1.1 The Multicore Multihart IP Top Function Prototype
and Local Declarations . . . . . . . . . . . . . . . . . . . . . . . 402
13.1.2 The Data Memory Accesses . . . . . . . . . . . . . . . . . . . 404
13.2 Simulating the IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
13.2.1 Simulating Independent Programs . . . . . . . . . . . . . . . 409
13.2.2 Simulating a Parallelized Program . . . . . . . . . . . . . . . 412
13.2.3 Synthesizing the IP . . . . . . . . . . . . . . . . . . . . . . . . . . 416
13.2.4 The Vivado Project . . . . . . . . . . . . . . . . . . . . . . . . . 416
13.3 Running the IP on the Development Board . . . . . . . . . . . . . . . 417
13.3.1 Running Independent Programs . . . . . . . . . . . . . . . . . 417
13.3.2 Running a Parallelized Program . . . . . . . . . . . . . . . . 420
13.4 Evaluating the Parallelism Efficiency of the Multicore
Multihart IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
14 Conclusion: Playing with the Pynq-Z1/Z2 Development Board
Leds and Push Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
14.1 A Zynq Design to Access Buttons and Leds
on the Development Board . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
14.2 A Design to Access Buttons and Leds from a RISC-V
Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
14.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Acronyms

The given definitions are all taken from online Wikipedia. The “In short” versions
are all mine. They intend to be less general but a bit more practical.
ABI Application Binary Interface: an interface between two binary program
modules. In short, an ABI fixes a general frame to build applications
from the processor architecture.
ALU Arithmetic and Logic Unit: A combinational digital electronic circuit that
performs arithmetic and bitwise operations on integer binary numbers.
AXI Advanced eXtensible Interface: a parallel high-performance,
synchronous, high-frequency, multi-master, multi-slave communication
interface, mainly designed for on-chip communication. In short, an IP
interconnection system.
CLB Configurable Logic Block: A fundamental building block of field-
programmable gate array (FPGA) technology. Logic blocks can be
configured by the engineer to provide reconfigurable logic gates. In
short, the elementary building structure in FPGAs.
CPU Central Processing Unit: The electronic circuitry within a computer that
executes instructions that make up a computer program. In short, the
processor core.
ELF Executable and Linkable Format: It is a common standard file format for
executable files, object code, shared libraries, and core dumps. In 1999, it
was chosen as the standard binary file format for Unix and Unix-like
systems on x86 processors by the 86open project. By design, the ELF
format is flexible, extensible, and cross-platform. For instance, it
supports different endiannesses and address sizes, so it does not exclude
any particular central processing unit (CPU) or Instruction Set Archi-
tecture. This has allowed it to be adopted by many different operating
systems on many different hardware platforms. In short, the loadable
format of all the executable files in Linux or MacOS systems.
FPGA Field-Programmable Gate Array: An integrated circuit designed to be
configured by a customer or a designer after manufacturing. In short, it is
a programmable chip.

xxiii
xxiv Acronyms

GUI Graphical User Interface: A form of user interface that allows users to
interact with electronic devices through graphical icons and audio
indicator such as primary notation, instead of text-based user interfaces,
typed command labels or text navigation.
HDL Hardware Description Language: A specialized computer language used
to describe the structure and behavior of electronic circuits, and most
commonly, digital logic circuits. In short: an HDL is to integrated
circuits what a programming language is to algorithms.
HLS High-Level Synthesis: An automated design process that interprets an
algorithmic description of a desired behavior and creates digital hardware
that implements that behavior. In short, implementing hardware with a
program written in a high-level language like C or C++.
IP Intellectual Property: A category of property that includes intangible
creations of the human intellect. In short, a component.
ISA Instruction Set Architecture: An abstract model of a computer. It is also
referred to as architecture or computer architecture. A realization of an
ISA, such as a central processing unit (CPU), is called an implemen-
tation. In short, a processor architecture is defined by an ISA, i.e., a
machine language (or assembly language).
LAB Logic Array Block: see the CLB entry. The LAB is for the Altera FPGA
constructor what the CLB is for the Xilinx FPGA constructor.
LUT Lookup Table: An array that replaces runtime computation with a
simpler array indexing operation. An n-bit lookup table implements any
n
of the 22 Boolean functions of n variables. In an FPGA, a 6-bit LUT is a
64-bits addressable table, which is addressed with a 6-bit word built from
the Boolean values of six variables. The addressed bit gives the Boolean
value of the function for the input combination forming the address.
OoO Out-of-Order: A paradigm used in most high-performance central
processing units to make use of instruction cycles that would otherwise
be wasted. In short, a hardware organization to run instructions in their
producer to consumer dependencies.
OS Operating System: A system software that manages computer hardware,
software resources, and provides common services for computer
programs. In short, Linux, Windows, or MacOS.
PCB Printed Circuit Board: A printed circuit board (PCB) mechanically
supports and electrically connects electrical or electronic components
using conductive tracks, pads, and other features etched from one or
more sheet layers of copper laminated onto and/or between sheet layers
of a non-conductive substrate. In short, your development board.
RAM Random Access Memory: A form of computer memory that can be read
and changed in any order, typically used to store working data and
machine code. In short, the processor’s main memory.
RAW Read After Write dependency (or true dependency): An instruction refers
to a result that has not yet been calculated or retrieved.
Acronyms xxv

RTL Register Transfer Level: A design abstraction which models a syn-


chronous digital circuit in terms of the flow of digital signals (data)
between hardware registers, and the logical operations performed on
those signals. In short, it is the description of the behavior of a circuit in
terms of gates or VHDL/Verilog program.
USB Universal Serial Bus: An industry standard that establishes specifications
for cables, connectors, and protocols for connection, communication, and
power supply (interfacing) between computers, peripherals, and other
computers. In short: an interface to connect low- or medium-speed
peripherals to the computer.
Verilog Verilog, standardized as IEEE 1364: A hardware description language
(HDL) used to model electronic systems. It is most commonly used in
the design and verification of digital circuits at the register-transfer level
of abstraction. In short: one of the two mostly used HDL, with VHDL.
VHDL VHSIC Hardware Description Language: A hardware description
language (HDL) that can model the behavior and structure of digital
systems at multiple levels of abstraction, ranging from the system level
down to that of logic gates, for design entry, documentation, and
verification purposes. In short: VHDL is to integrated circuits what C is
to algorithms.
VHSIC Very High-Speed Integrated Circuit Program: A United States Depart-
ment of Defense (DOD) research program that ran from 1980 to 1990. Its
mission was to research and develop very high-speed integrated circuits
for the United States Armed Forces.
Part I
Single Core Processors

In this first part, I present a set of four implementations of the RV32I RISC-V ISA:
non-pipelined, pipelined, multicycle, and multihart (i.e., multithreaded). Each
defines a single core IP which has been simulated and synthesized with the
Vitis HLS tool, placed and routed by the Vivado tool, and tested on the Xilinx FPGA
available on a Pynq-Z1/Pynq-Z2 development board.
Introduction:What Is an FPGA,What Is
High-Level Synthesis or HLS? 1

Abstract
This chapter shows what an FPGA is and how it is structured from Configurable
Logic Blocks or CLB (in the Xilinx terminology, or LAB, i.e. Logic Array Blocks
in Altera FPGAs). It also shows how a hardware is mapped on the CLB resources
and how a C program can be used to describe a circuit. An HLS tool transforms
the C source code into an intermediate code in VHDL or Verilog and a placement
and routing tool builds the bitstream to be sent to configure the FPGA.

1.1 What Hardware to Put in an FPGA?

A processor is a hardware device (an electronic circuit, or a component), able to


calculate everything which is computable, i.e. any calculation for which there is an
algorithm. It is enough to transform this algorithm into a program and apply the
processor to this program with data to obtain the result of the calculation.
For example, a processor can run a program turning it into a tremendous calcula-
tor, capable of carrying out all the mathematical operations. For this, the processor
contains a central component, the Arithmetic and Logic Unit (ALU). As its name
suggests, this electronic circuit unit within the processor performs basic arithmetic
and logic operations. In the ALU, the calculation is the propagation of signals pass-
ing through transistors (a transistor is a kind of small switch or tap which you open
or close to give way or block the current; a transistor has three ends: the input, the
output, and the open/close command).
The ALU itself contains an adder, i.e. a circuit to do binary additions.
How can transistors be assembled in a way which, by supplying the 0s and 1s of
the binary representation of two integers as input, obtain the 0s and 1s of the binary
representation of the result at the output of the transistor network?
When the solution to the problem is not directly apparent, we must break it down
to bring us back to a simpler problem. In school, we learned that to add two decimal
© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 3
B. Goossens, Guide to Computer Processor Architecture, Undergraduate Topics
in Computer Science, https://doi.org/10.1007/978-3-031-18023-1_1
4 1 Introduction: What Is an FPGA, What Is High-Level Synthesis or HLS?

Fig. 1.1 Decimal addition 1 110 1 1100 111


(left), binary addition (right). 8231 1010 0111
The two additions are + 1976 + 0111 0001
applied to different numbers 1 0207 1 0001 1000

Fig. 1.2 A pair of gates c=1


representing a binary adder
circuit a=1
s=0
b=1

numbers is to go from right to left—from units to tens, hundreds, etc.—by adding


the digits of the same rank and by propagating the carry to the left. In doing so, two
digits are produced at each step (each rank). One is the sum modulo 10 and the other
is the carry (see the left part of Fig. 1.1; the line in red is the carries one; the two
numbers to be added are in brown; the result is composed of the sum in blue and the
final carry in green).
We thus reduced our general problem of the addition of two numbers to the simpler
problem of the addition of two digits.
If the digits are binary ones (these are bits, abbreviation of binary digits), the
addition process is identical. The sum is calculated modulo 2 and there is a carry as
soon as at least two of the three input bits are 1s (see the right part of Fig. 1.1).
The modulo 2 sum of two bits and their carry can be defined as Boolean operators.
The modulo 2 sum is the exclusive OR (or XOR) of the two bits (the symbol ⊕)
and the carry is the AND (the symbol ∧).
Notice that a ⊕ b is 1 if and only if a and b are different (one of the two is a 1 and
the other is a 0). Similarly, a ∧ b is 1 if and only if a and b are both 1s.
The transition to Boolean operators is a decisive step towards a hardware repre-
sentation of the binary addition because we know how to build, based on transistors,
small constructions which form logic gates, i.e. Boolean operators. Thus, we find
NOT, AND, OR, XOR gates, but also NAND, NOR, and all the Boolean functions
of two variables.
Our binary adder becomes the pair of gates in Fig. 1.2. The top gate is an AND
and the bottom gate is an XOR. The figure shows the operation of the circuit when
two inputs are provided with the same value 1.
To build a circuit, we must draw the gates which compose it or write a program in
a hardware description language (HDL) like VHDL or Verilog. The code in Listing
1.1 is the VHDL interface and implementation of the adder shown in Fig. 1.2.
Listing 1.1 A VHDL function defining a 1-bit adder
L I B R A R Y IEEE ;
use IEEE . S T D _ L O G I C _ 1 1 6 4 . ALL ;
e n t i t y B I T _ A D D E R is
port (a , b : in STD_LOGIC ;
s , c : out S T D _ L O G I C ) ;
end B I T _ A D D E R ;
a r c h i t e c t u r e BHV of B I T _ A D D E R is
begin
1.2 Look-Up Table (LUT): A Piece of Hardware to Store a Truth Table 5

s <= a xor b ;
c <= a and b ;
end BHV ;

A succession of softwares transform these gates or this program into transistors


then organize them on a layout. Finally, a founder physically builds the circuit.
Instead of relying on an electronic foundry, we can use an FPGA. Its name indicates
that it is more or less an array of gates which can be programmed. The programming
consists of linking these gates into subsets forming small circuits within the large
circuit which houses them.

1.2 Look-Up Table (LUT): A Piece of Hardware to Store a Truth


Table

We want to add two 1-bit words, i.e. s = a + b, where a and b are Boolean variables.
The sum s is a 2-bit word, composed of the modulo 2 sum and the carry bit.
For example, if the pair (a, b) is (1, 1), their sum s in binary is 10, which is the
concatenation of the carry bit (1) and the modulo 2 sum (0).
Let us first concentrate on the modulo 2 sum.
We can define the modulo 2 sum as a Boolean function of two variables, which
truth table is presented as Table 1.1, where the arguments of the function are in blue
and the values of the function are in red.
For example, the last line of the table says that if a = b = 1 then s = 0, i.e.
s(1, 1) = 0.
A LUT (acronym of Look-Up Table) is a hardware device which is similar to
a memory. This memory is filled with the truth table of a Boolean function. For
example, a 4-bit LUT (or a LUT-2), can store the truth table of a Boolean function
of two variables (the red values in Table 1.1).
More generally, a 2n -bit LUT (or a LUT-n), can contain the truth table of a Boolean
function of n variables (where you can fit 2n truth values).
For example, NOT is a single-variable Boolean function. It is represented by a
two line truth table and a LUT-1, i.e. two truth values (NOT(0)=1 and NOT(1)=0).
The two-variable Boolean function AND can be extended to three variables (a
AND b AND c). The truth table has eight lines, as shown in Table 1.2.

Table 1.1 The truth table of the modulo 2 sum of two 1-bit words
a b s
0 0 0
0 1 1
1 0 1
1 1 0
6 1 Introduction: What Is an FPGA, What Is High-Level Synthesis or HLS?

Table 1.2 The truth table of the operator a AND b AND c


a b c s
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 0
1 1 1 1

Table 1.3 The truth table of the operator “IF a THEN b ELSE c”
a b c s
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 1

The operator “IF a THEN b ELSE c” is another example of a three-variable


Boolean function. It is represented by the eight truth values in Table 1.3. The function
“IF a THEN b ELSE c” is c if a is 0 (the values in cyan), b otherwise (the values in
orange).
The LUT, like the truth table, is a kind of universal Boolean function. By filling
it, you define the Boolean function it contains.
In an FPGA, a LUT is represented by a memory, i.e. an addressable hardware
device. By addressing the memory, we obtain what it contains at the provided address.
Figure 1.3 shows how, from a = 1 and b = 1 inputs, meaning the LUT address 3
(11 in binary), the bit contained in the memory cell at the bottom right is accessed.
The address is split into two halves. One half (a input) serves as a row selector and
the other half (b input) as a column selector.
In Fig. 1.3, the memory is addressed with a = 1, which selects the line framed in
red. It is also addressed with b = 1, which selects the column framed in green. The
intersection of the chosen row and column provides the output s of the LUT.
1.3 Combining LUTs 7

Fig. 1.3 Accessing the b=1


address 3 cell (11 in binary)
of the LUT to compute 0 1
s = (1 + 1) modulo 2
0
0 1
a=1
1
0 1
0
s=0

1.3 Combining LUTs

Let us continue our construction of an adder. This time, let us try to build a full adder,
that is, a hardware cell calculating the modulo 2 sum of two bits and an input carry.
The carry is a new input variable which extends the truth table from four to eight
rows. The modulo 2 sum of the three input bits a, b, and ci is their XOR (a ⊕ b ⊕ ci ).
Rather than being built with a LUT-3, the full adder is built with two LUT-2. It
calculates not only the modulo 2 sum of its three inputs but also their carry.
For example, if a = 0 and b = 1, the modulo 2 sum is s = 1. But if there is a
carry in, say ci = 1, then the modulo 2 sum is s = 0 and there is a carry out co = 1.
A first LUT-2 is used to store the truth table of the Boolean function generate. As
its name suggests, the generate function value is 1 when the sum of the two sources
a and b generates a carry, i.e. when a = b = 1, meaning a ∧ b is true (a AND b).
A second LUT-2 stores the truth table of the Boolean function propagate. The
propagate function value is 1 when both sources a and b can propagate an inbound
carry but cannot generate one, which happens when either of the two sources is a 1
but not both simultaneously. The propagate function is the XOR (a ⊕ b).
We link the two tables as shown in Fig. 1.4. In the figure, the addressed table
entries are shown in red. The values out of the LUTs are propagated to the mux box
and to the XOR gate on the right.
The box labeled mux is a multiplexer, that is, equivalent to the Boolean function
“IF x THEN y ELSE z”. The input coming from the left side of the box is the x
selector. The entries coming from the lower edge of the box are the choices y (the
right input) and z (the left input). If the selector x is a 0, the choice on the left (z) is
found at the output. Otherwise, it is the right choice which crosses the multiplexer
(y).
Thus, if a = 0 and b = 1, the propagate function value is 1 and the generate
function value is 0 (these values are in red in the figure). If the incoming carry ci
is 1, the multiplexer selector (1) passes the right choice ci and the outgoing carry is
co = 1.
The structure of the prefabricated circuit composed of the two LUTs and the two
gates brings out the propagation of the input carry ci towards the output co when the
multiplexer chooses its right input, i.e. when propagate is 1. This carry propagation
8 1 Introduction: What Is an FPGA, What Is High-Level Synthesis or HLS?

b=1
co

0 1 1
1
mux
0 1 0 1 1
0 s
propagate
1
a=0

0 0

0 1
ci=1
generate

Fig. 1.4 A full adder with two LUT-2

mode is very efficient because the input signal ci is found at the output after a single
gate crossing.
The gate on the right of the figure is an XOR. It produces the modulo 2 sum of
propagate and ci . Since propagate is itself an XOR, the output s is the modulo 2
sum of the three inputs a, b, and ci (a ⊕ b ⊕ ci ).
In the example presented, the combination of the two LUTs, the multiplexer and
the XOR gate calculates two bits, one representing the modulo 2 sum of the three
inputs and the other being the outgoing carry. By sticking these two bits together,
we form the 2-bit sum of the three inputs (0 + 1 + 1 = 10 in binary).
The organization of the full adder proposed above corresponds to what is found
in a CLB, i.e. a Configurable Logic Block, which is the basic building block of the
FPGA (in [1], pages 19 and 20, you have the exact description of the CLBs you find
in the FPGA used in this book).
A CLB combines a LUT with a fast carry propagation mechanism. It is a kind
of Swiss army knife, which computes logic functions with the LUT and arithmetic
functions with the carry propagation.
The programming or configuration of the CLB is the filling of the LUTs with
the truth values of the desired Boolean functions (in the example, the propagate and
generate functions; the Swiss army knife may divide the LUT in two halves to install
two Boolean functions).
1.4 The Structure of an FPGA 9

1.4 The Structure of an FPGA

Let us try to extend our adder from a 1-bit word adder to a 2-bit word adder.
Let A = a1 a0 and B = b1 b0 , for example A = 10, with a1 = 1 and a0 = 0 (i.e.
1 ∗ 21 + 0 ∗ 20 , or 2 in decimal), and B = 01 (i.e. 0 ∗ 21 + 1 ∗ 20 , or 1 in decimal).
The sum A + B + ci is the 3-bit word co s1 s0 (for example 10 + 01 + 1 = 100 or in
decimal 2 + 1 + 1 = 4).
By combining two CLBs configured as a full adder, with the output of the first
(co0 in Fig. 1.5) connected to the input of the second (ci1 in Fig. 1.5) and inputs a0
and b0 for the first and a1 and b1 for the second, three bits are output, forming the
co s1 s0 sum of the two 2-bit words A = a1 a0 and B = b1 b0 and an incoming carry
ci .
Figure 1.5 shows this 2-bit adder.
An FPGA contains a matrix of CLBs (see the left part of Fig. 1.6).
For example, the Zynq XC7Z020 from Xilinx is a SoC (System-on-Chip, i.e.
a circuit containing several components: processors, memories, USB and Ethernet
interfaces, and an FPGA of course) whose programmable part (the FPGA) contains
6650 CLBs.
One can imagine that the CLBs are organized in a square of more or less 80
columns and 80 rows (the exact geometry is not described). For a detailed presentation
of FPGAs (including their history), you can refer to the Hideharu Amano book [2].
Each CLB contains two identical, parallel and independent SLICEs (centre part
of Fig. 1.6). Each slice mainly consists of four LUT-6 and eight flip-flops (the red
squares labeled FF—for Flip-Flop—in the centre and right part of Fig. 1.6). Each
flip-flop is a 1-bit clocked memory point, which collects the output of the LUT.
Each LUT-6 can represent a six-variable Boolean function or can be split into two
LUT-5, each representing a five-variable Boolean function.
The LUTs of the same slice are linked together by a carry propagation chain
identical to that of Figs. 1.4 and 1.5 (including a multiplexer and an XOR gate).

Fig. 1.5 A 2-bit adder built co


from two CLBs
a1
s1
CLB1
b1
ci1

co0
a0
s0
CLB0
b0
ci
10 1 Introduction: What Is an FPGA, What Is High-Level Synthesis or HLS?

left slice right slice

CLB ... CLB LUT LUT

LUT LUT FF
... ...
LUT LUT

CLB ... CLB LUT LUT FF

FPGA CLB LUT−6

Fig. 1.6 The structure of an FPGA

Fig. 1.7 A 16-bit adder built co


with four CLBs
A3 a3 m x s3
B3 CLB b3 LUT

A2 a2 m x s2
B2 CLB b2 LUT

A1 a1 m x s1
B1 CLB b1 LUT

A0 a0 m x s0
B0 CLB b0 LUT
0 ci
A0 = a03...a00 B0 = b03...b00
A1 = a07...a04 B1 = b07...b04
A2 = a11...a08 B2 = b11...b08
A3 = a15...a12 B3 = b15...b12

A LUT can be partially filled. It may contain only four useful bits out of the 64
available to represent a Boolean function with two variables. But it is better not to
waste this resource.
By continuing to extend the 2-bit adder, one can build an adder of any size.
A 16-bit adder links four CLBs of a single column, using 16 LUTs in series, each
LUT containing the two tables in Fig. 1.4 (notice that the adder uses only one of the
two available slices in each CLB).
The left part of Fig. 1.7 shows how the two 16-bit words to be added are distributed
by nibbles in the four CLBs (for exemple the A3 = a15 a14 a13 a12 nibble inputs the
highest CLB in the figure). The first CLB in the chain (the lowest in the figure)
receives an input carry entry ci = 0.
The right part of the figure shows the addition of the first nibbles (a3 a2 a1 a0 +
b3 b2 b1 b0 ) in the LUTs (each LUT is split into two half LUTs, the first containing
the generate function and the second containing the propagate function). The multi-
plexers (boxes labeled m) propagate the carry from the input ci to the output co . The
XOR gates (boxes labeled x) provide the modulo 2 sum bits, which may be stored
in the flip-flops (rightmost boxes, labeled s0 through s3 ).
1.5 Programming an FPGA 11

1.5 Programming an FPGA

An FPGA is a programmable circuit. How do you program a circuit?


A circuit is programmable when it is given two successive operating modes.
The first mode is the initialization. Storing structures are filled with initial values.
Once this phase has been completed, the second operating mode starts. It is the
computation, which uses the values installed during the initialization.
The initialization phase of an FPGA fills the LUTs with the truth values of the
Boolean functions which they represent.
It is also necessary to link the CLBs participating in the same calculation (for
example, clear the ci input of the first CLB of the adder, and link its co output to the
next CLB ci input).
This link phase is done with multiplexers (for example to choose ci between 0
and co ). The initialization of the links sets the selection bit of the multiplexer.
All the resources of the FPGA (LUTs and inter CLB links) are thus initialized
from a sequence of bits which constitutes a bitstream.
This sequence of bits is sent from a programming station (i.e. your computer).
It comes in the FPGA bit by bit (known as serial transmission). Each bit takes its
corresponding place in the FPGA.
Once this phase is completed, the FPGA enters the computation phase which
performs the function assigned to it by the configuration phase.
In practice, the programming phase lasts a few seconds.
One question remains: how do you go from a function to its hardware implemen-
tation on the FPGA?
In the early days of FPGAs (i.e. in the mid-80s), gates were drawn as in Fig. 1.2.
A translator was in charge of placing these gates in LUTs.
Soon enough, FPGAs became big and complex enough to implement units which
became difficult (and unsafe) to define in schematics.
Hardware description languages (HDL) were proposed (VHDL, Very high speed
integrated circuits HDL, and Verilog are the two most used languages).
Rather than drawing gates, we describe a circuit behaviour with a hardware-
specific language and a compiler transforms the source description into a bitstream.
An HDL program exactly says how a circuit should behave, from its inputs to its
outputs, through binary operations or subroutine calls. In addition to the calculation,
the program also expresses the temporality of the signals—i.e. the variables of the
program—related to their propagation time in the circuit.
In the mid-90s, a higher level method was proposed, based on classic programming
languages (like C or C++). The temporality is left as a job for a translator. The idea was
to define a circuit by a program and let the translator implement the corresponding
component with CLBs. This method is HLS (High-Level Synthesis; synthesis is the
name given to the construction of the circuit from a transformation of the source
program; the translator is a synthesizer).
12 1 Introduction: What Is an FPGA, What Is High-Level Synthesis or HLS?

For example, the C function shown in Listing 1.2 builds a 32-bit adder.
Listing 1.2 A function defining a 32-bit adder
void a d d e r _ i p ( u n s i g n e d int a,
u n s i g n e d int b,
u n s i g n e d int * c ) {
*c = a + b;
}

HLS transforms this C code into an intermediate representation (one of them is


the RTL or Register Transfer Level representation, which is used in HDL programs;
from the RTL, a VHDL or a Verilog program can be built).
A placement and routing software maps the RTL on CLBs (placement phase),
then associates these CLBs with those of the FPGA by minimizing the propagation
times and sets up the necessary links (routing phase).
The placement and routing leads to the constitution of the bitstream which is lastly
transmitted to the FPGA through a USB link (Universal Serial Bus).
The next chapter is devoted to the installation of the HLS, placement and routing
softwares, and their application to the adder example.

References
1. https://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
2. H. Amano, Principles and Structures of FPGAs (Springer, 2018)
Setting up and Using the Vitis_HLS,
Vivado, and Vitis IDE Tools 2

Abstract
This chapter gives you the basic instructions to setup the Xilinx tools to implement
some circuit on an FPGA and to test it on a development board. It is presented as
a lab that you should carry out. The aim is to learn how to use the Vitis/Vivado
tools to design, implement, and run an IP.

2.1 Getting the Hardware

You should first order your development board on which you will later upload your
RISC-V processor design.
Any development board with an FPGA and an USB connection can fit.
I use a Pynq-Z1 board from Digilent equipped with a Xilinx Zynq XC7Z020
FPGA [1]. The FPGA is large enough to host the RV32I ISA subset. An equivalent
Pynq-Z2 board (from TUL [2]) with the same FPGA would also be fine and very
close to my Pynq-Z1.
The Basys3 from Digilent [3] has a Xilinx Artix-7 XC7A35T FPGA. It is also
suited to the book goals.
Older boards like the Zybo (Zynq XC7Z020 FPGA), the Zedboard (Zynq XC7Z020
FPGA), or the Nexys4 (Artix-7 XC7A100T FPGA) are also suitable.
More expensive boards like the ZCU 102/104/106 are very large. They can host
more ambitious IPs than the ones proposed in the book (for example, more than eight
cores or harts in a multicore or multihart processor).
More generally, any board embedding an FPGA with at least 10K LUTs is (more
than) large enough to host an RV32I RISC-V core (the more the LUTs, the larger the
FPGA). However, to implement the multicore designs presented in the second part
of the book, a larger FPGA with at least 30K LUTs is needed.
In the Xilinx Zynq-7000 FPGA family, the XC7Z010 FPGA has 18K LUTs. The
XC7Z020 FPGA has 53K LUTs.
© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 13
B. Goossens, Guide to Computer Processor Architecture, Undergraduate Topics
in Computer Science, https://doi.org/10.1007/978-3-031-18023-1_2
14 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

In the Xilinx Artix-7 FPGA family, the XC7A35T has 33K LUTs. The XC7A100T
has 101K LUTs.
In the Xilinx UltraScale+ FPGA family, the XCZU7EV has 230K LUTs (ZCU104/
106 boards). The XCZU9EG has 274K LUTs (ZCU 102 board).
I have tested two types of development boards: the ones embedding an Artix-7
series FPGA (e.g. Nexys4 and Basys3) and the ones embedding a Zynq-7000 series
FPGA (Pynq-Z1, Pynq-Z2, Zybo, and Zedboard).
The difference comes from the way they are interfaced.
The Artix-7 based boards give access to the programmable part of the FPGA
through a microblaze processor (the microblaze is a Xilinx softcore processor fea-
turing a MIPS-like CPU).
The Zynq based boards are interfaced through a Zynq7 Processing System IP,
placed between an embedded Cortex-A9 ARM processor and the programmable
part of the FPGA (you can find a very good description of what is inside a Zynq and
what you can do with it, for example on a Zedboard, in the Zynq Book [4]).
It does not make much difference in the programming because both processors,
microblaze or ARM, run programs built from C codes. But there are differences in
the way the IP you will develop should be connected to the interface system IP, either
microblaze or Zynq.
If you are a university professor, you may ask for a free board (you will receive a
Pynq-Z2 board) through the XUP Xilinx University Program [5].
Otherwise, the Pynq-Z2 board costs around 200e (210$ or 170£; these are the
2022 Q2 prices) (the Pynq-Z1 board is no more sold). The Basys3 has a smaller FPGA
but still large enough to host all the RV32I based RISC-V processors presented in
this book. It is sold at 130e (140$ or 110£).
The development board is the only element you will have to purchase (and this
book; but you already have it). Everything else is for free.
If you request XUP, it will probably take a few weeks before you receive your
board at home. This is why I started by this step. But meanwhile, you have plenty of
duties you can carry out (all the sections in this chapter except Sect. 2.7).

2.2 Getting the Software: The Xilinx Vitis Tool

(If you already know how to use Vitis/Vivado, i.e. Vitis_HLS, Vivado, and Vitis IDE,
and if you have already installed Vitis on your computer, you can jump to Chap. 3 to
install the RISC-V tools.)
First of all, the following is an important notice concerning the compatibility of
the different softwares with the Operating System.
In this book, I assume Linux, Ubuntu (any version from the 16.04 should be
compatible with Vitis; I use Ubuntu 22.04 LTS ‘Jammy Jellyfish’ in this book). I
also assume Vitis 2022.1 or a later version (if you have an older version, some of my
HLS codes might not be synthesizable, but they surely can be simulated within the
Vitis HLS tool).
2.2 Getting the Software: The Xilinx Vitis Tool 15

If you are using Windows, you will have to find software installation procedures
with your preferred browser.
For the RISC-V simulator, the standard tool spike is not available for Windows.
As far as I know, people run spike within a Linux virtual machine inside Windows.
Maybe you should consider this option for the RISC-V simulations (and learn a bit
of Linux from the commands used in this book).
If you are using MacOS X, you have to install the Xilinx tools through a Linux
virtual machine.
If you are using another Linux distribution (e.g. Debian), the given explanations
should more or less work.
The Xilinx Vitis software is available for Windows and Linux. If you use Windows,
you should find a few differences on how to start the Xilinx tools. Once inside the
Vitis software, there is no difference between Linux and Windows.
The Vitis software [6] is freely downloadable from the Xilinx site at the URL
shown in Listing 2.1 (you will have to register at Xilinx to download).
Listing 2.1 Xilinx URL from where to download the Vitis software
https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/
vitis.html

On Ubuntu 20.04 and 22.04, before installing Vitis, you must install the libt-
info.so.5 library ("sudo apt-get install libtinfo5") (otherwise, the installer hangs as
mentioned at https://support.xilinx.com/s/article/76616?language=en_US).
I assume you will install the software in the /opt/Xilinx folder.
If you are working on a Linux computer, you downloaded a file named Xil-
inx_Unified_2022.1_0420_0327_Lin64.bin (your version name might differ from
mine, especially if you get a later one). You must set it to executable and run it
with the commands in Listing 2.2 (in sudo mode to install in the /opt/Xilinx folder)
(the commands are available in the install_vitis.txt file in the goossens-book-ip-
projects/2022.1/chapter_2 folder).
Listing 2.2 Run the Vitis installation software
$ cd $HOME / D o w n l o a d s
$ chmod u + x X i l i n x _ U n i f i e d _ 2 0 2 2 .1 _ 0 4 2 0 _ 0 3 2 7 _ L i n 6 4 . bin
$ sudo ./ X i l i n x _ U n i f i e d _ 2 0 2 2 .1 _ 0 4 2 0 _ 0 3 2 7 _ L i n 6 4 . bin
...
$

Within the installer, you should choose to install Vitis (first choice in the Select
Product to Install page).
The installation is a rather long process (i.e. several hours, but mainly depending on
the speed of your internet connection; on my computer with a Gb speed connection,
it took 12h45 to download 65.77 GB, i.e. 1.43 MB per second; the installation itself
took 30 min).
The installation requires a lot of disk space (272 GB), which you can reduce a
bit by deselecting some design tools (you really need Vitis, Vivado, and Vitis HLS)
and some devices (for the PynqZ1/Z2 boards you need the SoCs devices and for the
Basys3 board, you need the 7 Series ones).
16 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

Since april 2022, git has been upgraded to face a security vulnerability. If you
have not freshly installed or recently upgraded your version of git, you should do
it (your version should be superior or equal to 2.35.2; check with "git --version").
Run the commands in Listing 2.3 (they are available in the install_git.txt file in the
chapter_2 folder).
Listing 2.3 upgrading git
$ sudo add - apt - r e p o s i t o r y -y ppa : git - core / ppa
$ sudo apt - get u p d a t e
$ sudo apt - get i n s t a l l git - y
$

2.3 Installing the Development Board Definition in the Vitis


Software

From the github sites given in Listings 2.4–2.6, download either of these three files:
pynq-z1.zip, pynq-z2.zip, master.zip (the first one if you have a Pynq-Z1 board, the
second one if you have a Pynq-Z2 board, the third one if you have a Basys3 board;
the master.zip file from the Digilent site also contains the definitions of many other
boards among which the Nexys4, Zybo, and Zedboard; if you do not find the zip
files, search with your preferred browser for "pynq-z1 pynq-z2 basys3 board file").
Listing 2.4 github from where to download the pynq-z1.zip file
https://github.com/cathalmccabe/pynq-z1_board_files

Listing 2.5 github from where to download the pynq-z2.zip file


https://dpoauwgwqsy2x.cloudfront.net/Download/pynq-z2.zip

Listing 2.6 github from where to download the master.zip file


https://github.com/Digilent/vivado-boards/archive/master.zip

Extract the zip and place the extracted folder (the main folder and its sub-folders)
into your Vitis installation in the /opt/Xilinx/Vivado/2022.1/data/boards/board_files
directory (create the missing board_files folder).

2.4 Installing the Book Resources

To install the book resources, run the commands in Listing 2.7 (available in in-
stall_book_resources.txt in the chapter_2 folder; as you have not cloned the re-
sources yet, you should get the file from the github repository).
2.5 Using the Software 17

Listing 2.7 Cloning the book resource folder


$ cd
$ git clone
https://github.com/goossens-springer/goossens-book-ip-projects
...
$

The newly created goossens-book-ip-projects folder in your HOME is the place


where you will work.

2.5 Using the Software

All the source files and shell command files related to the my_adder_ip can be found
in the chapter_2 folder.
The Vitis software is a huge piece of code, with many usages among which you
will use just a tiny part. To quickly focus on what is useful for you, you will design
a small but complete IP example.
The example IP is the adder presented in the introduction, which receives two
32-bit integers and outputs their sum modulo 232 .
You will write two C pieces of code, one which describes the component and the
other to use it.
The C code can be input through any text editing tool but I recommend to use the
Vitis_HLS tool Graphical User Interface (GUI).
Before you build your project, make sure that the build-essential package is
installed. To check, just try to install it again by running the command in Listing 2.8
(this command is in the install_build-essential.txt file in the chapter_2 folder).
Listing 2.8 Install the build-essential package
$ sudo apt - get i n s t a l l build - e s s e n t i a l
...
$

To start the GUI environment, type in a terminal the commands shown in Listing
2.9 (these commands are in the start_vitis_hls.txt file in the chapter_2 folder).
Listing 2.9 Set the required environment and start Vitis_HLS
$ cd / opt / X i l i n x / V i t i s _ H L S / 2 0 2 2 . 1
$ s o u r c e s e t t i n g s 6 4 . sh
$ cd $HOME / goossens - book - ip - p r o j e c t s / 2 0 2 2 . 1
$ vitis_hls &
...
$

On the Debian distribution of Linux, you may have to update the LD_LIBRARY_
PATH environment variable before launching Vitis_HLS (export "LD_LIBRARY_
PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH").
18 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

2.5.1 Creating a Project

Once in the Vitis_HLS tool (see Fig. 2.1), you are in the Vitis_HLS Welcome Page
where you click on Project/Create Project.
This opens a dialog box (New Vitis_HLS Project/Project Configuration, see
Fig. 2.2) which you fill with the name of your project (my_adder_ip; I systematically
name my Vitis_HLS project with the _ip suffix). You click on the Next button.
The next dialog box opens (New Vitis_HLS Project/Add/Remove Design Files,
see Fig. 2.3), where you name the top function (e.g. my_adder_ip; I systematically
give the same name to the Vitis_HLS project and its top function). This name will
be given to the built IP. You can leave the Design Files frame empty (you will add
design files later). Click on Next.
In the next dialog box (New Vitis_HLS Project/Add/Remove Testbench Files,
see Fig. 2.4), you can leave the TestBench Files frame empty (you will add testbench
files later). Click on Next.
In the Solution Configuration dialog box (see Fig. 2.5), you have to select which
development board you are targetting. In the Part Selection frame, click on the "..."
box.
In the Device Selection dialog box (see Fig. 2.6), click on the Boards button.

Fig. 2.1 The Vitis_HLS tool welcome page


2.5 Using the Software 19

Fig. 2.2 The Project Configuration dialog box

Fig. 2.3 The Add/Remove Design Files dialog box to name the top function
20 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

Fig. 2.4 The Add/Remove Testbench Files dialog box

Fig. 2.5 The Solution Configuration dialog box to select your development board
2.5 Using the Software 21

Fig. 2.6 The Device Selection dialog box to select your development board

In the Search frame (see Fig. 2.7), type z1 or z2 or basys3 (according to your
board; even if you are still waiting for it, you can proceed). Select your board (in my
case, Pynq-Z1, xc7z020clg400-1) and click on OK (if you do not see your board in
the proposed selection, it means you have not installed the board files properly: go
back to 2.3).
You are back to the Solution Configuration box. Click on Finish to create your
Vitis_HLS project skeleton (see Fig. 2.8).

2.5.2 Creating an IP

The next step after preparing the project is to fill it with some content. You will
add two pieces, one which will represent your adder IP and a second devoted to its
verification through simulation.
After the project creation, the Vitis_HLS tool opens the Vitis_HLS 2022.1 -
my_adder_ip eclipse-based window (see Fig. 2.9).
I will not describe the full possibilities. What I will describe now only concerns
the editing of the source and testbench files.
22 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

Fig. 2.7 Selecting the Pynq-Z1 board

Fig. 2.8 Finishing the Vitis_HLS project creation


2.5 Using the Software 23

Fig. 2.9 The main Vitis_HLS eclipse-based window

The IP should be designed through a void top function. This top function depicts
a component.
A component has a pinout and this pinout is the only way to interact with the
component. There is no backdoor. You should not be able to observe nor to modify
inside the component, which means that no observer nor modifier function should
be provided.
A component may be combinational or sequential. In the former case, the outputs
are a combination of the inputs. In the latter case, the outputs are a combination of
the inputs and an internal state which evolves. The internal state is memorized. A
sequential component is clocked and at the start of each clock cycle, the internal
state is updated.
The internal state is initialized through input pins. It should never be directly
manipulated from outside the IP, neither to set it nor to observe its values.
For example, a processor is a sequential component. Its internal state includes the
register file. The register file is not visible from outside the processor. The processor
definition may include an initialization phase (i.e. a reset phase) to clear the register
file and an ending phase to dump it to memory (i.e. a halt phase). But the external
world should have no access at all to the register file.
24 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

The adder example is a combinational circuit. It has no internal state. However,


your processor designs will be sequential IPs with an internal state.
To represent the component and its pinout, you will use a void function prototype.
The function arguments are the pinout, with input arguments acting as input pins and
output arguments acting as output pins.
In the my_adder_ip example, there are two inputs and one output. The two inputs
are the words to be added (32-bit integers) and the output is the sum word (another
32-bit integer). Listing 2.10 shows the my_adder_ip function prototype.
Listing 2.10 The my_adder_ip component prototype or pinout
void m y _ a d d e r _ i p ( u n s i g n e d int a,
u n s i g n e d int b,
u n s i g n e d int * c ) ;

The input arguments are values and the output argument is a pointer.
When your component will be simulated, you will use a main function to call the
my_adder_ip function. This call will have a hardware signification: apply inputs to
the component and let it the time to produce its output and save it into the unsigned
int c location.
In the main function, after the call to my_adder_ip, you will print the *c value to
mimic the electronic observation of the c pins.
In the FPGA, the a, b and c arguments will be implemented as memory points
connected to the my_adder_ip chip inside the programmable part.
Within the Vitis_HLS GUI, right-click on the Source button in the Explorer
frame and choose New Source File... (see Fig. 2.10).
In the navigation window, navigate to the my_adder_ip folder, open it, name your
new file my_adder_ip.cpp and click on Save (see Fig. 2.11).
The new file is added to the sources as shown in Fig. 2.12.
The my_adder_ip.cpp tab in the central frame let you edit your top function.
Copy/paste the my_adder_no_pragma_ip.cpp file from the chapter_2 folder).
Listing 2.11 The my_adder_ip top-function code
void m y _ a d d e r _ i p ( u n s i g n e d int a,
u n s i g n e d int b,
u n s i g n e d int * c ) {
*c = a + b;
}

The my_adder_ip.cpp tab in your Vitis_HLS window should look like in


Fig. 2.13. Save the file.

2.5.3 Simulating an IP

Before you implement the IP on the FPGA, it is better to take the time to test it. You
will see that placing and routing a design on an FPGA may be a rather long process
(from a few seconds to a few hours, according to the design complexity and your
computer efficiency). To avoid repeatedly waits, it is a good practice to debug your
HLS code with the Vitis_HLS tool simulation facility. For such a simulation, you
2.5 Using the Software 25

Fig. 2.10 Adding a new source file

Fig. 2.11 Adding a new my_adder_ip.cpp source file in the my_adder_ip folder
26 2 Setting up and Using the Vitis_HLS, Vivado, and Vitis IDE Tools

Fig. 2.12 The my_adder_ip.cpp file added to sources

need to provide a main function within a testbench file. The role of this function is
to create the component, run it and observe its behaviour.
Right-click on the Test Bench button in the Explorer frame. Select New Test
Bench File... (see Fig. 2.14).
In the navigation window, name your new testbench file
testbench_my_adder_ip.cpp and click on Save (see Fig. 2.15).
The new testbench file is added as shown in Fig. 2.16.
Click on the testbench_my_adder_ip.cpp tab in the central frame and fill it with
the code in Listing 2.12 (copy/paste the testbench_my_adder_ip.cpp file from the
chapter_2 folder).
Random documents with unrelated
content Scribd suggests to you:
que les Corses, sujets de la république de Gênes, n'avaient pas le
droit de disposer d'eux-mêmes, rejeta, sans même les discuter, les
propositions d'Orticoni. Voyant qu'aucune puissance terrestre ne
voulaient d'eux, les Corses finirent par se donner à la Sainte Vierge.
Les principaux de la nation, réunis en assemblée générale, le 30
janvier 1735, instituèrent de nouvelles lois sous ce titre: Nouvelles
lois du Royaume et République de Corse.
L'assemblée, en premier lieu, proclama «l'Immaculée Conception de
la vierge Marie», protectrice du royaume, et décréta que son image
serait peinte sur les armes et sur les drapeaux de la nation. Puis elle
abolit tout ce qui pouvait rester du gouvernement génois, dont les
lois et les statuts devaient être brûlés publiquement. Elle institua une
administration nationale et une diète composée des députés de
chaque ville et de chaque village. André Ceccaldi, Hyacinthe Paoli et
Louis Giafferi étaient nommés Primats de la nouvelle république avec
le titre d'Altesse Royale. La Diète recevait la Sérénité. Les emplois
subalternes donneraient les titres d'Excellence et d'Illustrissime [31].
Et cette assemblée de farouches libertaires décréta la peine de mort
contre quiconque oserait tourner ces titres en dérision [32].
Mais cette constitution ne pouvait qu'accroître l'anarchie. Il fallait à
la Corse un sauveur. Le pays était dans les conditions voulues pour
accueillir ce sauveur, quel qu'il fut; malheureusement il était
impossible qu'il sortit de son sein. Aucun des chefs n'avait assez
d'autorité pour organiser un mouvement général qui eût
définitivement chassé les Génois. Chacun d'eux avait son clan et sa
clientèle. Il était difficile à l'un des chefs d'imposer aux autres la
prépondérance de son parti sans éveiller des jalousies, qui dans ce
malheureux pays, dégénéraient toujours en luttes armées. Le
sauveur ne pouvait donc venir que du dehors.
Il se présenta aux quatre corses qui sortaient des prisons génoises
sous les traits d'un milord anglais. Ce milord était en réalité un baron
allemand, Théodore de Neuhoff.
Il faut maintenant examiner les antécédents de ce gentilhomme qui
allait jouer un rôle dans l'histoire du peuple corse.

II

A la fin du XVIIe siècle, on voyait encore, en Westphalie, de ces


barons Thunder-ten-Trunck et de ces hobereaux grotesques dont
parle Taine [33]. Pauvres, pleines d'orgueil, attachées à leurs préjugés
de caste, ces familles de barons vivaient dans leurs gentilhommières
qui conservaient, bien amoindri pourtant, l'aspect des burgs de la
vieille Allemagne. Elles se mariaient entre elles pour garder intacte la
pureté de leur sang féodal, et leurs fils s'en allaient guerroyer à la
solde des princes étrangers.
Telle était la famille des barons de Neuhoff: des gens d'ancienne
souche, très infatués de leur noblesse, sans doute, mais, à coup sûr,
sans fortune patrimoniale.
Cette fierté d'un côté, cette pauvreté de l'autre, contribuèrent à les
pousser aux aventures. Déjà avec Antoine de Neuhoff, le père de
Théodore, nous voyons se manifester ces tendances de chevaliers
errants. Dans Théodore, il y a du Don Quichotte avec trop d'ambition
dans le rêve.

Le fief des barons de Neuhoff, au XVIIe siècle, semble avoir été une
terre d'assez mince importance, située dans le comté de Marck en
Westphalie [34].
Antoine de Neuhoff, jeune homme aux manières avenantes, beau
cavalier, mais sans fortune comme tous les siens, était capitaine aux
gardes du corps de l'évêque de Munster. Son père avait commandé
un régiment sous Bernard de Galen [35], ce farouche prélat, véritable
«soudard mitré [36]».
Les préjugés féodaux, à partir de cet héritier, furent moins forts.
Antoine ne tarda pas à s'en défaire. Il quitta le service militaire de
l'évêque de Munster et chercha à redorer son blason par un mariage
avantageux; il n'arriva qu'à se mésallier sans profit. Le drapier de
Viseu, en Liégeois, dont il épousa la fille, mourut un an après le
mariage, ne laissant que onze mille florins.
La famille d'Antoine ne voulut plus le revoir. Il quitta l'Allemagne avec
sa femme [37].
S'il fallait chercher dans les lois encore obscures de l'atavisme moral
l'explication des mobiles qui font agir un être humain, nous verrions
Théodore soumis à une double influence dont les courants mal
équilibrés contrarièrent perpétuellement sa destinée. De sa mère,
Amélie, la fille du vieux drapier liégeois, il tenait cet esprit fertile en
ressources commerciales qui lui permit d'intéresser à son crédit des
juifs et des traitants hollandais; par le sang des routiers allemands
qui coulait dans ses veines, il fut poussé à l'audacieuse entreprise
qui, un moment, alarma Gênes et surprit l'Europe.
Antoine de Neuhoff, qui était venu s'établir dans les environs de
Metz, mourut obscurément en 1695. Il laissait deux enfants:
Elisabeth qui épousa le comte de Trévoux, et Théodore-Etienne, le
héros d'Aléria. La veuve d'Antoine se remaria à un commis des
douanes à Metz, nommé Marneau. Une fille naquit de ce mariage.
Elle épousa dans la suite Gomé Delagrange, conseiller au Parlement
de Metz [38].
Théodore Etienne, baron de Neuhoff, naquit à Cologne, dans la nuit
du 24 au 25 août 1694 [39], quelques mois seulement avant la mort
de son père.
Un parent de Westphalie, le baron Drost, prit soin de la première
enfance de Théodore [40]. A dix ans, il entra chez les jésuites de
Munster. Un trop enthousiaste biographe affirme qu'il fut un élève
intelligent et studieux, faisant ses délices de la lecture de Plutarque.
Il ne devait que de très loin en imiter les héros!
Théodore serait resté pendant six ans chez les jésuites de Munster.
Au collège, il s'était lié—dit-on—avec un jeune homme issu, comme
lui, d'une famille westphalienne. Neuhoff et son camarade auraient
alors été mis en pension à Cologne chez un professeur pour achever
leurs études. On a publié une lettre du compagnon de Théodore, qui
donne ces détails, et qui raconte un épisode tragique après lequel
Neuhoff dût s'enfuir [41].
Le professeur avait une femme et deux filles jolies et sages. L'aînée
se nommait Marianne. C'était un de ces paisibles intérieurs
allemands, aux mœurs familiales, où la vie s'écoulait monotone,
coupée par des récréations honnêtes, quelques promenades au
jardin, des lectures permises et sans doute un peu de sentiment.
Cette existence patriarcale dura deux ans; elle fut troublée par
l'arrivée d'un gentilhomme titré et riche. Il se mit à faire une cour
assidue à Marianne. Théodore était lui-même amoureux de cette
jeune personne, mais il soupirait en silence. Les assiduités du comte
exaspèrent Neuhoff. Bien qu'il n'eût jamais déclaré sa flamme et que
sa position ne lui permît pas de rivaliser avec le seigneur, il n'en
ressentit pas moins une violente jalousie. Un soir, après une fête de
famille, pour l'anniversaire de Marianne, Théodore provoqua le
comte et le tua. Au milieu du trouble, causé par ce drame, Neuhoff
s'était enfui «par une porte de derrière». Ce sera son habitude.
Mais il n'est guère possible d'ajouter foi à cette sombre histoire
d'amour. Théodore devait avoir alors dix-huit ans, puisqu'au dire de
son compagnon il aurait été mis chez les jésuites de Munster à dix
ans, qu'il y serait resté six ans, et qu'il aurait séjourné deux ans chez
le professeur de Cologne. Or, à l'âge de quinze ans, en 1709,
Théodore se trouvait à Versailles parmi les pages de Madame,
duchesse d'Orléans [42]. La preuve est formelle; c'est bien du futur
héros de Corse dont il s'agit. Les détails que la princesse donne sur
lui dans sa correspondance ne peuvent laisser aucun doute à cet
égard.
D'après Madame, le jeune Théodore avait une tournure agréable,
une jolie figure et l'esprit éveillé. Il savait «causer» [43]. Il fut vite
initié à la vie et aux intrigues de la cour. Il acquit une grande
souplesse et de la rouerie; le mot est de l'époque. La princesse n'eut
qu'à se louer du service de son page [44]. Sans doute elle regrettait
de trouver chez lui la trace des qualités françaises plutôt que ces
grosses vertus germaniques, qu'elle mettait au-dessus de tout,
comme elle eut donné toutes les «délicatesses» de la cuisine
française, pour une bonne soupe au lard ou une choucroute
largement garnie. Très allemande, elle s'efforçait d'inculquer à
Neuhoff des goûts allemands. Mais le petit page prit surtout ce qu'il
y avait de mauvais à la cour. La farouche vertu de Madame ne lui
laissa aucune empreinte.
Quand Neuhoff fut en âge de servir, il vint en Bavière [45] où, sur la
recommandation de la princesse, l'Electeur lui donna une bonne
compagnie. Mais Théodore était joueur; sa passion l'entraîna à
commettre des indélicatesses; il contracta des dettes et fit son
apprentissage dans l'art de ne pas les payer. Il devint «un coquin, un
excrocq». Deux chevaliers de Malte lui prêtèrent un jour de l'argent;
pour les tranquilliser, Théodore leur dit: «J'ai encore un oncle et une
tante chez Madame. Mon oncle, c'est M. de Wendt [46], et ma tante,
Mme de Rathsamhausen [47]; je vais vous donner une lettre pour l'un
et l'autre; ils vous payeront immédiatement.»
Il leur remit, en effet, des plis cachetés; les chevaliers arrivèrent à
Versailles et présentèrent à M. de Wendt et à Mme de
Rathsamhausen les lettres de leur neveu Neuhoff. «Nous
connaissons fort bien Neuhoff, répondirent-ils; il a été page de
Madame, mais il n'est pas notre parent.» On ouvrit les paquets: ils
ne contenaient que du papier blanc. Les deux chevaliers étaient
volés; ils s'adressèrent à Madame: «Cet homme, dit-elle, n'est plus à
mon service. Faites en ce que vous voudrez..... [48]».
Harcelé par ses créanciers, Théodore quitta la Bavière et vint à Paris
auprès de son beau-frère et de sa sœur, le comte et la comtesse de
Trévoux. Ses parents voulurent lui faire de la morale; mais le «gentil
enfant», prenant fort mal la chose, «tenta d'assassiner» son beau-
frère. Sur le point d'être arrêté, il s'enfuit et gagna l'Angleterre [49].
Il y a lieu de croire, quoiqu'en dise Madame, que cette tentative de
meurtre ne fut pas bien caractérisée. Elle n'empêchera pas Neuhoff
de revenir plus tard à Paris où personne ne songera à l'inquiéter; il
sera même reçu chez Trévoux.
Le séjour de Théodore, en Angleterre, reste mystérieux. Madame a
reproché à son ancien page d'avoir épousé une jeune anglaise éprise
de lui, alors qu'il s'était déjà marié en Bavière [50].
Cette éclipse ne fut pas de longue durée. On retrouve bientôt après
l'ingénieux baron mêlé à la conspiration de Gœrtz et Gyllenborg.
La Suède avait un roi qui ne s'occupait que de guerre et un ministre
qui ne faisait que de la politique. On aurait pu s'attendre à voir le
petit-fils du compagnon de Bernard de Galen servir Charles XII. Il
préféra se mettre sous les ordres de Gœrtz qui avait rêvé d'être
Richelieu et qui finit comme Cinq-Mars.
Quel fut exactement le rôle de Théodore auprès du ministre suédois?
En réalité, rien de bien défini. Au service de Gœrtz, comme après en
Espagne, comme aussi plus tard dans sa grande aventure de Corse,
Neuhoff fut un courtier marron de la politique internationale, un de
ces agents secrets qu'on emploie, qu'on paye, mais qu'on désavoue
et qu'on remercie quand ils sont brûlés. Ce rôle convenait bien à ce
baron allemand intrigant et besogneux, qui, à l'obstination massive
de ceux de sa race, mêlait les grâces persuasives, les manières
insinuantes, tout le raffinement vicieux d'un page de Versailles,
devenu un roué de la Régence.
On trouve quelques détails sur cette partie de sa vie dans un livre
publié à Londres en 1743 [51], à l'époque où Théodore, réfugié en
Toscane, était presque ouvertement un agent de l'Angleterre. Cet
ouvrage, écrit dans le but de favoriser les intrigues de Théodore, à
ce moment-là, m'a paru être plus sérieusement documenté sur les
antécédents politiques de Neuhoff que ses biographes du XIXe
siècle, trop pressés de s'en rapporter aux mémoires du colonel
Frédéric, un faussaire avéré.
D'après l'auteur du livre de 1743, le baron, avant de quitter Paris,
poursuivi par l'anathème de Madame, aurait rendu à certains
ministres étrangers des services importants que ceux-ci lui payaient;
même, il ne serait pas impossible qu'il fut, dès cette époque, entré
en rapport avec Gœrtz, qui se trouvait à Paris au commencement de
1717 [52].
Quand il fut obligé de quitter la France, Neuhoff, d'après le livre
anglais, n'aurait eu d'autres ressources que dans les intrigues
auxquelles il fut mêlé. Gœrtz, alors ministre du roi de Suède en
Hollande, avait été arrêté à Arnheim, sur la demande du roi
d'Angleterre. Les Anglais accusaient Gœrtz de conspirer avec les
jacobites afin d'amener une révolution en Angleterre. Le comte de
Gyllenborg, ministre de Suède à Londres, fut arrêté en même temps.
Le duc d'Orléans obtint, par ses démarches, la mise en liberté des
ministres suédois [53]. Le Régent affectait de ne pas croire à ce
complot; il persuada à Georges Ier que le roi de Suède n'y avait pris
aucune part. En réalité, la présence de Gœrtz, en Hollande, était
motivée par une négociation délicate; il s'agissait de traiter avec le
tzar Pierre Ier, qui se trouvait dans les Pays-Bas, d'une paix séparée
entre la Suède et la Russie. Le baron de Neuhoff aurait été chargé
de porter à Gœrtz des dépêches relatives à cette négociation [54].
Malgré sa jeunesse,—il avait alors 24 ans—Théodore remplit si bien
sa mission et sut se rendre si agréable au ministre, que celui-ci le
prit pour secrétaire et bientôt après pour son «principal
confident [55]».
Dans les derniers mois de 1718, Gœrtz envoya Neuhoff en mission
auprès d'Alberoni. A peine avait-il entamé les négociations que le roi
de Suède mourut [56]. Bientôt après, Gœrtz était décapité [57].
Théodore se «trouva donc sans ressources dans un pays dont il
ignorait la langue, et privé de l'appui de la maison d'Orléans,
puisqu'il était entré dans des plans qui portaient préjudice aux
intérêts de cette famille [58]».
Cependant Théodore devait encore surnager après ce nouveau
naufrage.
La Cour d'Espagne, remplie d'intrigues d'antichambre, avec une
dynastie nouvelle et étrangère qu'entourait une foule d'aventuriers
cosmopolites, constituait bien le milieu voulu pour l'ambition inquiète
et peu scrupuleuse du petit baron de Westphalie. Ripperda, qui, plus
tard, devait devenir premier ministre, commençait à jouir d'une
grande faveur à l'Escurial. Fidèle à ses ondoyants principes,
l'intrigant habile qu'était Neuhoff ne manqua pas d'aller lui faire sa
cour. Ils se plurent. Ripperda, dit-on, lui fit obtenir le grade de
colonel avec une pension de six cents pistoles [59].
Mais Neuhoff n'avait pas renoncé à ses goûts dispendieux. Il était
souvent gêné, et Alberoni dut, à plusieurs reprises, lui venir en aide.
La fortune cependant lui sourit encore. Sur les conseils de Ripperda
et grâce à son appui, il épousa une des demoiselles d'honneur de la
reine d'Espagne, lady Sarsfield, fille de lord Kilmallock, jacobite
réfugié à Madrid, parent du duc d'Ormond [60].
Ce mariage, qui aurait dû fixer Théodore, paraît avoir été une
déception pour lui. Il fut quelque chose de plus pour sa femme. Lady
Sarsfield était laide et vaniteuse; l'ancien page de Madame était
volage, et milady n'avait rien de ce qu'il fallait pour retenir l'humeur
inconstante de son mari. Cela fit un déplorable ménage.
Rostini, dans ses Mémoires, dit ceci: «Théodore épousa, dit-on, une
parente du duc de Sales actuel, alors marquis de Monte Allegro.»
Or, en 1738, nous verrons le ministre du roi de Naples, le marquis de
Montalègre, accorder, à Théodore, sa protection d'une façon
absolue, surtout lors d'un incident touchant des vaisseaux hollandais
affretés par le baron. La protection qu'exerça à ce moment
Montalègre vis-à-vis de Théodore, est d'autant plus extraordinaire
que le bon droit n'était certes pas du côté de l'aventurier.—Les
dépêches diplomatiques de Montalègre, en 1738, sont, la plupart du
temps, signées: El marques de Salas.
Alberoni était tombé du pouvoir, méprisé de l'Europe entière.
Neuhoff perdait en lui un protecteur puissant. Ripperda, cependant,
lui restait; mais Théodore, qui ne pouvait s'astreindre à un genre de
vie en rapport avec ses moyens, eut encore des besoins d'argent qui
le perdirent.
On raconte que Ripperda lui ayant confié des sommes importantes
pour le règlement de fournitures militaires, il les détourna pour ses
dépenses personnelles [61].
Quoiqu'il en soit, Neuhoff, à cette époque, quitta l'Espagne
subrepticement, abandonnant sa femme, grosse alors. La baronne
mourut à Paris en 1724, ainsi que sa fille née de ce mariage [62].
L'aventurier avait profité du séjour de sa femme à l'Escurial avec la
cour, pour quitter Madrid la nuit, en emportant tous ses bijoux. Il
s'embarqua à Carthagène pour la France, et bientôt il arriva à
Paris [63].
A la chute d'Alberoni, Théodore, ne sachant que devenir, avait écrit à
la duchesse d'Orléans, pour la prier de le reprendre à son service.
Madame ne répondit pas; mais à peine débarqué à Paris, l'aventurier
sollicita de nouveau son ancienne protectrice. Celle-ci lui fit défendre
de se présenter devant elle. La princesse, un jour, se rendait aux
Carmélites; son carrosse croisa une voiture dans laquelle se trouvait
Théodore. Madame s'écria: «Voilà cet honnête garçon de Neuhoff!»
Il entendit l'apostrophe, baissa les yeux et pâlit [64].
Paris était alors en pleine fièvre de spéculation. Law faisait merveille
avec son Système.
La fureur de l'agiotage avait pénétré dans toutes les classes de la
société. Il y avait là de quoi tenter l'esprit aventureux de Neuhoff,
toujours harcelé par les besoins d'argent; mais il est peu probable,
comme certains l'ont prétendu, que Théodore soit entré en relations
directes avec Law. L'Ecossais d'origine obscure, devenu le grand
financier, dispensateur des deniers de l'État et de la fortune publique
en France, dont l'antichambre était encombrée de ducs, dont la
femme parlait toilette avec les princesses, dont le fils, qu'on appelait
le Chevalier Système [65], fréquentait la jeunesse dorée de la cour,
n'avait pas le temps de se commettre avec le baron westphalien. Les
aventuriers, quand ils sont arrivés, dédaignent leurs semblables. Que
Théodore ait spéculé, comme tout le monde, à l'époque, c'est très
probable, mais non pas avec Law lui-même, alors à l'apogée de sa
puissance. Peut-être, en intrigant habile, sût-il se faufiler dans
l'entourage du financier. Madame rapporte, en effet, que la rumeur
publique accusait son ancien page d'avoir pris un million au frère de
Law [66].
Le livre anglais, que j'ai déjà cité, dit qu'il eût à Paris plusieurs
aventures étranges. Il avait rompu avec la plupart de ses anciens
amis qui le connaissaient trop, mais il parvint à entrer en rapports
avec quelques personnes de distinction qui le connaissaient moins.
Ses relations avec Alberoni et Ripperda, les ennemis de la famille
d'Orléans, lui fermaient les portes de la cour. Il ne s'attarda pas à
rentrer en grâce auprès de Madame, qui, du reste, l'avait rejeté de la
façon la plus formelle. Il aima mieux devenir un courtier marron de
la diplomatie. C'était un emploi qui lui convenait à merveille. La
délicatesse ne l'embarrassait pas; aucun principe ne le gênait; il
n'avait qu'un but: se procurer de l'argent.
Le baron qui, de bonne heure, avait été à l'école des Gœrtz, des
Alberoni et des Ripperda, trouva le moyen de donner à quelques
ministres étrangers des renseignements qui lui furent très bien
payés. Il entra également en correspondance avec des diplomates
du dehors. Sans lui créer une position définie, ni surtout avouable,
ces manœuvres lui fournirent les moyens de subvenir à ses besoins
toujours fort grands. Mais ces choses-là ne peuvent pas durer; on se
lasse vite d'un agent louche. Théodore savait que tout ce qu'il faisait
pouvait le mener en prison, et l'ombre de la Bastille le hantait. Il
résolut donc de quitter Paris, et, d'après le livre anglais, il serait parti
deux jours seulement avant que ses intrigues ne fussent
découvertes. Il aurait gagné la Hollande en emportant divers secrets
surpris dans les antichambres diplomatiques qu'il fréquentait,
entr'autres toute la trame d'une mystérieuse négociation engagée à
Turin et dont il comptait se servir auprès de la cour impériale pour
en tirer profit [67].
Madame, qui avait l'âme d'un greffier, donne une autre version du
départ de Théodore; les motifs en sont encore moins honorables.
Neuhoff, dans un moment de détresse, ne sachant que devenir,
aurait fait un sérieux retour sur lui-même. Désirant rentrer en grâce
auprès de sa famille, il confessa ses erreurs passées et promit de
mener, à l'avenir, une vie régulière, plus conforme à son rang de
gentilhomme. Durant un certain temps, il se conduisit bien. Il était
reçu chez sa sœur [68]. Un lieutenant-colonel du régiment de La
Marck, beau-frère de la comtesse d'Appremont, rencontra plusieurs
fois Théodore à dîner chez Mme de Trévoux [69].
Un jour, Théodore déclare qu'il a reçu des lettres lui annonçant que
sa femme, quittant l'Espagne, était en route pour Paris. Il lui paraît
convenable d'aller à sa rencontre. Sous ce prétexte, il part pendant
la nuit. «Le matin, on découvre qu'il a tout enlevé à sa sœur et à
son beau-frère. Il leur a pris deux cent mille livres. Personne ne sait
de quel coté il a passé. Sa sœur, Mme de Trévoux, est
désespérée [70].»
Je n'ai pu trouver nulle part la confirmation de ce vol.
Quoiqu'il en soit, il est certain que Théodore quitta Paris vers le
milieu de 1720, et arriva en Hollande. A La Haye, il se serait rendu
auprès du ministre impérial. Il lui remit un pli en le priant de le faire
tenir d'une façon sûre au comte de Zinzendorf, chancelier de Charles
VI. Les explications qu'il donna à l'ambassadeur autrichien furent
sans doute très explicites, car la réponse de Vienne ne se fit pas
attendre. Elle consistait en une lettre de change de cinq mille florins.
Les renseignements dérobés à Paris, au sujet de la mystérieuse
négociation entamée à Turin, auraient été reconnus exacts à Vienne
et seraient arrivés dans un moment opportun: d'où la récompense
immédiate [71]. Théodore était, ce qu'on pourrait appeler, un
crocheteur de la diplomatie.
Puis il se serait mis en rapport avec un personnage, de passage en
Hollande, et qui allait à Londres représenter une petite cour
allemande. Ce personnage passait pour un très habile homme, mais
Théodore était plus fin encore. Il ne tarda pas à reconnaître que les
capacités qu'on prêtait au diplomate étaient toutes en façade. Se
sentant plus apte à remplir les fonctions destinées au ministre
allemand, Neuhoff aurait tenté de le supplanter en allant lui-même à
Londres; mais ses manœuvres furent découvertes, et l'homme qu'il
cherchait à léser partit pour l'Angleterre après avoir raconté son
histoire partout, ce qui fit du tort à Théodore. Personne ne voulut
plus l'employer.
La misère vint alors. L'argent fondait entre ses mains; partout il avait
des créanciers.
En attendant un emploi, il apprit l'anglais. L'historien anonyme nous
dit que «jamais, sauf M. de Voltaire, aucun étranger n'arriva aussi
bien ni aussi vite à comprendre l'anglais». Mais, malgré toute son
intelligence, il était à bout de ressource et de crédit. Pour se
procurer le pain quotidien, il se fit virtuose, chimiste, «connoisseur
en painture». Ces diverses tentatives ne furent pas couronnées de
succès. Ni la musique, ni les sciences, ni la critique d'art ne lui
donnèrent les moyens de subvenir à ses besoins [72]. Bien des
hommes, avant de trouver leur voie, se sont essayés dans les
différentes branches de l'activité humaine: professions, métiers ou
arts. Je ne crois pas qu'il s'en soit jamais trouvé un seul qui ait
poussé ces essais plus loin que Théodore, puisqu'il devait aller
jusqu'à la royauté, métier qui d'ailleurs ne lui donna pas de quoi
vivre.
Si à Paris la Bastille troublait son sommeil, en Hollande il voyait se
dresser devant lui la prison pour dettes. La diplomatie lui fournit de
nouveau quelques ressources ou tout au moins lui permit de fuir ses
créanciers. Un personnage, établi dans les Pays-Bas, cherchait pour
le compte de l'Empereur un homme retors et habile, capable
d'accomplir une mission secrète en Italie. Il s'agissait de découvrir
les intrigues que, disait-on, la France et l'Espagne entretenaient dans
la péninsule. Le personnage trouva son homme en Théodore. Celui-
ci partit. Il s'embarqua dans l'île de Voorne, et deux ou trois mois
après on le vit parcourant l'Italie [73].
Ce pays, partagé en petits États, livré à toutes les convoitises
étrangères, neuf pour lui, ouvrait un vaste champ à son ambition
mal équilibrée. Que fit-il réellement en Italie? La question est difficile
à résoudre. La renommée ne l'avait pas atteint encore et les
certitudes manquent sur cette période de sa vie. La mission dont il
aurait été chargé était sans doute peu importante, mais, pendant
son séjour en Italie, Théodore allait faire des relations qui devaient
avoir une singulière influence sur sa destinée.
On vit Neuhoff à Rome et on sut plus tard qu'il s'y faisait appeler le
baron Etienne Romberg [74]. Dans cette ville, il fit la connaissance des
dames Fonseca, religieuses au couvent des Saints Dominique et
Sixte, qui eurent toujours une foi aveugle dans l'aventurier et qui
devaient le soutenir avec le plus touchant dévouement dans
l'adversité. Il connut aussi à Rome un marquis, un comte, un docteur
ès-lois, un simple drapier, toujours en quête de nouvelles protections
ou à l'affût de dupes faciles. Son imagination, jamais à court, le
poussa à se lier avec un moine qui cherchait le secret de la pierre
philosophale [75].
C'était un de ces moines errants, comme il y en avait beaucoup en
Italie. Ces religieux, rejetés d'un couvent, réfugiés dans un autre qui
ne les gardait pas, vagabonds allant de cloître en auberge, étaient
de tristes hères qui formaient ce que l'on pourrait appeler la bohême
de l'église. Beaucoup étaient des détraqués tombés dans la magie
noire, le grand œuvre et l'escroquerie.
Mais Théodore était l'homme des résultats positifs, tangibles et
immédiats. Il avait bien pu s'en aller, le soir, dans les ruelles
sombres, enveloppé d'un long manteau, retrouver son moine
alchimiste. Tous deux, penchés sur les fourneaux mal éclairés d'une
cire jaune, ils avaient pu épier le mystérieux travail de l'athanor et
des cornues, au milieu de vieux grimoires à demi-rongés par les rats
et couverts de fils d'araignée. Mais, comme la transmutation était
lente, l'impatient baron se lassa. Il dit adieu au moine alchimiste et à
la pierre philosophale et courut à Florence, toujours inquiet,
furetant, combinant.
En 1727, Théodore se trouvait de nouveau à Paris. Un décret de
prise de corps pour dettes fut rendu contre lui [76]. Il s'enfuit assez à
temps pour éviter la prison.
Vers la même époque, il parut à Londres. Il aurait pris logement aux
Armes d'Ipswich, dans Cullum Street, puis dans un café où il se
serait tenu caché. Jamais il ne sortait, restant au lit, sous prétexte
de maladie [77]. Craignait-il encore la poursuite de créanciers? C'est
probable. Un rapport de police rapporte qu'il aurait filouté des
marchands de Londres et qu'il aurait été obligé de fuir en toute
hâte [78].
Le baron de Neuhoff reparut bientôt en Italie. On a prétendu
qu'alors il aurait trouvé de puissants protecteurs à la cour du grand-
duc de Toscane et qu'il aurait été «sur le point de lever un régiment
pour le compte de l'Empereur [79]». Comme état de services, il faut
avouer que cette quasi mission mérite peu d'être signalée. Mais ce
n'est pas sans surprise qu'on lit dans le même auteur qu'en 1732
Théodore était résident de l'empereur Charles VI, à Florence [80]. Le
fait est matériellement faux. Ce qui est plus vraisemblable, c'est
l'histoire qui, vers la même époque, aurait signalé son passage à
Livourne. Ce fut un coup de commerce, avatar assez naturel dans
lequel réapparaissait le petit fils du drapier liégeois. En réalité, il fit
une nouvelle dupe. Il y eut quelque mérite. Sa victime fut un
banquier de Livourne, nommé Jabach.
Les historiographes de Théodore ont dit que les Jabach étaient juifs.
Il n'en est rien. Ils appartenaient à une famille de riches banquiers
de Cologne, véritable dynastie financière qui donna, entr'autres, le
fameux Everhard Jabach, qui fut connu à Paris comme banquier et
collectionneur, au XVIIe siècle [81]. Les membres de cette famille,
disséminés en France et en Italie, étaient catholiques. Quelques-uns
d'entre eux avaient fait leurs études chez les jésuites de Cologne.
Jean Engelbert Jabach fut chanoine capitulaire de l'archevêché de
Cologne, chancelier de l'Université de cette ville, et le Pape lui
conféra la dignité de protonotaire. François-Antoine fut banquier à
Livourne où il mourut en 1761 [82].
Ce fut avec ce dernier, sans doute, que Théodore eût des rapports
dont la maison Jabach ne paraît pas avoir eu à se louer.
Neuhoff, dont la famille avait des attaches à Cologne (son cousin
Drost y était grand commandeur de l'Ordre Teutonique), avait dû
trouver des facilités pour nouer des relations avec ses riches
compatriotes établis à Livourne.
A cette époque, un banquier était déjà un personnage important et
méfiant, peu accessible aux entreprises chimériques. Mais le baron
avait un talent particulier d'insinuation. Soit qu'il se laissât prendre
aux belles paroles de l'aventurier, soit qu'il y fut poussé par d'anciens
souvenirs de famille, Jabach avança à Théodore des sommes
importantes sous prétexte d'affaires commerciales. Le banquier
s'aperçut vite qu'il était trompé, et, ne pouvant rentrer dans ses
découverts, il fit mettre son client en prison. Celui-ci tomba malade
et on dut le transférer à l'hôpital.
Comment désintéressa-t-il son créancier? Il est probable que Jabach
eût pitié de lui et qu'il ne poursuivit pas la contrainte. Toujours est-il
qu'au sortir de l'hospice, Théodore ne réintégra pas la prison. Il
continua sa vie errante à la poursuite de la fortune.
C'est ainsi qu'il arriva à Gênes.
Le livre anglais, auquel j'ai déjà fait plusieurs emprunts, nous dit que
Neuhoff était chargé par la cour impériale de prendre des
renseignements aussi précis que possible sur l'état de la Corse.
Charles VI, après être intervenu dans les affaires de l'île, recevait de
ses agents des rapports bien différents et inexacts. Le baron ayant
appris que les représentants des Corses étaient Ceccaldi et Raffaelli,
se serait abouché avec eux. Ce fut à la suite d'un rapport de
Théodore, adressé à Vienne, que l'Empereur aurait ordonné au
prince de Wurtemberg de conclure avec la république un traité qui,
tout en laissant la Corse aux Génois, donnerait quelques libertés aux
insulaires [83].
Il est plus vraisemblable de penser que Théodore à ce moment-là
était un agent secret du duc François de Lorraine, gendre de Charles
VI. L'époux de Marie-Thérèse se commettait volontiers avec les
aventuriers, qu'il recevait dans les pièces les plus intimes de ses
appartements. Il écoutait les propositions les plus extraordinaires. Il
avait une politique à lui, qui s'élaborait en secret avec des agents
interlopes. Ayant des vues de mesquine ambition sur la Corse, il était
entré en rapports avec le baron [84]. Il nous faudra revenir sur les
projets louches de François de Lorraine.
Il est d'ailleurs certain que les entrevues de Neuhoff avec les Corses
n'eurent pas le caractère presque officiel que leur donne le livre
anglais. Elles furent au contraire entourées du plus grand mystère.

III

Théodore changeait souvent de déguisement; c'était une nécessité


pour lui. Il laissait des dettes partout où il passait, et il lui fallait
s'ingénier à dépister des créanciers assez indiscrets pour chercher à
le découvrir. En 1732, à Gênes, il s'était transformé en milord
anglais.
Un certain Ruffino, corse, natif de Farinole, frère lai franciscain, de
l'ordre appelé Observantin dans l'île, habitait Gênes depuis
longtemps. C'était un de ces moines chirurgiens comme on en voyait
beaucoup alors. Praticiens peu habiles et ignorants, ils gagnaient
leur misérable existence à faire quelques menues opérations,
apprises par routine. Ruffino se rendait souvent au Grand Hôpital où
il exerçait son art rudimentaire.
Un jour il rencontra le milord. Le hasard fut-il la seule cause de cette
rencontre? Y eut-il d'un côté ou de l'autre un calcul? On ne saurait le
dire. Toujours est-il que le moine et l'Anglais se plurent. Ils parlèrent
politique et la conversation tomba fort à propos sur les affaires de
Corse [85].
Sans prendre aucune précaution oratoire, le milord déclara au
religieux qu'il avait les moyens et le pouvoir de délivrer l'île de
l'oppression génoise; mais Gênes était un mauvais endroit pour
parler politique et surtout des choses de Corse, «de même qu'à
Babylone on ne chantait pas les cantiques sacrés et que les chefs du
peuple élu n'étaient pas libres pour traiter». Théodore conseilla donc
à Ruffino d'aller à Livourne. Il se rendit également dans cette
ville [86]. Ils purent désormais causer à l'aise, à l'abri des espions dont
les rues de Gênes étaient remplies.
Le moine s'aboucha avec Ceccaldi, Giafferi et Aitelli. Ces corses, qui
sortaient des prisons de la Sérénissime République, était animés
d'un vif ressentiment à l'égard des Génois. Ruffino leur parla du
milord avec enthousiasme. Théodore l'avait complètement
convaincu, et il le représenta aux chefs comme le «Rédempteur» du
peuple corse. Les insulaires attendaient un Messie; le milord arrivait
à propos. Le moine le mit en rapport avec ses amis; Neuhoff fit sans
doute connaître, alors, sa véritable identité. Il eut avec les chefs de
nombreuses et longues conférences. Quels arguments fit-il valoir?
Par quels artifices parvint-il à persuader aux Corses qu'il avait le
pouvoir de délivrer leur pays? On l'ignore [87]. Toujours est-il qu'ils
furent bien convaincus que le moine ne les avait pas trompés, et
qu'ils tenaient, enfin, un «Rédempteur».
Théodore possédait une grande facilité d'élocution; il était insinuant
et il savait mentir avec cet aplomb et cette force de persuasion qui
en impose. Arrivé à ce degré, le mensonge est un art; il y était
maître. Et puis, les Corses se trouvaient dans une disposition d'esprit
où ils ne demandaient qu'à être convaincus. Le baron leur parla,
sans doute, des secours qu'il se faisait fort d'obtenir de certaines
puissances. C'était toucher la corde sensible; car les insulaires
avaient cette idée fixe: obtenir l'aide d'un grand état quelconque. Il
leur promit aussi probablement des canons, des fusils, de la poudre
et des balles. Les Corses possédaient un goût très prononcé pour
toutes sortes d'engins de guerre; du reste, ils avaient besoin de
munitions pour faire la guerre aux Génois et les chasser de l'île. Il
dut encore laisser entrevoir à ses nouveaux amis qu'il avait
beaucoup d'argent à sa disposition; c'est un argument qui a toujours
été décisif. Bref, il n'oublia rien de ce qui constituait son rôle de
sauveur. Il se montra ému des malheurs du peuple corse; il parut,
aux chefs, généreux, grand, superbe. Et comme ils étaient arrivés à
un moment où ils avaient besoin de croire en quelqu'un et d'espérer
en quelque chose, ils crurent en ce faux milord; ils espérèrent qu'il
leur donnerait la liberté.
Les conférences de Théodore avec les Corses peuvent
vraisemblablement se résumer ainsi. Il est probable encore que ces
réunions ne se terminèrent pas sans que, de part et d'autre, on eût
pris «certains engagements» [88].
Quand il fut décidé que la Corse serait sauvée par le baron de
Neuhoff, on annonça la chose au comte de Charny, commandant des
troupes espagnoles arrivées quelque temps auparavant avec l'infant
Don Carlos. On fit croire au général que le baron agissait pour le
compte de l'Angleterre [89]; mais en attendant que la Corse fût
délivrée, le pauvre frère Ruffino fut arrêté et mis en prison. Il est
toujours dangereux de vouloir sauver un peuple. Théodore jugea
prudent de ne pas insister; il partit pour Florence [90].
Il est vraisemblable de supposer que, dès cette époque, il ait été en
relation à Livourne avec le chanoine Orticoni et avec Dominique
Rivarola [91], tous deux agents des Corses en Italie.
Que fit réellement Neuhoff pendant les quatre années qui suivirent
les entrevues de Livourne? Il les employa évidemment à préparer
son débarquement en Corse. On a prétendu que le grand-duc de
Toscane, Jean-Gaston de Médicis, lui aurait donné quelques sequins
et une lettre de recommandation pour un certain Buongiorno qui
exerçait la médecine à Tunis [92]. Il est vrai que Théodore a connu ce
Buongiorno à Tunis, soit sous les auspices de Jean-Gaston de
Médicis, soit de toute autre façon.
On a prétendu aussi que le baron, en quittant la Toscane, serait allé
à Constantinople où il aurait été en rapport avec François Rakoczy,
prince de Transylvanie, et avec le comte de Bonneval, un aventurier
fameux qui, après avoir couru le monde, finit par prendre le turban
et le nom d'Achmet-Pacha. On a échafaudé tout un roman sur les
relations de Théodore avec ces deux personnages [93]. Il était digne
d'être l'ami de Bonneval, ce grand agité, qui fut enterré dans un
couvent de derviches tourneurs!
On a dit encore que Neuhoff avait été reçu presque solennellement
par le bey de Tunis. Le gouvernement ottoman aurait même ordonné
au bey, non seulement d'encourager les projets du baron, mais
encore de lui fournir des armes et des munitions, de mettre enfin un
trésor à sa disposition [94]. L'entreprise se présente ainsi sous un
aspect imposant. Il y aurait eu là un effort considérable pour chasser
les Génois de l'île, et très certainement cet effort eut pu être
couronné de succès. Mais tout cela rentre dans le domaine de la
légende. Théodore ne fut jamais officiellement accrédité à Tunis. Il
ne vit pas le bey. Celui-ci ne lui fournit aucun secours. Il est certain
que le débarquement théâtral du baron de Neuhoff, à Aléria, fut
machiné à Tunis; ce fut de Tunis qu'il partit; mais les préparatifs de
l'entreprise n'eurent pas cette envergure qu'on leur prête.
Grâce à un document qui se trouve dans les archives d'État à Gênes,
nous avons des renseignements précis sur le séjour de Théodore à
Tunis et sur ses intrigues [95]. Les faits rapportés sont tellement
conformes à sa manière d'agir qu'il faut nous en tenir à ce
document.
Cette pièce est cotée sous ce titre:
Copia delle deposizioni fatte nella cancelleria del illustrissimo
magistrato del Riscatto de' schiavi.—Ribellione de' Corsi, filza

É
11/3009. Archives d'État de Gênes, archives secrètes.
Un bâtiment français, provenant de Livourne, débarqua, un jour à
Tunis, un personnage étranger. Ce personnage était le baron de
Neuhoff, qui alla, dès son arrivée, loger chez Léonard Buongiorno [96].
Fidèle à ses habitudes de prudence, Théodore conserva l'incognito
pendant un certain temps. Il fit répandre le bruit qu'il était venu à
Tunis pour racheter tous les Corses qui y gémissaient dans
l'esclavage. Ce rachat devait se faire avec de l'argent qu'il tenait d'un
legs pieux. Il eut de longues et sécrètes conférences avec
Buongiorno, avec le Père administrateur de l'hôpital espagnol et avec
le trésorier du bey.
Le but avoué de ces conférences était de débattre le prix des
esclaves. Mais comme on pouvait s'étonner de ne jamais voir le
charitable personnage donner le moindre argent, il déclara n'être
venu à Tunis que pour fixer le prix des Corses prisonniers. Les fonds
étaient déposés à Livourne. Quand on se serait mis d'accord, il irait
chercher l'argent qu'il rapporterait plus tard. Il aimait sans doute à
marchander, car les entrevues se multiplièrent. Mais Théodore et ses
trois compères parlaient certainement de toute autre chose que des
esclaves.
Buongiorno était sicilien. Il habitait Tunis avec sa famille depuis
plusieurs années. Chargé par sa nation de racheter des esclaves, il
avait conservé pour lui l'argent destiné à ce rachat. Après cette belle
action, il s'était bien gardé de retourner dans son pays. Les
malheureux siciliens avaient continué leur dur esclavage. Mais lui, il
avait ouvert un cabinet de médecin et il jouissait à Tunis d'une
certaine considération. Dans ce cabinet, on ne s'occupait pas
seulement de guérir les malades: on y faisait un peu de tout. Pour
l'instant, chez Buongiorno, entre un allemand, un sicilien, un
espagnol et un tunisien, s'élaborait le grand dessein d'arracher la
Corse à la tyrannie génoise!
Ripperda, alors réfugié au Maroc, aurait également trempé dans le
complot en essayant d'entraîner les Marocains dans une alliance
avec les Tunisiens pour favoriser l'entreprise de Neuhoff [97].
Théodore n'avait pas d'argent. Il essaya d'emprunter aux Français
quarante à cinquante mille francs; mais les Français ne se laissèrent
pas faire. Buongiorno aboucha son ami avec des marchands grecs.
Sous la caution du médecin et sous celle du Révérend Père
espagnol, il obtint diverses marchandises et munitions: trois caisses
de canons de fusils; deux caisses de lames de sabres; plusieurs
barils de poudre et de balles; mille cinq cents bottes turques, dont la
tige montait à mi-jambe. Le consul anglais, à Tunis, se serait
également porté garant du payement de ces marchandises. Ces
munitions furent embarquées sur un navire battant pavillon
britannique et commandé par le capitaine Dick, fils naturel du
consul.
Théodore racheta, également à crédit, deux esclaves corses,
promettant sur son honneur de les payer plus tard. Ce mode de
règlement était dans ses habitudes. Les deux corses se nommaient
Quilico Fascianello, d'Aléria, et Patrone Francesco, du Cap Corse. Ils
furent embarqués sur le bâtiment. Le frère du médecin, Cristoforo
Buongiorno, et un certain Bigani, fils du capitaine du bagne de
Livourne, faisaient aussi partie de l'expédition. Quand tout fut prêt,
Neuhoff monta sur le navire. Avant de s'embarquer, il donna son
véritable nom.
A peine le navire eut-il pris le large que le médecin Buongiorno fit
une déclaration dont le bruit se répandit bientôt à Tunis. Le baron
Théodore faisait voile vers la Corse avec armes et munitions pour
assister les insulaires. L'infant Don Carlos, d'Espagne, lui avait promis
son aide afin de délivrer l'île. Bientôt on devait voir arriver, sur les
côtes corses, plusieurs navires destinés à empêcher l'accès de l'île
aux Génois [98]. Ceux qui y demeureraient, n'ayant plus aucun
secours, seraient aisément chassés.
Pour un si grand projet, Neuhoff ne possédait que des moyens très
restreints: un peu d'argent et quelques munitions extorquées à des
trafiquants trop confiants; mais il avait confiance dans son étoile. Il
allait ceindre une couronne, et, pour la circonstance, il s'était revêtu
d'un beau costume oriental.

«Histoire des Révolutions de l'Île de Corse et de l'élévation de


Théodore Ier sur le trône de cet État.»
(La Haye, 1738.)
CHAPITRE II
Débarquement du baron de Neuhoff à Aléria.—Il est proclamé roi de Corse.
—Son couronnement.—Théodore Ier notifie son élévation à sa famille.—
Opinions et inquiétudes des diplomates.—Le roi nomme les grands
dignitaires de la Cour.—Jalousies et querelles des chefs corses.—Premières
opérations contre les Génois.—Trahison de Luccioni.—Sa condamnation et
son exécution.

Si certaines parties de la vie de Théodore sont restées dans une


obscurité d'où il est bien difficile, pour un historien scrupuleux, de
les faire sortir, par contre, je n'ose dire par compensation, les détails
abondent sur son arrivée en Corse.
A la nouvelle du débarquement d'un étranger à Aléria, la république
de Gênes, très alarmée, mit en mouvement tout son personnel
diplomatique et administratif pour avoir des renseignements sur cet
inconnu et sur sa famille. On peut facilement se rendre compte des
craintes qui s'emparèrent du gouvernement génois en compulsant
les volumineux dossiers concernant Théodore dans les archives
d'État à Gênes. Les inquisiteurs, le grand et le petit Conseil, la junte
de Corse, toutes ces différentes branches du gouvernement
s'occupèrent de lui. Sorba, ministre de Gênes à Paris, eut, au sujet
du baron, des conférences avec le cardinal Fleury, Chauvelin et
Maurepas.
L'opinion publique s'intéressa à l'aventure. Les gazettes publièrent
des articles sur cet événement à sensation. Un livre anonyme [99],
imprimé à La Haye, en 1738, chez Pierre Paupie [100], publia une
Relation de la descente d'un étranger en l'île de Corse. Cette relation
donna des détails qui furent d'accord avec les rapports des agents
génois.
On commença par se demander quel était le personnage qui se
trouvait à bord du bâtiment anglais [101]. Les gazettes mirent
plusieurs noms en avant: le fils aîné du chevalier de Saint-Georges,
le prince Rakoczy, le duc de Ripperda [102], le comte de Bonneval [103].
On finit par savoir que l'inconnu s'appelait Théodore, baron de
Neuhoff, gentilhomme westphalien; mais comme ce nom, par lui-
même, n'évoquait pas l'idée d'une force suffisante pour accomplir les
grandes choses dont ce débarquement devait être le prélude, on
chercha à savoir quelles combinaisons il pouvait bien y avoir derrière
tout cela. Le chemin était ouvert aux suppositions. On entrevoyait
que de graves desseins allaient bientôt être mis à exécution sous le
couvert de cet agent.

Jusqu'au commencement du XVIIIe siècle, «la Corse était à peu près


aussi inconnue que la Californie et le Japon» [104]. L'Europe
cependant commençait à tourner les yeux du côté de cette île, non
qu'elle s'intéressât beaucoup aux démêlés de la république de Gênes
avec ses sujets, mais la Corse, par sa position, formant pour ainsi
dire l'avant-poste de l'Italie, pouvait faire naître les convoitises les
plus explicables, comme les craintes les mieux justifiées, surtout au
milieu de cette paix mal définie qui suivit la guerre de la succession
d'Espagne.
Le vaisseau anglais était muni d'un passe-port délivré par le consul
anglais à Tunis. Aléria avait été choisi pour attérir parce que ce port
était dans la possession des mécontents. Le navire tira quelques
salves auxquelles l'écho du maquis seul répondit.
Les moindres détails concernant les grands personnages ont
toujours eu de l'attrait pour la foule. Le 12 mars 1736, Théodore
entrait dans l'histoire; on ne savait pas encore quel rôle il allait jouer,
mais il était intéressant de connaître le costume qu'il portait. Il était
vêtu, dit le chroniqueur de La Haye, «d'un long habit d'écarlate
doublé de fourrure, couvert d'une perruque cavalière et d'un
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like