Merge pull request #129 from WhiteNinjaZ/master

Fix xdc parser to ignore multiple spaces
diff --git a/xdc-plugin/tests/Makefile b/xdc-plugin/tests/Makefile
index 363cbfe..f96a6f1 100644
--- a/xdc-plugin/tests/Makefile
+++ b/xdc-plugin/tests/Makefile
@@ -8,12 +8,14 @@
 
 # counter - basic test for IOSTANDARD, SLEW, DRIVE, IN_TERM properties
 # counter-dict - basic test using XDC -dict for IOSTANDARD, SLEW, DRIVE, IN_TERM properties
+# package_pins-dict-space - basic test for variable whitespace between PACKAGE_PINs and IOSTANDARD
 # port_indexes - like counter but bus port indices are passes without curly braces
 # io_loc_pairs - test for LOC property being set on IOBUFs as the IO_LOC_PAIRS parameter
 # minilitex_ddr_arty - litex design with more types of IOBUFS including differential
 # package_pins - test for PACKAGE_PIN property being set on IOBUFs as the IO_LOC_PAIRS parameter
 TESTS = counter \
 	counter-dict \
+	package_pins-dict-space \
 	port_indexes \
 	io_loc_pairs \
 	minilitex_ddr_arty \
@@ -34,3 +36,4 @@
 io_loc_pairs_verify = $(call json_test,io_loc_pairs)
 minilitex_ddr_arty_verify = $(call json_test,minilitex_ddr_arty)
 package_pins_verify = $(call json_test,package_pins)
