Skip to content

Commit 6531416

Browse files
authored
Merge pull request #2110 from sdamghan/yosys_vtr_dsp
Providing Yosys Frontend with the Declaration of Custom Complex Blocks
2 parents b992351 + 5dbdb9f commit 6531416

File tree

12 files changed

+315
-16
lines changed

12 files changed

+315
-16
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ ODIN_II/usefull_tools/**/track_completed
105105
#
106106
Yosys
107107

108+
#
109+
#ArchFPGA exec dir
110+
#
111+
ArchFPGA
112+
108113
#
109114
#Python
110115
#

doc/src/yosys+odin/dev_guide/contributing.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ If no architecture is passed in, Odin-II will create the soft logic and use LUTs
156156
However, if an architecture is passed, Odin-II will map accordingly to the available hard blocks and LUTs.
157157
It uses a combination of soft logic and hard logic.
158158

159+
.. note::
160+
161+
Please visit the Yosys's `Developers Guide <https://docs.verilogtorouting.org/en/latest/yosys/dev_guide/#working-with-complex-blocks-and-how-to-instantiate-them?>`_ for more information about how Yosys deals with the complex blocks defined in the VTR architecture file.
162+
159163
With the integration of Yosys+Odin-II, the Odin-II partial mapping features such as hard/soft logic trade-offs become available for a Yosys elaborated circuit.
160164
For instance, using optimization command arguments, a user can force the partial mapper to infer at least a user-defined percentage of multipliers in soft logic.
161165

doc/src/yosys/dev_guide.rst

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ Changes applied to the VTB files are outlined as follows:
2828
The LUT size is considered the one defined in the architecture file as the same as the regular VTR flow
2929

3030

31-
How to add new changes?
32-
-----------------------
31+
Working with Complex Blocks and How to Instantiate them?
32+
-------------------------------------------------------
3333

