diff options
Diffstat (limited to 'fpga_interchange')
| -rw-r--r-- | fpga_interchange/examples/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | fpga_interchange/examples/tests/obuftds/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | fpga_interchange/examples/tests/obuftds/basys3.xdc | 9 | ||||
| -rw-r--r-- | fpga_interchange/examples/tests/obuftds/obuftds.v | 37 | ||||
| -rw-r--r-- | fpga_interchange/examples/tests/obuftds/run.tcl | 14 | ||||
| -rw-r--r-- | fpga_interchange/macros.cc | 12 | 
6 files changed, 80 insertions, 0 deletions
| diff --git a/fpga_interchange/examples/tests/CMakeLists.txt b/fpga_interchange/examples/tests/CMakeLists.txt index 1d3dd72f..f8a52a41 100644 --- a/fpga_interchange/examples/tests/CMakeLists.txt +++ b/fpga_interchange/examples/tests/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(ff)  add_subdirectory(lut)  add_subdirectory(lut_nexus)  add_subdirectory(lutram) +add_subdirectory(obuftds)  add_subdirectory(ram_nexus) diff --git a/fpga_interchange/examples/tests/obuftds/CMakeLists.txt b/fpga_interchange/examples/tests/obuftds/CMakeLists.txt new file mode 100644 index 00000000..0313c9bb --- /dev/null +++ b/fpga_interchange/examples/tests/obuftds/CMakeLists.txt @@ -0,0 +1,7 @@ +add_interchange_group_test( +    name obuftds +    family ${family} +    board_list basys3 +    tcl run.tcl +    sources obuftds.v +) diff --git a/fpga_interchange/examples/tests/obuftds/basys3.xdc b/fpga_interchange/examples/tests/obuftds/basys3.xdc new file mode 100644 index 00000000..4b777233 --- /dev/null +++ b/fpga_interchange/examples/tests/obuftds/basys3.xdc @@ -0,0 +1,9 @@ +set_property PACKAGE_PIN V2 [get_ports sw[8] ] +set_property PACKAGE_PIN T3 [get_ports sw[9] ] +set_property PACKAGE_PIN T2 [get_ports sw[10]] +set_property PACKAGE_PIN R3 [get_ports sw[11]] + +set_property PACKAGE_PIN U19 [get_ports diff_p[0]] +set_property PACKAGE_PIN V19 [get_ports diff_n[0]] +set_property PACKAGE_PIN V13 [get_ports diff_p[1]] +set_property PACKAGE_PIN V14 [get_ports diff_n[1]] diff --git a/fpga_interchange/examples/tests/obuftds/obuftds.v b/fpga_interchange/examples/tests/obuftds/obuftds.v new file mode 100644 index 00000000..d4e9a603 --- /dev/null +++ b/fpga_interchange/examples/tests/obuftds/obuftds.v @@ -0,0 +1,37 @@ +module top( +  input  wire [11:8] sw, + +  output wire [1:0]  diff_p, +  output wire [1:0]  diff_n +); + +wire [1:0] buf_i; +wire [1:0] buf_t; + +OBUFTDS # ( +  .IOSTANDARD("DIFF_SSTL135"), +  .SLEW("FAST") +) obuftds_0 ( +  .I(buf_i[0]), +  .T(buf_t[0]), +  .O(diff_p[0]), +  .OB(diff_n[0]) +); + +OBUFTDS # ( +  .IOSTANDARD("DIFF_SSTL135"), +  .SLEW("FAST") +) obuftds_1 ( +  .I(buf_i[1]), +  .T(buf_t[1]), +  .O(diff_p[1]), +  .OB(diff_n[1]) +); + +assign buf_i[0] = sw[ 8]; +assign buf_t[0] = sw[ 9]; +assign buf_i[1] = sw[10]; +assign buf_t[1] = sw[11]; + +endmodule + diff --git a/fpga_interchange/examples/tests/obuftds/run.tcl b/fpga_interchange/examples/tests/obuftds/run.tcl new file mode 100644 index 00000000..b8d0df72 --- /dev/null +++ b/fpga_interchange/examples/tests/obuftds/run.tcl @@ -0,0 +1,14 @@ +yosys -import + +read_verilog $::env(SOURCES) + +synth_xilinx -nolutram -nowidelut -nosrl -nocarry -nodsp + +# opt_expr -undriven makes sure all nets are driven, if only by the $undef +# net. +opt_expr -undriven +opt_clean + +setundef -zero -params + +write_json $::env(OUT_JSON) diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc index 42c8e1ba..762615c1 100644 --- a/fpga_interchange/macros.cc +++ b/fpga_interchange/macros.cc @@ -58,14 +58,24 @@ void Arch::expand_macros()      std::vector<CellInfo *> next_cells; +    bool first_iter = false;      do {          // Expand cells          for (auto cell : cells) {              // TODO: consult exception map              const MacroExpansionPOD *exp = lookup_macro_rules(chip_info, cell->type); + +            // Block infinite expansion loop due to a macro being expanded in the same primitive. +            // E.g.: OBUFTDS expands into the following cells, with an infinite loop being generated: +            //          - 2 OBUFTDS +            //          - 1 INV +            if (exp && first_iter) +                continue; +              const MacroPOD *macro = lookup_macro(chip_info, exp ? IdString(exp->macro_name) : cell->type);              if (macro == nullptr)                  continue; +              // Get the ultimate root of this macro expansion              IdString parent = (cell->macro_parent == IdString()) ? cell->name : cell->macro_parent;              // Create child instances @@ -158,6 +168,8 @@ void Arch::expand_macros()          // The next iteration only needs to look at cells created in this iteration          std::swap(next_cells, cells);          next_cells.clear(); + +        first_iter = true;      } while (!cells.empty());      // Do this at the end, otherwise we might add cells that are later destroyed      for (auto &cell : ctx->cells) | 