+package_pins-dict-space_verify = $(call json_test,package_pins-dict-space)
diff --git a/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.golden.json b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.golden.json
new file mode 100644
index 0000000..2e9102d
--- /dev/null
+++ b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.golden.json
@@ -0,0 +1,47 @@
+{
+  "OBUFTDS_2": {
+    "IOSTANDARD": "DIFF_SSTL135",
+    "IO_LOC_PAIRS": "signal_p:N2,signal_n:N1",
+    "SLEW": "FAST"
+  },
+  "OBUF_6": {
+    "DRIVE": "12",
+    "IOSTANDARD": "LVCMOS33",
+    "IO_LOC_PAIRS": "led[0]:D10",
+    "SLEW": "SLOW"
+  },
+  "OBUF_7": {
+    "IN_TERM": "UNTUNED_SPLIT_40",
+    "IOSTANDARD": "SSTL135",
+    "IO_LOC_PAIRS": "led[1]:A9",
+    "SLEW": "FAST"
+  },
+  "OBUF_OUT": {
+    "IN_TERM": "UNTUNED_SPLIT_50",
+    "IOSTANDARD": "LVCMOS33",
+    "IO_LOC_PAIRS": "out_a:E3",
+    "SLEW": "FAST"
+  },
+  "bottom_inst.OBUF_10": {
+    "IOSTANDARD": "LVCMOS18",
+    "IO_LOC_PAIRS": "out_b[0]:C2",
+    "SLEW": "SLOW"
+  },
+  "bottom_inst.OBUF_11": {
+    "DRIVE": "4",
+    "IOSTANDARD": "LVCMOS25",
+    "IO_LOC_PAIRS": "out_b[1]:R2",
+    "SLEW": "FAST"
+  },
+  "bottom_inst.OBUF_9": {
+    "IOSTANDARD": "DIFF_SSTL135",
+    "IO_LOC_PAIRS": "led[2]:M6",
+    "SLEW": "FAST"
+  },
+  "bottom_intermediate_inst.OBUF_8": {
+    "DRIVE": "16",
+    "IOSTANDARD": "SSTL135",
+    "IO_LOC_PAIRS": "led[3]:N4",
+    "SLEW": "SLOW"
+  }
+}
\ No newline at end of file
diff --git a/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.tcl b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.tcl
new file mode 100644
index 0000000..7303563
--- /dev/null
+++ b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.tcl
@@ -0,0 +1,15 @@
+yosys -import
+if { [info procs get_ports] == {} } { plugin -i design_introspection }
+if { [info procs read_xdc] == {} } { plugin -i xdc }
+yosys -import  ;# ingest plugin commands
+
+read_verilog $::env(DESIGN_TOP).v
+# -flatten is used to ensure that the output eblif has only one module.
+# Some of symbiflow expects eblifs with only one module.
+synth_xilinx -flatten -abc9 -nosrl -noclkbuf -nodsp
+
+#Read the design constraints
+read_xdc -part_json [file dirname [info script]]/../xc7a35tcsg324-1.json $::env(DESIGN_TOP).xdc
+
+# Write the design in JSON format.
+write_json [test_output_path "package_pins-dict-space.json"]
diff --git a/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.v b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.v
new file mode 100644
index 0000000..d4d172d
--- /dev/null
+++ b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.v
@@ -0,0 +1,111 @@
+// Copyright (C) 2020-2021  The SymbiFlow Authors.
+//
+// Use of this source code is governed by a ISC-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/ISC
+//
+// SPDX-License-Identifier:ISC
+
+module top (
+    input clk,
+    output [3:0] led,
+    inout out_a,
+    output [1:0] out_b,
+    output signal_p,
+    output signal_n
+);
+
+  wire LD6, LD7, LD8, LD9;
+  wire inter_wire, inter_wire_2;
+  localparam BITS = 1;
+  localparam LOG2DELAY = 25;
+
+  reg [BITS+LOG2DELAY-1:0] counter = 0;
+
+  always @(posedge clk) begin
+    counter <= counter + 1;
+  end
+  assign led[1] = inter_wire;
+  assign inter_wire = inter_wire_2;
+  assign {LD9, LD8, LD7, LD6} = counter >> LOG2DELAY;
+  OBUFTDS OBUFTDS_2 (
+      .I (LD6),
+      .O (signal_p),
+      .OB(signal_n),
+      .T (1'b1)
+  );
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_6 (
+      .I(LD6),
+      .O(led[0])
+  );
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_7 (
+      .I(LD7),
+      .O(inter_wire_2)
+  );
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_OUT (
+      .I(LD7),
+      .O(out_a)
+  );
+  bottom bottom_inst (
+      .I (LD8),
+      .O (led[2]),
+      .OB(out_b)
+  );
+  bottom_intermediate bottom_intermediate_inst (
+      .I(LD9),
+      .O(led[3])
+  );
+endmodule
+
+module bottom_intermediate (
+    input  I,
+    output O
+);
+  wire bottom_intermediate_wire;
+  assign O = bottom_intermediate_wire;
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_8 (
+      .I(I),
+      .O(bottom_intermediate_wire)
+  );
+endmodule
+
+module bottom (
+    input I,
+    output [1:0] OB,
+    output O
+);
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_9 (
+      .I(I),
+      .O(O)
+  );
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_10 (
+      .I(I),
+      .O(OB[0])
+  );
+  OBUF #(
+      .IOSTANDARD("LVCMOS33"),
+      .SLEW("SLOW")
+  ) OBUF_11 (
+      .I(I),
+      .O(OB[1])
+  );
+endmodule
+
diff --git a/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.xdc b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.xdc
new file mode 100644
index 0000000..70453d1
--- /dev/null
+++ b/xdc-plugin/tests/package_pins-dict-space/package_pins-dict-space.xdc
@@ -0,0 +1,29 @@
+#OBUF_6
+set_property PACKAGE_PIN D10 [get_ports {led[0]}]
+set_property DRIVE 12 [get_ports {led[0]}]
+#OBUF_7
+set_property -dict { PACKAGE_PIN A9   IOSTANDARD SSTL135 } [get_ports {led[1]}]
+set_property IN_TERM UNTUNED_SPLIT_40 [get_ports led[1]]
+set_property SLEW FAST [get_ports led[1]]
+#OBUF_OUT
+set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33} [get_ports out_a]
+set_property IN_TERM UNTUNED_SPLIT_50 [get_ports out_a]
+set_property SLEW FAST [get_ports out_a]
+#bottom_inst.OBUF_10
+set_property -dict {PACKAGE_PIN C2  IOSTANDARD LVCMOS18} [get_ports {out_b[0]}]
+set_property SLEW SLOW [get_ports {out_b[0]}]
+#bottom_inst.OBUF_11
+set_property -dict { PACKAGE_PIN R2   IOSTANDARD LVCMOS25 } [get_ports {out_b[1]}]
+set_property DRIVE 4 [get_ports {out_b[1]}]
+set_property SLEW FAST [get_ports {out_b[1]}]
+#bottom_inst.OBUF_9
+set_property -dict {PACKAGE_PIN M6      IOSTANDARD DIFF_SSTL135} [get_ports {led[2]}]
+set_property SLEW FAST [get_ports {led[2]}]
+#bottom_intermediate_inst.OBUF_8
+set_property -dict {PACKAGE_PIN N4    IOSTANDARD SSTL135} [get_ports {led[3]}]
+set_property DRIVE 16 [get_ports {led[3]}]
+#OBUFTDS_2
+set_property -dict {PACKAGE_PIN N2    IOSTANDARD DIFF_SSTL135} [get_ports signal_p]
+set_property PACKAGE_PIN N1 [get_ports signal_n]
+set_property SLEW FAST [get_ports signal_p]
+
diff --git a/xdc-plugin/xdc.cc b/xdc-plugin/xdc.cc
index 2e935ea..387d191 100644
--- a/xdc-plugin/xdc.cc
+++ b/xdc-plugin/xdc.cc
@@ -136,7 +136,9 @@
             std::vector<std::string> tokens;
             std::string intermediate;
             while (getline(args_stream, intermediate, ' ')) {
-                tokens.push_back(intermediate);
+                if (intermediate != "\0") {
+                    tokens.push_back(intermediate);
+                }
             }
             if (tokens.size() % 2 != 0) {
                 log_cmd_error("Invalid number of dict parameters: %lu.\n", tokens.size());