3434
The Yosys synthesis commands, including the generic synthesis and additional VTR specific configurations, are provided
3535
in `synthesis.tcl <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/synthesis.tcl>`_. To make changes in the overall Yosys synthesis flow, the `synthesis.tcl <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/synthesis.tcl>`_
@@ -42,10 +42,31 @@ the `yosys_models.v <https://github.com/verilog-to-routing/vtr-verilog-to-routin
4242

4343
Except for `single_port_ram.v <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/single_port_ram.v>`_ and `dual_port_ram.v <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/dual_port_ram.v>`_ Verilog files that perform the depth splitting
4444
process, the other files are defined as black-box, i.e., their declarations are required while no definition is needed. To add new black-box
45-
components, developers should first provide the corresponding Verilog files similar to the `adder.v <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/adder.v>`_. Then, a new `read_verilog -lib TTT/NEW_BB.v`
45+
components manually, developers should first provide the corresponding Verilog files similar to the `adder.v <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/adder.v>`_. Then, a new `read_verilog -lib TTT/NEW_BB.v`
4646
command should be added to the Yosys synthesis script. If there is an implicit inference of the new black-box component, the `yosys_models.v <https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/misc/yosyslib/yosys_models.v>`_
4747
Verilog file must also be modified, as mentioned earlier.
4848

49+
It is worth noting that the VTR flow scripts for running Yosys standalone as the VTR frontend are designed to automatically provide the black box declaration of complex blocks defined in the architecture XML file for Yosys.
50+
Technically, by running the ``run_vtr_flow.py`` script with the Yosys frontend, the ``write_arch_bb`` routine, defined in the ``libarchfpga``, is executed initially to extract the information of complex blocks defined in the architecture file.
51+
Then, the routine generates a file, including the black box declaration of the complex blocks in the Verilog format.
52+
The output file is named ``arch_dsps.v`` by default, found in the project destination directory.
53+
54+
Instantiation of complex blocks is similar to the explicit instantiation of VTR primitives in HDL format.
55+
The ``write_arch_bb`` generates a Verilog module with the same name as the complex block model.
56+
Module ports are also defined according to the port declaration provided in the architecture file.
57+
For instance, the HDL instantiation of the ``multiply_fp_clk`` complex block defined in the ``COFFE_22nm/k6FracN10LB_mem20K_complexDSP_customSB_22nm.xml`` architecture file is as follows:
58+
59+
.. code-block:: verilog
60+
...
61+
multiply_fp_clk instance_name(
62+
.b(i_b), // input [31:0] b
63+
.a(i_a), // input [31:0] a
64+
.clk(i_clk), // input [0:0] clk
65+
.out(i_out) // output [31:0] out
66+
);
67+
...
68+
69+
**Algorithm 1** - Custom Complex Blocks HDL Instantiation
4970

5071
Yosys Synthesis Script File
5172
---------------------------
@@ -135,4 +156,4 @@ Yosys Synthesis Script File
135156
# ZZZ will be replaced by run_vtr_flow.pl
136157
write_blif -true + vcc -false + gnd -undef + unconn -blackbox ZZZ
137158
138-
**Algorithm 1** - The Yosys Tcl Script File
159+
**Algorithm 2** - The Yosys Tcl Script File

libs/EXTERNAL/libyosys/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ add_custom_target(yosys ALL DEPENDS ${LIB_FILE} ${BINARY_LIB_FILE})
3939

4040
# create an library target out of the library compilation result
4141
add_library(libyosys SHARED IMPORTED GLOBAL)
42-
add_dependencies(libyosys yosys)
42+
43+
# adding dependency to libarchfpga, as it is required
44+
# by VTR scripts for Yosys standalone frontend
45+
add_dependencies(libyosys yosys libarchfpga)
4346

4447
# specify where the library is and where to find the headers
4548
set_target_properties(libyosys

libs/libarchfpga/CMakeLists.txt

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ cmake_minimum_required(VERSION 3.9)
22

33
project("libarchfpga")
44

5-
file(GLOB_RECURSE EXEC_SOURCES src/main.cpp)
5+
file(GLOB_RECURSE READ_ARCH_EXEC_SRC src/main.cpp)
6+
file(GLOB_RECURSE WRITE_ARCH_BB_EXEC_SRC src/write_arch_bb.cpp)
67
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
78
file(GLOB_RECURSE LIB_HEADERS src/*.h)
89
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
910

1011
#Remove test executable from library
11-
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
12+
list(REMOVE_ITEM LIB_SOURCES ${READ_ARCH_EXEC_SRC} ${WRITE_ARCH_BB_EXEC_SRC})
1213

1314
#Create the library
1415
add_library(libarchfpga STATIC
@@ -31,16 +32,40 @@ target_link_libraries(libarchfpga
3132
target_compile_definitions(libarchfpga PUBLIC ${INTERCHANGE_SCHEMA_HEADERS})
3233

3334
#Create the test executable
34-
add_executable(read_arch ${EXEC_SOURCES})
35+
add_executable(read_arch ${READ_ARCH_EXEC_SRC})
36+
add_executable(write_arch_bb ${WRITE_ARCH_BB_EXEC_SRC})
3537
target_link_libraries(read_arch libarchfpga)
38+
target_link_libraries(write_arch_bb libarchfpga)
3639

3740
#Supress IPO link warnings if IPO is enabled
3841
get_target_property(READ_ARCH_USES_IPO read_arch INTERPROCEDURAL_OPTIMIZATION)
42+
get_target_property(WRITE_ARCH_BB_USES_IPO write_arch_bb INTERPROCEDURAL_OPTIMIZATION)
3943
if (READ_ARCH_USES_IPO)
4044
set_property(TARGET read_arch APPEND PROPERTY LINK_FLAGS ${IPO_LINK_WARN_SUPRESS_FLAGS})
4145
endif()
46+
if (WRITE_ARCH_BB_USES_IPO)
47+
set_property(TARGET write_arch_bb APPEND PROPERTY LINK_FLAGS ${IPO_LINK_WARN_SUPRESS_FLAGS})
48+
endif()
49+
50+
install(TARGETS libarchfpga read_arch write_arch_bb DESTINATION bin)
4251

43-
install(TARGETS libarchfpga read_arch DESTINATION bin)
52+
#
53+
# install executables in the VTR source root directory
54+
# to utilize them for scripts running VTR flow
55+
#
56+
set(ARCHFPGA_DIR ${VTR_SOURCE_DIR}/ArchFPGA)
57+
# making a new custom target out of libarchfpga to automatically perform
58+
# the house keeping for end users by deleting the ArchFPGA dir in the
59+
# VTR root dir if it exists and holds expired execs
60+
add_custom_target(archfpga-execs ALL
61+
DEPENDS read_arch write_arch_bb
62+
COMMAND ${CMAKE_COMMAND} -E
63+
remove_directory ${ARCHFPGA_DIR}
64+
COMMAND ${CMAKE_COMMAND} -E
65+
make_directory ${ARCHFPGA_DIR}
66+
COMMAND ${CMAKE_COMMAND} -E
67+
copy_directory ${CMAKE_CURRENT_BINARY_DIR} ${ARCHFPGA_DIR}
68+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
4469

4570
#
4671
# Unit Tests

libs/libarchfpga/src/main.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
#include "vtr_error.h"
1313
#include "vtr_memory.h"
1414

15+
#include "arch_util.h"
1516
#include "read_xml_arch_file.h"
1617
#include "echo_arch.h"
1718

1819
void print_help();
1920

2021
int main(int argc, char** argv) {
2122
try {
22-
t_arch* arch = (t_arch*)vtr::calloc(1, sizeof(t_arch));
23+
t_arch arch;
2324
std::vector<t_physical_tile_type> physical_tile_types;
2425
std::vector<t_logical_block_type> logical_block_types;
2526

@@ -43,12 +44,17 @@ int main(int argc, char** argv) {
4344
printf("Reading in architecture\n");
4445

4546
/* function declarations */
46-
XmlReadArch(argv[1], atoi(argv[2]), arch, physical_tile_types, logical_block_types);
47+
XmlReadArch(argv[1], atoi(argv[2]), &arch, physical_tile_types, logical_block_types);
4748

4849
printf("Printing Results\n");
4950

50-
EchoArch(argv[3], physical_tile_types, logical_block_types, arch);
51-
free(arch);
51+
EchoArch(argv[3], physical_tile_types, logical_block_types, &arch);
52+
53+
// CLEAN UP
54+
free_arch(&arch);
55+
free_type_descriptors(physical_tile_types);
56+
free_type_descriptors(logical_block_types);
57+
5258
} catch (vtr::VtrError& vtr_error) {
5359
printf("Failed to process architecture %s: %s\n", argv[1], vtr_error.what());
5460
return 1;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Reading an architecture and output the Verilog black box
3+
* declaration of complex blocks in a file
4+
*
5+
* Date: July, 2022
6+
* Author: Seyed Alireza Damghani
7+
*/
8+
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <vector>
12+
13+
#include "vtr_error.h"
14+
#include "vtr_memory.h"
15+
16+
#include "arch_util.h"
17+
#include "read_xml_arch_file.h"
18+
#include "write_models_bb.h"
19+
20+
void print_help();
21+
22+
int main(int argc, char** argv) {
23+
try {
24+
t_arch arch;
25+
std::vector<t_physical_tile_type> physical_tile_types;
26+
std::vector<t_logical_block_type> logical_block_types;
27+
28+
if (argc - 1 != 2) {
29+
printf("Error: Unexpected # of arguments. Expected 2 found %d arguments\n",
30+
argc);
31+
print_help();
32+
return 1;
33+
}
34+
35+
printf("-------------------------------------------------------------------------------------------------------\n");
36+
printf("- Read architecture file and generate a Verilog file including the declaration of models as black boxes\n");
37+
printf("-------------------------------------------------------------------------------------------------------\n\n");
38+
39+
printf(
40+
"Inputs: \n"
41+
"architecture %s\n"
42+
"output file %s\n",
43+
argv[1], argv[2]);
44+
printf("Reading in architecture ...\n");
45+
46+
/* function declarations */
47+
XmlReadArch(argv[1], false, &arch, physical_tile_types, logical_block_types);
48+
49+
printf("Printing Results ...\n");
50+
51+
WriteModels_bb(argv[1], argv[2], &arch);
52+
53+
// CLEAN UP
54+
free_arch(&arch);
55+
free_type_descriptors(physical_tile_types);
56+
free_type_descriptors(logical_block_types);
57+
58+
} catch (vtr::VtrError& vtr_error) {
59+
printf("Failed to process architecture %s: %s\n", argv[1], vtr_error.what());
60+
return 1;
61+
} catch (std::exception& error) {
62+
printf("Failed to process architecture %s: %s\n", argv[1], error.what());
63+
return 1;
64+
}
65+
66+
printf("Done\n");
67+
68+
return 0;
69+
}
70+
71+
void print_help() {
72+
printf("\n-----------------------------------------------------------------------------------------------------------------------\n");
73+
printf("write_arch_bb - Read a VPR architecture file and output a Verilog file including the declaration of models as black boxes\n");
74+
printf("\n");
75+
printf("Usage: write_arch_bb <arch_file.xml> <output_file>\n");
76+
printf("\n");
77+
printf(" ex: write_arch_bb k4_n10.xml dsp_bb.v\n");
78+
printf(" Read timing-driven architecture k4_n10.xml and output the results to arch_data.out\n");
79+
printf("\n-----------------------------------------------------------------------------------------------------------------------\n");
80+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include <algorithm> // std::all_of
2+
3+
#include "vtr_util.h" // vtr::fopen
4+
#include "vtr_assert.h" // VTR ASSERT
5+
6+
#include "write_models_bb.h"
7+
8+
using vtr::t_linked_vptr;
9+
10+
/* the output file description */
11+
#define OUTPUT_HEADER_COMMENT(Echo, ArchFile) \
12+
{ \
13+
fprintf(Echo, \
14+
"/*********************************************************************************************************/\n"); \
15+
fprintf(Echo, "/* %-100s*/\n", ""); \
16+
fprintf(Echo, "/* %-100s*/\n", \
17+
"This is a machine-generated Verilog code, including the black box declaration of"); \
18+
fprintf(Echo, "/* %-100s*/\n", \
19+
"complex blocks defined in the following architecture file:"); \
20+
fprintf(Echo, "/* %-100s*/\n", ""); \
21+
fprintf(Echo, "/* %-90s*/\n", strrchr(ArchFile, '/') + 1); \
22+
fprintf(Echo, "/* %-100s*/\n", ""); \
23+
fprintf(Echo, \
24+
"/*********************************************************************************************************/\n\n"); \
25+
}
26+
27+
/* a comment for the body of black box modules */
28+
const char* HARD_BLOCK_COMMENT = "/* the body of the complex block module is empty since it should be seen as a black box */";
29+
/* list of vtr primitives blocks */
30+
static constexpr short num_vtr_primitives = 8;
31+
static constexpr const char* vtr_primitives[num_vtr_primitives] = {
32+
"LUT_K",
33+
"DFF",
34+
"fpga_interconnect",
35+
"mux",
36+
"adder",
37+
"multiply",
38+
"single_port_ram",
39+
"dual_port_ram"};
40+
41+
/* declarations */
42+
void DeclareModel_bb(FILE* Echo, const t_model* model);
43+
44+
/**
45+
* (function: WriteModels_bb)
46+
*
47+
* @brief Output the black box declaration of
48+
* complex blocks in the Verilog format
49+
*
50+
* @param ArchFile path to the architecture file
51+
* @param VEchoFile path to the architecture file
52+
* @param arch pointer to the arch data structure
53+
*/
54+
void WriteModels_bb(const char* ArchFile,
55+
const char* VEchoFile,
56+
const t_arch* arch) {
57+
// validate the arch
58+
VTR_ASSERT(arch);
59+
60+
FILE* Echo = vtr::fopen(VEchoFile, "w");
61+
t_model* cur_model = arch->models;
62+
63+
/* the output file description */
64+
OUTPUT_HEADER_COMMENT(Echo, ArchFile)
65+
66+
// iterate over models
67+
while (cur_model) {
68+
// avoid printing vtr primitives
69+
if (std::all_of(vtr_primitives,
70+
vtr_primitives + num_vtr_primitives,
71+
[&](const auto& e) { return strcmp(e, cur_model->name); }))
72+
DeclareModel_bb(Echo, cur_model);
73+
74+
// moving forward with the next complex block
75+
cur_model = cur_model->next;
76+
}
77+
78+
// CLEAN UP
79+
fclose(Echo);
80+
}
81+
82+
/**
83+
* (function: DeclareModel_bb)
84+
*
85+
* @brief prints the declaration of the given
86+
* complex block model into the Echo file
87+
*
88+
* @param Echo pointer output file
89+
* @param model pointer to the complex block t_model
90+
*/
91+
void DeclareModel_bb(FILE* Echo, const t_model* model) {
92+
// validate the blackbox name
93+
VTR_ASSERT(model);
94+
95+
// module
96+
fprintf(Echo, "module %s(\n", model->name);
97+
98+
// input/output ports
99+
t_model_ports* input_port = model->inputs;
100+
while (input_port) {
101+
fprintf(Echo, "\tinput\t[%d:0]\t%s,\n", input_port->size - 1, input_port->name);
102+
// move forward until the end of input ports' list
103+
input_port = input_port->next;
104+
}
105+
106+
t_model_ports* output_port = model->outputs;
107+
while (output_port) {
108+
fprintf(Echo, "\toutput\t[%d:0]\t%s,\n", output_port->size - 1, output_port->name);
109+
// move forward until the end of output ports' list
110+
output_port = output_port->next;
111+
}
112+
fprintf(Echo, ");\n");
113+
114+
// body
115+
fprintf(Echo, "%s\n", HARD_BLOCK_COMMENT);
116+
117+
// endmodule
118+
fprintf(Echo, "endmodule\n\n");
119+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef WRITE_MODELS_BB_H
2+
#define WRITE_MODELS_BB_H
3+
4+
#include "arch_types.h"
5+
6+
void WriteModels_bb(const char* ArchFile,
7+
const char* VEchoFile,
8+
const t_arch* arch);
9+
10+
#endif

0 commit comments

Comments
 (0)