Skip to content

Upgrade the Yosys+Odin-II Front-end #2148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9a450c0
[Yosys+Odin-II]: enhance the Yosys script for performing the HDL elab…
sdamghan Aug 27, 2022
9f041e4
[Yosys+Odin-II]: passing clock nodes intact to the partial mapper as …
sdamghan Aug 27, 2022
450c06e
[Yosys+Odin-II]: avoid concatenating the top module name to the edge …
sdamghan Aug 27, 2022
2b4cc32
[Yosys+Odin-II]: - avoid resolving signle bit FF nodes as they alread…
sdamghan Aug 27, 2022
86c08b3
[Odin-II]: avoid generating extra buf nodes while the top output driv…
sdamghan Aug 27, 2022
0fab2ac
[Yosys+Odin-II]: upgrade the Yosys script to utilize Yosys simplemap …
sdamghan Aug 29, 2022
317f10c
[Yosys+Odin-II]: - avoid instantiating logical not while there is a s…
sdamghan Aug 29, 2022
246558c
[Yosys+Odin-II]: - warn about undriven pins in Yosys coarse-grained B…
sdamghan Aug 29, 2022
05cddb1
[Odin-II]: fix a bug in printing netlist statistics
sdamghan Aug 29, 2022
ad63ed3
[Yosys+Odin-II]: - add $clog2 to calculate address width in memory be…
sdamghan Aug 29, 2022
52a53b6
[Yosys+Odin-II]: regenerate expectation results of common and keyword…
sdamghan Aug 29, 2022
4fcde37
[Yosys+Odin-II]: regenerate expectation results of operators benchmarks
sdamghan Aug 29, 2022
88f9ded
[Yosys+Odin-II]: regenerate expectation results of FIR benchmarks
sdamghan Aug 29, 2022
e27f220
[Yosys+Odin-II]: - regenerate expectation results of micro benchmarks
sdamghan Aug 29, 2022
5af7763
[Yosys+Odin-II]: regenerate expectation results of syntax benchmarks
sdamghan Aug 29, 2022
1fdce66
[Yosys+Odin-II]: - regenerate expectation results of full benchmarks
sdamghan Aug 29, 2022
8d7280e
[Yosys+Odin-II]: regenerate expectation results of large, koios, and …
sdamghan Aug 29, 2022
6d7e99a
[Infra]: regenerate vtr_reg_yosys_odin golden results
sdamghan Aug 29, 2022
1e25d17
[Yosys+Odin-II]: fix cpp format
sdamghan Aug 29, 2022
5f05c15
[Doc]: update the documentaion for the Yosys+Odin-II upgraded script
sdamghan Aug 29, 2022
6ff282d
[Infra]: regenerate vtr_reg_yosys_odin golden results
sdamghan Aug 29, 2022
6329031
[Yosys+Odin-II]: update simulation output vectors for bm_match1_str_a…
sdamghan Aug 29, 2022
f953415
[Yosys+Odin-II]: adding the Yosys full memory command instead of just…
sdamghan Aug 30, 2022
3fb3a6b
[Yosys+Odin-II]: - perform memory mapping in Odin-II partial mapper f…
sdamghan Aug 30, 2022
6ba2241
[Yosys+Odin-II]: regenerate golden results
sdamghan Aug 31, 2022
d2f6bcb
[Yosys+Odin-II]: fix format issues
sdamghan Aug 31, 2022
2636bea
[Docs]: update docs with recent changes in Yossys+Odin-II scripts
sdamghan Sep 1, 2022
699ea98
[Yosys+Odin-II]: - fix a bug in receiving sv extension without having…
sdamghan Sep 2, 2022
7c84656
[Yosys+Odin-II]: remove memory_share from Yosys script
sdamghan Sep 3, 2022
2e304bd
[Yosys+Odin-II]: regenerate expectation results of the common regress…
sdamghan Sep 3, 2022
a26d280
[Yosys+Odin-II]: fix format issue
sdamghan Sep 4, 2022
4fcb998
[Docs]: resolve confilicts with the master branch update
sdamghan Sep 4, 2022
955cbfb
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
sdamghan Sep 4, 2022
fe5d659
[Docs]: resolve confilcts
sdamghan Sep 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ODIN_II/SRC/BLIFElaborate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,13 @@ void blif_elaborate_node(nnode_t* node, short traverse_number, netlist_t* netlis
case INPUT_NODE: //fallthrough
case OUTPUT_NODE: //fallthrough
case HARD_IP: //fallthrough
case CLOCK_NODE: //fallthroguh
case BUF_NODE: {
/* some are already resolved for this phase */
break;
}
case ADDER_FUNC:
case CARRY_FUNC:
case CLOCK_NODE:
case GENERIC:
default:
error_message(BLIF_ELABORATION, node->loc, "node (%s: %s) should have been converted to softer version.", node->type, node->name);
Expand Down
19 changes: 14 additions & 5 deletions ODIN_II/SRC/BLIFReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,13 @@ void BLIF::Reader::hook_up_node(nnode_t* node) {

nnet_t* output_net = (nnet_t*)output_nets_hash->get(input_pin->name);

if (!output_net)
error_message(PARSE_BLIF, my_location, "Error: Could not hook up the pin %s: not available.", input_pin->name);
if (!output_net) {
if (configuration.coarsen)
warning_message(PARSE_BLIF, my_location, "Warn: Could not hook up the pin %s: not available.", input_pin->name);
else
error_message(PARSE_BLIF, my_location, "Error: Could not hook up the pin %s: not available.", input_pin->name);
return;
}

add_fanout_pin_to_net(output_net, input_pin);
}
Expand Down Expand Up @@ -1186,11 +1191,11 @@ operation_list BLIF::Reader::read_bit_map_find_unknown_gate(int input_count, nno
/* Assumption that bit map is in order when read from blif */
else if (line_count_bitmap == 2) {
/* LOGICAL_XOR */
if ((strcmp(bit_map[0], "01") == 0) && (strcmp(bit_map[1], "10") == 0)) {
if (((strcmp(bit_map[0], "01") == 0) && (strcmp(bit_map[1], "10") == 0)) || ((strcmp(bit_map[0], "10") == 0) && (strcmp(bit_map[1], "01") == 0))) {
to_return = LOGICAL_XOR;
}
/* LOGICAL_XNOR */
else if ((strcmp(bit_map[0], "00") == 0) && (strcmp(bit_map[1], "11") == 0)) {
else if (((strcmp(bit_map[0], "00") == 0) && (strcmp(bit_map[1], "11") == 0)) || ((strcmp(bit_map[0], "11") == 0) && (strcmp(bit_map[1], "00") == 0))) {
to_return = LOGICAL_XNOR;
}
/* SMUX_2 */
Expand Down Expand Up @@ -1372,7 +1377,11 @@ void BLIF::Reader::create_latch_node_and_driver() {
input_token_count += 1;
names = (char**)vtr::realloc(names, (sizeof(char*)) * (input_token_count));

names[input_token_count - 1] = resolve_signal_name_based_on_blif_type(blif_netlist->identifier, ptr);
// to avoid concatenating the top module name to edge sentivity and init value inputs
if (configuration.coarsen && (input_token_count == 3 || input_token_count == 5))
names[input_token_count - 1] = resolve_signal_name_based_on_blif_type(nullptr, ptr);
else
names[input_token_count - 1] = resolve_signal_name_based_on_blif_type(blif_netlist->identifier, ptr);
}

/* assigning the new_node */
Expand Down
3 changes: 3 additions & 0 deletions ODIN_II/SRC/BLIFWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ void BLIF::Writer::output_blif(FILE* out, const netlist_t* netlist) {
nnet_t* net = node->input_pins[0]->net;
warn_undriven(node, net);
for (int j = 0; j < net->num_driver_pins; j++) {
// skip if their names is identical
if (coarsen_cleanup && net->driver_pins[j]->name && node->name && !strcmp(net->driver_pins[j]->name, node->name))
continue;
fprintf(out, ".names");
print_net_driver(out, node, net, j);
print_output_pin(out, node);
Expand Down
19 changes: 12 additions & 7 deletions ODIN_II/SRC/BlockMemories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1074,13 +1074,8 @@ static void create_nrmw_dual_port_ram(block_memory_t* bram, netlist_t* netlist)
nnode_t* old_node = bram->node;
int data_width = bram->node->attributes->DBITS;
int addr_width = bram->node->attributes->ABITS;
int num_rd_ports = old_node->attributes->RD_PORTS;
int num_wr_ports = old_node->attributes->WR_PORTS;

/* should have been resovled before this function */
oassert(num_rd_ports > 2);
oassert(num_wr_ports > 2);

/* dual port ram signals */
dp_ram_signals* signals = (dp_ram_signals*)vtr::calloc(1, sizeof(dp_ram_signals));
signal_list_t* selectors = NULL;
Expand Down Expand Up @@ -1706,17 +1701,27 @@ static void perform_optimization(block_memory_t* memory) {
* @return last item outputs in the chain of cascaded signals
*/
static signal_list_t* split_cascade_port(signal_list_t* signalvar, signal_list_t* selectors, int desired_width, nnode_t* node, netlist_t* netlist) {
signal_list_t* return_value = NULL;

/* check if cascade is needed */
if (signalvar->count == desired_width) {
return (signalvar);
return_value = init_signal_list();
if (selectors->count == desired_width) {
for (int i = 0; i < signalvar->count; ++i)
add_pin_to_signal_list(return_value, selectors->pins[i]);
} else {
for (int i = 0; i < signalvar->count; ++i)
add_pin_to_signal_list(return_value, signalvar->pins[i]);
}

return (return_value);
}

/* validate signals list size */
oassert(signalvar->count % desired_width == 0);

int i, j;
int num_chunk = signalvar->count / desired_width;
signal_list_t* return_value = NULL;
/* validate selector size */
oassert(selectors->count == num_chunk);

Expand Down
4 changes: 4 additions & 0 deletions ODIN_II/SRC/FlipFlop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ void resolve_dff_node(nnode_t* node, uintptr_t traverse_mark_number, netlist_t*
npin_t* clk_pin = node->input_pins[0];
clk_pin->sensitivity = node->attributes->clk_edge_type;

/* already satisfy the partial mapper requirements */
if (width == 1)
return;

/* remapping the D inputs to [1..n] */
for (i = 0; i < width; i++) {
make_ff_node(node->input_pins[i + clk_width], // D
Expand Down
65 changes: 52 additions & 13 deletions ODIN_II/SRC/YYosys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,28 @@ void YYosys::execute() {
run_pass(std::string("hierarchy -check -auto-top -purge_lib"));
}

// Translate processes to netlist components such as MUXs, FFs and latches
run_pass(std::string("proc; opt;"));
/*
* Translate processes to netlist components such as MUXs, FFs and latches
* Transform the design into a new one with single top module
*/
run_pass(std::string("proc; flatten; opt_expr; opt_clean;"));
/*
* Looking for combinatorial loops, wires with multiple drivers and used wires without any driver.
* "-nodffe" to disable dff -> dffe conversion, and other transforms recognizing clock enable
* "-nosdff" to disable dff -> sdff conversion, and other transforms recognizing sync resets
*/
run_pass(std::string("check; opt -nodffe -nosdff;"));
// Extraction and optimization of finite state machines
run_pass(std::string("fsm; opt;"));
// Collects memories, their port and create multiport memory cells
run_pass(std::string("memory_collect; memory_dff; opt;"));
// To possibly reduce word sizes by Yosys
run_pass(std::string("wreduce;"));
// To applies a collection of peephole optimizers to the current design.
run_pass(std::string("peepopt; opt_clean;"));
/*
* To merge shareable resources into a single resource. A SAT solver
* is used to determine if two resources are share-able
*/
run_pass(std::string("share; opt;"));

// Use a readable name convention
// [NOTE]: the 'autoname' process has a high memory footprint for giant netlists
Expand All @@ -317,8 +333,15 @@ void YYosys::execute() {
// Transform asynchronous dffs to synchronous dffs using techlib files provided by Yosys
run_pass(std::string("techmap -map " + this->odin_techlib + "/adff2dff.v"));
run_pass(std::string("techmap -map " + this->odin_techlib + "/adffe2dff.v"));
// To resolve Yosys internal indexed part-select circuitries
run_pass(std::string("techmap */t:$shift */t:$shiftx"));

// Yosys performs various optimizations on memories in the design. Then, it detects DFFs at
// memory read ports and merges them into the memory port. I.e. it consumes an asynchronous
// memory port and the flip-flops at its interface and yields a synchronous memory port.
// Afterwards, Yosys detects cases where an asynchronous read port is only connected via a mux
// tree to a write port with the same address. When such a connection is found, it is replaced
// with a new condition on an enable signal, allowing for removal of the read port. Finally
// Yosys collects memories, their port and create multiport memory cells.
run_pass(std::string("opt_mem; memory_dff; opt_clean; opt_mem_feedback; opt_clean; memory_collect;"));

/**
* convert yosys mem blocks to BRAMs / ROMs
Expand All @@ -333,19 +356,35 @@ void YYosys::execute() {
* Yosys::run_pass(std::string("techmap -map ", this->odin_techlib, "/mem_map.v"));
*/

/*
* Transforming all RTLIL components into LUTs except for memories, adders, subtractors,
* multipliers, DFFs with set (VCC) and clear (GND) signals, and DFFs with the set (VCC),
* clear (GND), and enable signals The Odin-II partial mapper will perform the technology
* mapping for the above-mentioned circuits
*
* [NOTE]: the purpose of using this pass is to keep the connectivity of internal signals
* in the coarse-grained BLIF file, as they were not properly connected in the
* initial implementation of Yosys+Odin-II, which did not use this pass
*/
run_pass(std::string("techmap -autoproc */t:$mem */t:$memrd */t:$add */t:$sub */t:$mul */t:$dffsr */t:$dffsre */t:$sr */t:$dlatch */t:$adlatch %% %n"));

// Transform the design into a new one with single top module
run_pass(std::string("flatten"));
// Transforms PMUXes into trees of regular multiplexers
run_pass(std::string("pmuxtree"));
// To possibly reduce word sizes by Yosys
run_pass(std::string("wreduce"));

// To possibly reduce word sizes by Yosys and fine-graining the basic operations
run_pass(std::string("wreduce; simplemap */t:$dffsr */t:$dffsre */t:$sr */t:$dlatch */t:$adlatch %% %n;"));
// Turn all DFFs into simple latches
run_pass(std::string("dffunmap; opt -fast -noff;"));

// Check the hierarchy for any unknown modules, and purge all modules (including blackboxes) that aren't used
run_pass(std::string("hierarchy -check -purge_lib"));
// "-undriven" to ensure there is no wire without drive
// -noff #potential option to remove all sdffXX and etc. Only dff will remain
// "-noff" option to remove all sdffXX and etc. Only dff will remain
// "opt_muxtree" removes dead branches, "opt_expr" performs const folding and
// removes "undef" from mux inputs and replace muxes with buffers and inverters
run_pass(std::string("opt -undriven -full; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"));
run_pass(std::string("opt -undriven -full -noff; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"));
// Use a readable name convention
run_pass(std::string("autoname"));
run_pass(std::string("autoname;"));
// Print statistics
run_pass(std::string("stat"));
}
Expand Down
26 changes: 15 additions & 11 deletions ODIN_II/SRC/include/odin_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,29 @@ extern std::vector<std::pair<std::string, int>> include_file_names;
extern int delayed_errors;
extern const loc_t unknown_location;

#ifdef ODIN_USE_YOSYS
#define SYSTEMVERILOG_PARSER_ERROR \
"The SystemVerilog parser is provided within Yosys. " \
"Please use the Yosys elaborator to synthesize SystemVerilog files.\n"
#define UHDM_PARSER_ERROR \
"The UHDM parser is provided within Yosys. " \
"Please use the Yosys elaborator to synthesize UHDM files.\n"

#ifndef ODIN_USE_YOSYS
# define YOSYS_INSTALLATION_ERROR \
"It seems Yosys is not installed in the VTR repository. " \
"Please compile the VTR with (\" -DODIN_USE_YOSYS=ON \") flag.\n"
#else
# define YOSYS_ELABORATION_ERROR \
"Yosys failed to perform elaboration, " \
"Please look at the log file for the failure cause or pass \'--show_yosys_log\' to Odin-II to see the logs.\n"
# define YOSYS_FORK_ERROR \
"Yosys child process failed to be created\n"
# define YOSYS_PLUGINS_WITH_ODIN_ERROR \
"Utilizing SystemVerilog/UHDM plugins requires activating the Yosys frontend.\
Please recompile the VTR project either with the \"WITH_YOSYS\" or \"ODIN_USE_YOSYS\" flag on."
#else
# define YOSYS_INSTALLATION_ERROR \
"It seems Yosys is not installed in the VTR repository." \
" Please compile the VTR with (\" -DODIN_USE_YOSYS=ON \") flag.\n"
#endif

#ifndef YOSYS_SV_UHDM_PLUGIN
# define YOSYS_PLUGINS_NOT_COMPILED \
"SystemVerilog/UHDM plugins are not compiled.\
Please recompile the VTR project with the \"YOSYS_SV_UHDM_PLUGIN\" flag on."
# define YOSYS_PLUGINS_NOT_COMPILED \
"SystemVerilog/UHDM plugins are not compiled. " \
"Please recompile the VTR project with the \"YOSYS_SV_UHDM_PLUGIN\" flag on."
#endif

// causes an interrupt in GDB
Expand Down
2 changes: 1 addition & 1 deletion ODIN_II/SRC/include/odin_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ long shift_left_value_with_overflow_check(long input_value, long shift_by, loc_t
std::string get_file_extension(std::string input_file);
std::string get_directory(std::string input_file);
void create_directory(std::string path);
void assert_valid_file_extenstion(std::vector<std::string> name_list, file_type_e type);
void report_frontend_elaborator();
void assert_supported_file_extension(std::string input_file, loc_t loc);
FILE* open_file(const char* file_name, const char* open_type);
void get_current_path();
Expand Down
4 changes: 2 additions & 2 deletions ODIN_II/SRC/netlist_statistic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ void compute_statistics(netlist_t* netlist, bool display) {
auto unused_pi = netlist->num_top_input_nodes - netlist->num_of_type[op] - netlist->num_of_type[CLOCK_NODE];
if (unused_pi > 0) {
hdr = std::string("Number of unused <")
+ operation_list_STR[op][ODIN_LONG_STRING]
+ operation_list_STR[INPUT_NODE][ODIN_LONG_STRING]
+ "> node: ";
printf("%-42s%lld\n", hdr.c_str(), unused_pi);
}
Expand All @@ -497,7 +497,7 @@ void compute_statistics(netlist_t* netlist, bool display) {
auto unused_po = netlist->num_top_output_nodes - netlist->num_of_type[op];
if (unused_po > 0) {
hdr = std::string("Number of unused <")
+ operation_list_STR[op][ODIN_LONG_STRING]
+ operation_list_STR[OUTPUT_NODE][ODIN_LONG_STRING]
+ "> node: ";
printf("%-42s%lld\n", hdr.c_str(), unused_po);
}
Expand Down
24 changes: 12 additions & 12 deletions ODIN_II/SRC/netlist_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1613,9 +1613,9 @@ void reduce_input_ports(nnode_t*& node, netlist_t* netlist) {
int max = std::max(input_ports[0]->count, input_ports[1]->count);

while (input_ports[0]->count < max)
add_pin_to_signal_list(input_ports[0], get_pad_pin(netlist));
add_pin_to_signal_list(input_ports[0], get_zero_pin(netlist));
while (input_ports[1]->count < max)
add_pin_to_signal_list(input_ports[1], get_pad_pin(netlist));
add_pin_to_signal_list(input_ports[1], get_zero_pin(netlist));
}

/* creating a new node */
Expand Down Expand Up @@ -1890,16 +1890,6 @@ void equalize_input_ports_size(nnode_t*& node, uintptr_t traverse_mark_number, n
oassert(node->traverse_visited == traverse_mark_number);
oassert(node->num_input_port_sizes > 0 && node->num_input_port_sizes <= 2);

/**
* INPUTS
* A: (width_a)
* B: (width_b) [optional]
* OUTPUT
* Y: width_y
*/
/* removing extra pad pins based on the signedness of ports */
reduce_input_ports(node, netlist);

int port_a_size = node->input_port_sizes[0];
int port_b_size = -1;
if (node->num_input_port_sizes == 2) {
Expand All @@ -1914,6 +1904,16 @@ void equalize_input_ports_size(nnode_t*& node, uintptr_t traverse_mark_number, n
if (port_a_size == port_y_size)
return;

/**
* INPUTS
* A: (width_a)
* B: (width_b) [optional]
* OUTPUT
* Y: width_y
*/
/* removing extra pad pins based on the signedness of ports */
reduce_input_ports(node, netlist);

/* creating the new node */
nnode_t* new_node = (port_b_size == -1) ? make_1port_gate(node->type, port_a_size, port_y_size, node, traverse_mark_number)
: make_2port_gate(node->type, port_a_size, port_b_size, port_y_size, node, traverse_mark_number);
Expand Down
2 changes: 1 addition & 1 deletion ODIN_II/SRC/odin_ii.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ netlist_t* start_odin_ii(int argc, char** argv) {
ODIN_ERROR_CODE error_code;

print_input_files_info();
assert_valid_file_extenstion(configuration.list_of_file_names, configuration.input_file_type);
report_frontend_elaborator();

if (configuration.input_file_type != file_type_e::_BLIF || configuration.coarsen) {
try {
Expand Down
Loading