完成 SSI 计算逻辑修复 | 修复 TCL 刷新 XPR 的设计源添加逻辑漏洞

This commit is contained in:
锦恢 2024-11-26 21:38:23 +08:00
parent 70088a0a24
commit 951f831f63
26 changed files with 526 additions and 393 deletions

View File

@ -69,5 +69,7 @@
"info.pl.xilinx.update-addfiles": "Datei zu Xilinx-Projekt hinzufügen",
"info.pl.xilinx.update-delfiles": "Löschen Sie die folgenden Dateien aus dem Xilinx-Projekt.",
"info.pl.xilinx.no-need-add-files": "Keine Dateien zum Hinzufügen zum Xilinx-Projekt",
"info.pl.xilinx.no-need-del-files": "Es müssen keine Dateien aus Xilinx gelöscht werden."
"info.pl.xilinx.no-need-del-files": "Es müssen keine Dateien aus Xilinx gelöscht werden.",
"error.pl.launch.not-valid-vivado-path": "Fehler beim Starten des Vivado TCL-Skriptinterpreters: {0}. Bitte überprüfen Sie, ob der Startpfad für Vivado korrekt ist. Derzeit eingestellter Startordnerpfad für Vivado: {1}",
"info.pl.launch.set-vivado-path": "Zur Einstellung des Vivado-Installationspfads gehen"
}

View File

@ -69,5 +69,7 @@
"info.pl.xilinx.update-addfiles": "Add file to Xilinx project",
"info.pl.xilinx.update-delfiles": "Delete the following files from the Xilinx project.",
"info.pl.xilinx.no-need-add-files": "No files need to be added to the Xilinx project",
"info.pl.xilinx.no-need-del-files": "There are no files to be deleted from Xilinx."
"info.pl.xilinx.no-need-del-files": "There are no files to be deleted from Xilinx.",
"error.pl.launch.not-valid-vivado-path": "Error encountered while starting the Vivado TCL script interpreter: {0}. Please check if your Vivado startup path is correct. Currently set Vivado startup folder path: {1}",
"info.pl.launch.set-vivado-path": "Go to set the Vivado installation path"
}

View File

@ -69,5 +69,7 @@
"info.pl.xilinx.update-addfiles": "ファイルを Xilinx プロジェクトに追加",
"info.pl.xilinx.update-delfiles": "以下のファイルをXilinxプロジェクトから削除してください。",
"info.pl.xilinx.no-need-add-files": "Xilinx プロジェクトに追加するファイルはありません",
"info.pl.xilinx.no-need-del-files": "Xilinx から削除するファイルはありません。"
"info.pl.xilinx.no-need-del-files": "Xilinx から削除するファイルはありません。",
"error.pl.launch.not-valid-vivado-path": "Vivado TCL スクリプトインタプリタの起動中にエラーが発生しました:{0}。Vivado の起動パスが正しいか確認してください。現在設定されている Vivado 起動フォルダパス:{1}",
"info.pl.launch.set-vivado-path": "Vivado インストールパスの設定に移動"
}

View File

@ -69,5 +69,7 @@
"info.pl.xilinx.update-addfiles": "添加文件到 Xilinx 工程",
"info.pl.xilinx.update-delfiles": "将下方文件从 Xilinx 工程中删除",
"info.pl.xilinx.no-need-add-files": "没有需要添加到 Xilinx 工程的文件",
"info.pl.xilinx.no-need-del-files": "没有需要从 Xilinx 中删除的文件"
"info.pl.xilinx.no-need-del-files": "没有需要从 Xilinx 中删除的文件",
"error.pl.launch.not-valid-vivado-path": "启动 Vivado TCL 脚本解释器遇到错误:{0} 。请检查你的 Vivado 启动路径是否正确,当前设置的 Vivado 启动文件夹路径:{1}",
"info.pl.launch.set-vivado-path": "前往设置 Vivado 安装路径"
}

View File

@ -69,5 +69,7 @@
"info.pl.xilinx.update-addfiles": "將檔案新增到 Xilinx 專案",
"info.pl.xilinx.update-delfiles": "從 Xilinx 專案中刪除以下檔案。",
"info.pl.xilinx.no-need-add-files": "沒有需要添加到 Xilinx 工程的文件",
"info.pl.xilinx.no-need-del-files": "沒有需要從 Xilinx 中刪除的檔案。"
"info.pl.xilinx.no-need-del-files": "沒有需要從 Xilinx 中刪除的檔案。",
"error.pl.launch.not-valid-vivado-path": "啟動 Vivado TCL 腳本解釋器遇到錯誤:{0} 。請檢查你的 Vivado 啟動路徑是否正確,目前設定的 Vivado 啟動資料夾路徑:{1}",
"info.pl.launch.set-vivado-path": "前往設定 Vivado 安裝路徑"
}

View File

@ -1,4 +1,13 @@
{
"clock": {
"prefix": "create_pll",
"body": [
"create_clock -period 20.000 [get_ports clock]",
"set_input_jitter [get_clocks -of_objects [get_ports clock]] 0.200",
"set_property PHASESHIFT_MODE WAVEFORM [get_cells -hierarchical *adv*]"
]
},
"ILA_CORE": {
"prefix": "create_ILA_CORE",
"body": [
@ -8,6 +17,7 @@
"connect_debug_port dbg_hub/clk [get_nets [list CLK_Global_u/clk_out${2:3}]]"
]
},
"Debug_CORE": {
"prefix": "create_Debug_CORE",
"body": [
@ -24,6 +34,7 @@
"connect_debug_port u_ila_$1/clk [get_nets [list CLK_Global_u/clk_out${3:3}]]"
]
},
"Debug_add_port": {
"prefix": "add_port",
"body": [

View File

@ -1,210 +1,18 @@
{
"IDDR": {
"prefix": "iddr",
"body" : [
"IDDR #(",
" // \"OPPOSITE_EDGE\", \"SAME_EDGE\" or \"SAME_EDGE_PIPELINED\" ",
" .DDR_CLK_EDGE(\"SAME_EDGE\"), ",
" .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1",
" .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1",
" .SRTYPE(\"SYNC\")) // Set/Reset type: \"SYNC\" or \"ASYNC\" ",
"IDDR_inst (",
"IDDR #(",
" .Q1(rx_data_pos), // 1-bit output for positive edge of clock ",
" .Q2(rx_data_neg), // 1-bit output for negative edge of clock",
" .C(data_clk), // 1-bit clock input",
" .CE(1'b1), // 1-bit clock enable input",
" .D(rx_data_dly), // 1-bit DDR data input",
" .R(1'b0), // 1-bit reset",
" .S(1'b0) // 1-bit set",
");"
]
},
"ODDR": {
"prefix": "oddr",
"body" : [
"ODDR #(",
" .DDR_CLK_EDGE(\"SAME_EDGE\"), // \"OPPOSITE_EDGE\" or \"SAME_EDGE\" ",
" .INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1",
" .SRTYPE(\"SYNC\")) // Set/Reset type: \"SYNC\" or \"ASYNC\" ",
"ODDR_inst (",
" .Q(odata), // 1-bit DDR output",
" .C(data_clk), // 1-bit clock input",
" .CE(1'b1), // 1-bit clock enable input",
" .D1(data_p), // 1-bit data input (positive edge)",
" .D2(data_n), // 1-bit data input (negative edge)",
" .R(1'b0), // 1-bit reset",
" .S(1'b0) // 1-bit set",
");"
]
},
"OBUFDS": {
"prefix": "obuf",
"body" : [
"OBUFDS #(",
" .IOSTANDARD(\"LVDS18\"), // Specify the output I/O standard",
" .SLEW(\"SLOW\")) // Specify the output slew rate",
"OBUFDS_inst (",
" .O(tx_frame_p), // Diff_p output (connect directly to top-level port)",
" .OB(tx_frame_n), // Diff_n output (connect directly to top-level port)",
" .I(tx_frame) // Buffer input ",
");"
]
},
"IBUFDS": {
"prefix": "ibuf",
"body" : [
"IBUFDS #(",
" .DIFF_TERM(\"FALSE\"), // Differential Termination",
" .IBUF_LOW_PWR(\"TRUE\"), // Low power=\"TRUE\", Highest performance=\"FALSE\" ",
" .IOSTANDARD(\"DEFAULT\")) // Specify the input I/O standard",
"IBUFDS_inst (",
" .O(data_clk_tmp), // Buffer output",
" .I(data_clk_p), // Diff_p buffer input (connect directly to top-level port)",
" .IB(data_clk_n) // Diff_n buffer input (connect directly to top-level port)",
");"
]
},
"OSERDESE2": {
"prefix": "oserd",
"body" : [
"OSERDESE2 #(",
" .DATA_RATE_OQ(\"DDR\"), // DDR, SDR",
" .DATA_RATE_TQ(\"DDR\"), // DDR, BUF, SDR",
" .DATA_WIDTH(4), // Parallel data width (2-8,10,14)",
" .INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1)",
" .INIT_TQ(1'b0), // Initial value of TQ output (1'b0,1'b1)",
" .SERDES_MODE(\"MASTER\"), // MASTER, SLAVE",
" .SRVAL_OQ(1'b0), // OQ output value when SR is used (1'b0,1'b1)",
" .SRVAL_TQ(1'b0), // TQ output value when SR is used (1'b0,1'b1)",
" .TBYTE_CTL(\"FALSE\"), // Enable tristate byte operation (FALSE, TRUE)",
" .TBYTE_SRC(\"FALSE\"), // Tristate byte source (FALSE, TRUE)",
" .TRISTATE_WIDTH(4) // 3-state converter width (1,4)",
")",
"OSERDESE2_inst (",
" .OFB(OFB), // 1-bit output: Feedback path for data",
" .OQ(OQ), // 1-bit output: Data path output",
" // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)",
" .SHIFTOUT1(SHIFTOUT1),",
" .SHIFTOUT2(SHIFTOUT2),",
" .TBYTEOUT(TBYTEOUT), // 1-bit output: Byte group tristate",
" .TFB(TFB), // 1-bit output: 3-state control",
" .TQ(TQ), // 1-bit output: 3-state control",
" .CLK(CLK), // 1-bit input: High speed clock",
" .CLKDIV(CLKDIV), // 1-bit input: Divided clock",
" // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)",
" .D1(D1),",
" .D2(D2),",
" .D3(D3),",
" .D4(D4),",
" .D5(D5),",
" .D6(D6),",
" .D7(D7),",
" .D8(D8),",
" .OCE(OCE), // 1-bit input: Output data clock enable",
" .RST(RST), // 1-bit input: Reset",
" // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)",
" .SHIFTIN1(SHIFTIN1),",
" .SHIFTIN2(SHIFTIN2),",
" // T1 - T4: 1-bit (each) input: Parallel 3-state inputs",
" .T1(T1),",
" .T2(T2),",
" .T3(T3),",
" .T4(T4),",
" .TBYTEIN(TBYTEIN), // 1-bit input: Byte group tristate",
" .TCE(TCE) // 1-bit input: 3-state clock enable",
");"
]
},
"ISERDESE2": {
"prefix": "iserd",
"body" : [
"ISERDESE2 #(",
" .DATA_RATE(\"DDR\"), // DDR, SDR",
" .DATA_WIDTH(4), // Parallel data width (2-8,10,14)",
" .DYN_CLKDIV_INV_EN(\"FALSE\"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)",
" .DYN_CLK_INV_EN(\"FALSE\"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)",
" // INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)",
" .INIT_Q1(1'b0),",
" .INIT_Q2(1'b0),",
" .INIT_Q3(1'b0),",
" .INIT_Q4(1'b0),",
" .INTERFACE_TYPE(\"MEMORY\"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE",
" .IOBDELAY(\"NONE\"), // NONE, BOTH, IBUF, IFD",
" .NUM_CE(2), // Number of clock enables (1,2)",
" .OFB_USED(\"FALSE\"), // Select OFB path (FALSE, TRUE)",
" .SERDES_MODE(\"MASTER\"), // MASTER, SLAVE",
" // SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)",
" .SRVAL_Q1(1'b0),",
" .SRVAL_Q2(1'b0),",
" .SRVAL_Q3(1'b0),",
" .SRVAL_Q4(1'b0))",
"ISERDESE2_inst (",
" .O(O), // 1-bit output: Combinatorial output",
" // Q1 - Q8: 1-bit (each) output: Registered data outputs",
" .Q1(Q1),",
" .Q2(Q2),",
" .Q3(Q3),",
" .Q4(Q4),",
" .Q5(Q5),",
" .Q6(Q6),",
" .Q7(Q7),",
" .Q8(Q8),",
" // SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports",
" .SHIFTOUT1(SHIFTOUT1),",
" .SHIFTOUT2(SHIFTOUT2),",
"\n",
" // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to",
" // CLKDIV when asserted (active High). Subsequently, the data seen on the Q1",
" // to Q8 output ports will shift, as in a barrel-shifter operation, one",
" // position every time Bitslip is invoked (DDR operation is different from",
" // SDR).",
" .BITSLIP(BITSLIP), ",
"\n",
" // CE1, CE2: 1-bit (each) input: Data register clock enable inputs",
" .CE1(CE1),",
" .CE2(CE2),",
" .CLKDIVP(CLKDIVP), // 1-bit input: TBD",
" // Clocks: 1-bit (each) input: ISERDESE2 clock input ports",
" .CLK(CLK), // 1-bit input: High-speed clock",
" .CLKB(CLKB), // 1-bit input: High-speed secondary clock",
" .CLKDIV(CLKDIV), // 1-bit input: Divided clock",
" .OCLK(OCLK), // 1-bit input: High speed output clock used when INTERFACE_TYPE=\"MEMORY\" ",
" // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity",
" .DYNCLKDIVSEL(DYNCLKDIVSEL), // 1-bit input: Dynamic CLKDIV inversion",
" .DYNCLKSEL(DYNCLKSEL), // 1-bit input: Dynamic CLK/CLKB inversion",
" // Input Data: 1-bit (each) input: ISERDESE2 data input ports",
" .D(D), // 1-bit input: Data input",
" .DDLY(DDLY), // 1-bit input: Serial data from IDELAYE2",
" .OFB(OFB), // 1-bit input: Data feedback from OSERDESE2",
" .OCLKB(OCLKB), // 1-bit input: High speed negative edge output clock",
" .RST(RST), // 1-bit input: Active high asynchronous reset",
" // SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports",
" .SHIFTIN1(SHIFTIN1),",
" .SHIFTIN2(SHIFTIN2)",
");"
]
},
"count": {
"prefix": "count",
"counter": {
"prefix": "counter",
"body": [
"//define the time counter",
"reg [${1:32}:0] cnt$2 = 0;",
"reg ${3:impulse};",
"parameter SET_TIME = $1'd$4;",
"always@(posedge clk) begin",
" if (cnt$2 == SET_TIME) begin",
" cnt$2 <= $1'd0;",
"reg [${1:32}:0] count$2;",
"reg ${3:impulse};",
"always@(posedge clock) begin",
" if (count$2 == SET_TIME) begin",
" count$2 <= $1'd0;",
" $3 <= 1'd1;",
" end",
" else begin",
" cnt$2 <= cnt$2 + 1'd1;",
" count$2 <= count$2 + 1'd1;",
" $3 <= 1'd0;",
" end",
"end"
@ -214,15 +22,15 @@
"divclk": {
"prefix": "div",
"body": [
"reg [${1:3}:0] cnt$2 = 0;",
"reg clk_div$2;",
"always@(posedge ${3:clk}) begin",
" if (cnt$2 == ${4:3}) begin",
" cnt$2 <= $1'd0;",
"reg [${1:3}:0] count$2;",
"reg clk_div$2;",
"always@(posedge ${3:clock}) begin",
" if (count$2 == ${4:3}) begin",
" count$2 <= $1'd0;",
" clk_div$2 <= ~clk_div$2;",
" end",
" else begin",
" cnt$2 <= cnt$2 + 1'd1;",
" count$2 <= count$2 + 1'd1;",
" end",
"end"
]
@ -234,10 +42,10 @@
"reg gate$2;",
"reg gate$2_buf;",
"wire gate$2_pose = gate$2 & ~gate$2_buf;",
"wire gate$2_nege = ~gate$2 & gate$2_buf;",
"wire gate$2_pos = gate$2 & ~gate$2_buf;",
"wire gate$2_neg = ~gate$2 & gate$2_buf;",
"always@(posedge clk) begin",
"always@(posedge clock) begin",
" gate$2 <= ${1:signal};",
" gate$2_buf <= gate$2;",
"end"
@ -262,9 +70,9 @@
"prefix": "resetn",
"body": [
"reg rst_n_s1, rst_n_s2;",
"wire rst_n",
"always @ (posedge clk or negedge sys_rst_n) begin",
" if (sys_rst_n) begin",
"wire sys_rstn",
"always @ (posedge clock or negedge rstn) begin",
" if (rstn) begin",
" rst_n_s2 <= 1'b0;",
" rst_n_s1 <= 1'b0;",
" end",
@ -272,18 +80,18 @@
" rst_n_s2 <= rst_n_s1;",
" end",
"end",
"assign rst_n = rst_n_s2;"
"assign sys_rstn = rst_n_s2;"
],
"description" : "Asynchronous sys_rst_n synchronous release (intel device)"
"description" : "Asynchronous sys_rstn synchronous release (intel device)"
},
"reset": {
"prefix": "reset",
"body": [
"reg rst_s1, rst_s2;",
"wire rst",
"always @ (posedge clk or posedge sys_rst) begin",
" if (sys_rst) begin",
"wire sys_rst",
"always @ (posedge clock or posedge reset) begin",
" if (reset) begin",
" rst_s2 <= 1'b0;",
" rst_s1 <= 1'b0;",
" end",
@ -291,9 +99,9 @@
" rst_s2 <= rst_s1;",
" end",
"end",
"assign rst = rst_s2;"
"assign sys_rst = rst_s2;"
],
"description" : "Asynchronous sys_rst synchronous release (xilinx device)"
"description" : "Asynchronous reset synchronous release (xilinx device)"
},
"initial sim": {
@ -369,18 +177,18 @@
"alwaysposclk": {
"prefix": "alclk",
"body": [
"always @(posedge clk) begin",
"always @(posedge clock) begin",
" $1;",
"end"
],
"description": "always @(posedge clk) directly"
"description": "always @(posedge clock) directly"
},
"alwayssyncrst": {
"prefix": "alsync",
"body": [
"always @(posedge clk) begin",
" if(rst) begin",
"always @(posedge clock) begin",
" if(reset) begin",
" $1 <= 0;",
" end",
" else begin",
@ -394,8 +202,8 @@
"alwaysasyncrst": {
"prefix": "alasync",
"body": [
"always @(posedge clk or posedge rst) begin",
" if(rst) begin",
"always @(posedge clock or posedge reset) begin",
" if(reset) begin",
" $1 <= 0;",
" end",
" else begin",
@ -409,8 +217,8 @@
"alwayssyncrstn": {
"prefix": "alsyncn",
"body": [
"always @(posedge clk) begin",
" if(!rst_n) begin",
"always @(posedge clock) begin",
" if(!rstn) begin",
" $1 <= 0;",
" end",
" else begin",
@ -418,14 +226,14 @@
" end",
"end"
],
"description": "synchronous rst_n (intel device)"
"description": "synchronous rstn (intel device)"
},
"alwaysasyncrstn": {
"prefix": "alasyncn",
"body": [
"always @(posedge clk or negedge rst_n) begin",
" if(!rst_n) begin",
"always @(posedge clock or negedge rstn) begin",
" if(!rstn) begin",
" $1 <= 0;",
" end",
" else begin",
@ -433,7 +241,7 @@
" end",
"end"
],
"description": "asynchronous rst_n (intel device)"
"description": "asynchronous rstn (intel device)"
},
"beginend": {
@ -461,13 +269,13 @@
"prefix": "modp",
"body": [
"module ${1:name} #(",
" parameter INPUT_WIDTH = ${2:12},",
" parameter OUTPUT_WIDTH = $2",
" parameter IWIDTH = ${2:12},",
" parameter OWIDTH = $2",
") (",
" input clk,",
" input RST,",
" input [INPUT_WIDTH - 1 : 0] ${3:data_i},",
" output [OUTPUT_WIDTH - 1 : 0] ${4:data_o}",
" input clock,",
" input reset,",
" input [IWIDTH - 1 : 0] ${3:data_i},",
" output [OWIDTH - 1 : 0] ${4:data_o}",
");",
" $5",
"endmodule //$1\n"
@ -479,8 +287,8 @@
"prefix": "mod",
"body": [
"module ${1:moduleName} (",
" input clk,",
" input rst,",
" input clock,",
" input reset,",
" $2",
");",
" $3",
@ -488,6 +296,7 @@
],
"description": "Insert a module without parameter"
},
"simple module": {
"prefix": "module",
"body": [
@ -497,6 +306,7 @@
],
"description": "Insert a common module"
},
"generate_for": {
"prefix": "genfor",
"body": [
@ -903,18 +713,21 @@
"*/"
]
},
"dumpfile": {
"prefix": "$dumpfile",
"body": [
"\\$dumpfile(\"$1\");"
]
},
"dumpvars": {
"prefix": "$dumpvars",
"body": [
"\\$dumpvars;"
]
},
"finish": {
"prefix": "$finish",
"body": [

View File

@ -8,6 +8,7 @@
],
"description": "For Loop"
},
"foreach": {
"prefix": "foreach",
"body": [
@ -17,6 +18,7 @@
],
"description": "Foreach Loop"
},
"if": {
"prefix": "if",
"body": [
@ -26,6 +28,7 @@
],
"description": "If Condition"
},
"elseif": {
"prefix": "elseif",
"body": [
@ -35,6 +38,7 @@
],
"description": "ElseIf Condition"
},
"else": {
"prefix": "else",
"body": [
@ -44,6 +48,7 @@
],
"description": "Else Block"
},
"proc": {
"prefix": "proc",
"body": [
@ -53,6 +58,7 @@
],
"description": "Proc Block"
},
"while": {
"prefix": "while",
"body": [
@ -62,6 +68,7 @@
],
"description": "While Loop"
},
"catch": {
"prefix": "catch",
"body": [
@ -69,6 +76,7 @@
],
"description": "Catch Block"
},
"try": {
"prefix": "try",
"body": [
@ -80,6 +88,7 @@
],
"description": "Try Block"
},
"switch": {
"prefix": "switch",
"body": [
@ -90,6 +99,7 @@
],
"description": "Switch Block"
},
"oo::class create": {
"prefix": "oo::class create",
"body": [
@ -105,6 +115,7 @@
],
"description": "Class Create"
},
"tk_chooseDirectory": {
"prefix": "tk_chooseDirectory",
"body": [
@ -112,6 +123,7 @@
],
"description": "Choose Directory"
},
"tk_getOpenFile": {
"prefix": "tk_getOpenFile",
"body": [
@ -122,6 +134,7 @@
],
"description": "Open File Dialog"
},
"tk_getSaveFile": {
"prefix": "tk_getSaveFile",
"body": [
@ -132,6 +145,7 @@
],
"description": "Save File Dialog"
},
"tk_messageBox": {
"prefix": "tk_messageBox",
"body": [
@ -139,6 +153,7 @@
],
"description": "Message Box"
},
"set_property": {
"prefix": "set_property",
"body": [
@ -146,18 +161,21 @@
],
"description": "set property"
},
"create_clock": {
"prefix": "create_clock",
"body": [
"create_clock ${1:signal_name} ${2:clock_name} ${3:frequency} ${4:uncertainty}"
]
},
"set_initial_state": {
"prefix": "set_initial_state",
"body": [
"set_initial_5state ${1:initial_state}"
]
},
"connect_port": {
"prefix": "connect_port",
"body": [

View File

@ -5,120 +5,140 @@
"description": "asynchronous process",
"scope": "source.vhdl"
},
"arch": {
"prefix": "arch",
"body": "architecture ${1:arch} of ${2:ent} is\n\n\tsignal $0\n\nbegin\n\nend ${1:arch} ; -- ${1:arch}",
"description": "architecture",
"scope": "source.vhdl"
},
"case": {
"prefix": "case",
"body": "case( ${1:signal_name} ) is\n\n\twhen ${2:IDLE} =>\n\t\t$0\n\n\twhen others =>\n\nend case ;",
"description": "case",
"scope": "source.vhdl"
},
"else": {
"prefix": "else",
"body": "else\n\t$0",
"description": "else",
"scope": "source.vhdl"
},
"elsif": {
"prefix": "elsif",
"body": "elsif ${1:expression} then\n\t$0",
"description": "elsif",
"scope": "source.vhdl"
},
"ent": {
"prefix": "ent",
"body": "entity ${1:ent} is\n port (\n\t${0:clock}\n ) ;\nend ${1:ent};",
"description": "entity",
"scope": "source.vhdl"
},
"entarch": {
"prefix": "entarch",
"body": "entity ${1:ent} is\n port (\n\t${0:clock}\n ) ;\nend ${1:ent} ;\n\narchitecture ${2:arch} of ${1:ent} is\n\n\n\nbegin\n\n\n\nend architecture ; -- ${2:arch}",
"description": "entity architecture",
"scope": "source.vhdl"
},
"for": {
"prefix": "for",
"body": "${1:identifier} : for ${2:i} in ${3:0} to ${4:10} loop\n\t$0\nend loop ; -- ${1:identifier}",
"description": "for loop",
"scope": "source.vhdl"
},
"forg": {
"prefix": "forg",
"body": "${1:identifier} : for ${2:i} in ${3:x} to ${4:y} generate\n\t$0\nend generate ; -- ${1:identifier}",
"description": "for generate",
"scope": "source.vhdl"
},
"if": {
"prefix": "if",
"body": "if ${1:expression} then\n\t$0\nend if ;",
"description": "if",
"scope": "source.vhdl"
},
"pack": {
"prefix": "pack",
"body": "package ${1:pkg} is\n\t$0\nend package ;",
"description": "package",
"scope": "source.vhdl"
},
"pro": {
"prefix": "pro",
"body": "${1:identifier} : process( ${2:sensitivity_list} )\nbegin\n\t$0\nend process ; -- ${1:identifier}",
"description": "process",
"scope": "source.vhdl"
},
"s": {
"prefix": "s",
"body": "signed(${1:x} downto ${2:0}) ;$0",
"description": "signed downto",
"scope": "source.vhdl"
},
"sr": {
"prefix": "sr",
"body": "signed(${1:signal}'range) ;$0",
"description": "signed range",
"scope": "source.vhdl"
},
"spro": {
"prefix": "spro",
"body": "${1:identifier} : process( ${2:clock} )\nbegin\n\tif( rising_edge(${2:clock}) ) then\n\t\t$0\n\tend if ;\nend process ; -- ${1:identifier}",
"description": "synchronous process",
"scope": "source.vhdl"
},
"slv": {
"prefix": "slv",
"body": "std_logic_vector(${1:x} downto ${2:0}) ;$0",
"description": "std_logic_vector downto",
"scope": "source.vhdl"
},
"slvr": {
"prefix": "slvr",
"body": "std_logic_vector(${1:signal}'range) ;$0",
"description": "std_logic_vector range",
"scope": "source.vhdl"
},
"u": {
"prefix": "u",
"body": "unsigned(${1:x} downto ${2:0}) ;$0",
"description": "unsigned downto",
"scope": "source.vhdl"
},
"ur": {
"prefix": "ur",
"body": "unsigned(${1:signal}'range) ;$0",
"description": "unsigned range",
"scope": "source.vhdl"
},
"vhdl": {
"prefix": "vhdl",
"body": "library ieee ;\n\tuse ieee.std_logic_1164.all ;\n\tuse ieee.numeric_std.all ;\n\nentity ${1:ent} is\n port (\n\t${0:clock}\n ) ;\nend ${1:ent} ; \n\narchitecture ${2:arch} of ${1:ent} is\n\nbegin\n\nend architecture ;",
"description": "vhdl template",
"scope": "source.vhdl"
},
"while": {
"prefix": "while",
"body": "${1:identifier} : while ${2:expression} loop\n\t$0\nend loop ; -- ${1:identifier}",

View File

@ -71,7 +71,7 @@ class WaveViewer {
this.panel.iconPath = getIconConfig('view');
registerMessageEvent(this.panel, uri);
} else {
WaveViewOutput.report('preview html in <WaveViewer.create> is empty', ReportType.Warn);
WaveViewOutput.report('preview html in <WaveViewer.create> is empty', { level: ReportType.Warn });
}
}
@ -138,7 +138,7 @@ class VcdViewerProvider implements vscode.CustomEditorProvider {
webviewPanel.webview.html = preprocessHtml;
webviewPanel.iconPath = getIconConfig('view');
} else {
WaveViewOutput.report('preview html in <WaveViewer.create> is empty', ReportType.Warn);
WaveViewOutput.report('preview html in <WaveViewer.create> is empty', { level: ReportType.Warn });
}
}

View File

@ -4,7 +4,7 @@ import * as fspath from 'path';
import { AbsPath, opeParam, MainOutput, ReportType } from '../../global';
import { hdlParam, HdlModule, HdlFile, HdlInstance } from '../../hdlParser/core';
import { HdlModulePort, HdlModuleParam, InstModPathStatus } from '../../hdlParser/common';
import { HdlModulePort, HdlModuleParam, InstModPathStatus, HdlFileProjectType } from '../../hdlParser/common';
import { MarkdownString, RenderString, RenderType,
mergeSortByLine, getWavedromsFromFile, Count, WavedromString } from './common';
@ -43,7 +43,7 @@ function selectFieldValue(obj: any, subName: string, ws: string, name: string, i
if (fs.existsSync(value)) {
// 判断 类型
const hdlFile = hdlParam.getHdlFile(value);
if (hdlFile && hdlFile.type === 'remote_lib') {
if (hdlFile && hdlFile.projectType === HdlFileProjectType.RemoteLib) {
// 如果是 库 文件,做出更加自定义的字面量
const libRelPath = value.replace(`${opeParam.extensionPath}/library/`, '');
value = `<span class="source-lib-tag">library</span> [${libRelPath}](file://${value})`;
@ -277,10 +277,12 @@ async function getDocsFromFile(path: AbsPath): Promise<MarkdownString[] | undefi
const standardPath = hdlPath.toSlash(path);
const response = await doFastApi(standardPath, 'common');
const langID = hdlFile.getLanguageId(standardPath);
const projectType = hdlParam.getHdlFileProjectType(standardPath, 'common');
moduleFile = new HdlFile(
standardPath, langID,
response?.macro || defaultMacro,
response?.content || [],
projectType,
'common'
);
// 从 hdlParam 中去除,避免干扰全局

View File

@ -55,7 +55,10 @@ class VivadoLinter implements BaseLinter {
this.diagnostic.set(document.uri, diagnostics);
}
} else {
LspOutput.report('vivado linter is not available, please check prj.vivado.install.path in your setting', ReportType.Error, true);
LspOutput.report('vivado linter is not available, please check prj.vivado.install.path in your setting', {
level: ReportType.Error,
notify: true
});
}
}
@ -79,7 +82,9 @@ class VivadoLinter implements BaseLinter {
if (headerInfo === 'ERROR') {
const errorInfos = parsedPath.split(':');
const errorLine = Math.max(parseInt(errorInfos[errorInfos.length - 1]) - 1, 0);
LspOutput.report(`<xvlog linter> line: ${errorLine}, info: ${syntaxInfo}`, ReportType.Run);
LspOutput.report(`<xvlog linter> line: ${errorLine}, info: ${syntaxInfo}`, {
level: ReportType.Run
});
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
@ -136,8 +141,13 @@ class VivadoLinter implements BaseLinter {
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.bat' : executorName;
if (vivadoInstallPath.trim() === '' || !fs.existsSync(vivadoInstallPath)) {
LspOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid. Use ${executorName} in default.`, ReportType.Warn);
LspOutput.report('If you have doubts, check prj.vivado.install.path in setting', ReportType.Warn);
LspOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid. Use ${executorName} in default.`, {
level: ReportType.Warn
});
LspOutput.report('If you have doubts, check prj.vivado.install.path in setting', {
level: ReportType.Warn
});
return executorName;
} else {
LspOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid`);
@ -161,11 +171,16 @@ class VivadoLinter implements BaseLinter {
const { stderr } = await easyExec(executorPath, []);
if (stderr.length === 0) {
this.executableInvokeNameMap.set(langID, executorPath);
LspOutput.report(`success to verify ${executorPath}, linter from vivado is ready to go!`, ReportType.Launch);
LspOutput.report(`success to verify ${executorPath}, linter from vivado is ready to go!`, {
level: ReportType.Launch
});
return true;
} else {
this.executableInvokeNameMap.set(langID, undefined);
LspOutput.report(`Fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error, true);
LspOutput.report(`Fail to execute ${executorPath}! Reason: ${stderr}`, {
level: ReportType.Error,
notify: true
});
return false;
}
}

View File

@ -31,10 +31,12 @@ class Netlist {
const standardPath = hdlPath.toSlash(path);
const response = await doFastApi(standardPath, 'common');
const langID = hdlFile.getLanguageId(standardPath);
const projectType = hdlParam.getHdlFileProjectType(standardPath, 'common');
moduleFile = new HdlFile(
standardPath, langID,
response?.macro || defaultMacro,
response?.content || [],
projectType,
'common'
);
// 从 hdlParam 中去除,避免干扰全局

View File

@ -73,7 +73,10 @@ class Simulate {
};
let code = hdlFile.readFile(path);
if (!code) {
MainOutput.report('error when read ' + path, ReportType.Error, true);
MainOutput.report('error when read ' + path, {
level: ReportType.Error,
notify: true
});
return;
}
@ -95,7 +98,9 @@ class Simulate {
if (!hdlFile.isDir(simConfig.simulationHome)) {
MainOutput.report('create dir ' + simConfig.simulationHome, ReportType.Info);
MainOutput.report('create dir ' + simConfig.simulationHome, {
level: ReportType.Info
});
hdlDir.mkdir(simConfig.simulationHome);
}
@ -113,7 +118,10 @@ class Simulate {
simConfig.installPath = setting.get('digital-ide.function.simulate.icarus.installPath', '');
if (simConfig.installPath !== '' && !hdlFile.isDir(simConfig.installPath)) {
MainOutput.report(`install path ${simConfig.installPath} is illegal`, ReportType.Error, true);
MainOutput.report(`install path ${simConfig.installPath} is illegal`, {
level: ReportType.Error,
notify: true
});
return;
}
@ -252,7 +260,9 @@ class IcarusSimulate extends Simulate {
// console.log(thirdLibraryFileArgs);
const cmd = `${iverilogPath} ${argu} -o ${outVvpPath} -s ${name} ${macroIncludeArgs} ${thirdLibraryDirArgs} ${mainPath} ${dependenceArgs} ${thirdLibraryFileArgs}`;
MainOutput.report(cmd, ReportType.Run);
MainOutput.report(cmd, {
level: ReportType.Run
});
return cmd;
}
@ -287,26 +297,42 @@ class IcarusSimulate extends Simulate {
}
child_process.exec(command, { cwd }, (error, stdout, stderr) => {
if (error) {
MainOutput.report('Error took place when run ' + command, ReportType.Error);
MainOutput.report('Reason: ' + stderr, ReportType.Error);
MainOutput.report('Error took place when run ' + command, {
level: ReportType.Error
});
MainOutput.report('Reason: ' + stderr, {
level: ReportType.Error
});
} else {
MainOutput.report(stdout, ReportType.Info);
MainOutput.report(stdout, {
level: ReportType.Info
});
const vvpOutFile = hdlPath.join(simConfig.simulationHome, 'out.vvp');
MainOutput.report("Create vvp to " + vvpOutFile, ReportType.Run);
MainOutput.report("Create vvp to " + vvpOutFile, {
level: ReportType.Run
});
const outVvpPath = hdlPath.join(simConfig.simulationHome, 'out.vvp');
const vvpPath = simConfig.vvpPath;
// run vvp to interrupt script
const vvpCommand = `${vvpPath} ${outVvpPath}`;
MainOutput.report(vvpCommand, ReportType.Run);
MainOutput.report(vvpCommand, {
level: ReportType.Run
});
child_process.exec(vvpCommand, { cwd }, (error, stdout, stderr) => {
if (error) {
MainOutput.report('Error took place when run ' + vvpCommand, ReportType.Error);
MainOutput.report('Reason: ' + stderr, ReportType.Error);
MainOutput.report('Error took place when run ' + vvpCommand, {
level: ReportType.Error
});
MainOutput.report('Reason: ' + stderr, {
level: ReportType.Error
});
} else {
MainOutput.report(stdout, ReportType.Info);
MainOutput.report(stdout, {
level: ReportType.Info
});
}
});
}
@ -355,7 +381,10 @@ class IcarusSimulate extends Simulate {
this.exec(simulationCommand, cwd);
} else {
const errorMsg = 'Fail to generate command';
MainOutput.report(errorMsg, ReportType.Error, true);
MainOutput.report(errorMsg, {
level: ReportType.Error,
notify: true
});
return;
}
}
@ -386,15 +415,13 @@ class IcarusSimulate extends Simulate {
}
const standardPath = hdlPath.toSlash(path);
console.log('enter [doFastApi]');
const response = await doFastApi(standardPath, 'common');
console.log('response result: ');
console.log(response);
const projectType = hdlParam.getHdlFileProjectType(standardPath, 'common');
const moduleFile = new HdlFile(
standardPath, langID,
response?.macro || defaultMacro,
response?.content || [],
projectType,
'common'
);
// 从 hdlParam 中去除,避免干扰全局
@ -418,7 +445,10 @@ class IcarusSimulate extends Simulate {
if (targetModule !== undefined) {
this.simulateByHdlModule(targetModule);
} else {
MainOutput.report('There is no module named ' + view.name + ' in ' + view.path, ReportType.Error, true);
MainOutput.report('There is no module named ' + view.name + ' in ' + view.path, {
level: ReportType.Error,
notify: true
});
return;
}
}

View File

@ -49,7 +49,9 @@ function openFileByUri(path: string, range: Range, element: ModuleDataItem) {
}
}
}
MainOutput.report("invalid jump uri triggered in treeview, el: " + JSON.stringify(element, null, ' '), ReportType.Error);
MainOutput.report("invalid jump uri triggered in treeview, el: " + JSON.stringify(element, null, ' '), {
level: ReportType.Error
});
}
function gotoXilinxIPDefinition(element: ModuleDataItem) {
@ -63,7 +65,9 @@ function gotoXilinxIPDefinition(element: ModuleDataItem) {
vscode.window.showInformationMessage(t('info.treeview.ip-no-active.message'));
}
} else {
MainOutput.report("[gotoXilinxIPDefinition] path is undefined", ReportType.Error);
MainOutput.report("[gotoXilinxIPDefinition] path is undefined", {
level: ReportType.Error
});
}
}

View File

@ -3,7 +3,7 @@ import * as vscode from 'vscode';
import { AbsPath, MainOutput, opeParam, ReportType } from '../../global';
import { SimPath, SrcPath } from '../../global/prjInfo';
import { HdlInstance, hdlParam } from '../../hdlParser/core';
import { HdlFileType, Range } from '../../hdlParser/common';
import { HdlFileProjectType, Range } from '../../hdlParser/common';
import { hdlFile, hdlPath } from '../../hdlFs';
import { xilinx, itemModes, otherModes } from './common';
import { getIconConfig } from '../../hdlFs/icons';
@ -71,7 +71,7 @@ class ModuleTreeProvider implements vscode.TreeDataProvider<ModuleDataItem> {
this.srcRootItem = {
icon: 'src',
type: HdlFileType.Src,
type: HdlFileProjectType.Src,
doFastFileType: undefined,
name: 'src',
range: undefined,
@ -81,7 +81,7 @@ class ModuleTreeProvider implements vscode.TreeDataProvider<ModuleDataItem> {
this.simRootItem = {
icon: 'sim',
type: HdlFileType.Sim,
type: HdlFileProjectType.Sim,
doFastFileType: undefined,
name: 'sim',
range: undefined,

View File

@ -2,16 +2,53 @@
import * as vscode from 'vscode';
enum ReportType {
/**
* debug
*/
Debug = 'Debug',
/**
*
*/
Launch = 'Launch',
/**
*
*/
Performance = 'Performance',
/**
* debug
*/
PathCheck = 'Path Check',
/**
*
*/
Info = 'Info',
/**
* warn
*/
Warn = 'Warn',
/**
* error
*/
Error = 'Error',
/**
*
*/
Run = 'Run'
};
interface ReportOption {
/**
* level
* [ReportType](https://github.com/Digital-EDA/Digital-IDE/blob/main/src/global/outputChannel.ts#L4)
*/
level?: ReportType,
/**
* true
* vscode.window.showInformationMessage false
*/
notify?: boolean
}
class Output {
private _output: vscode.OutputChannel;
private _ignoreTypes: ReportType[];
@ -51,19 +88,21 @@ class Output {
}
/**
*
* @description Output
* @param message message
* @param type report type
* @param reportInWindows whether use vscode.windows.<api> to show info
* @param option
*/
public report(message: string | unknown, type: ReportType = ReportType.Info, reportInWindows: boolean = false) {
if (!this.skipMessage(type) && message) {
// this._output.show(true);
const currentTime = this.getCurrentTime();
this._output.appendLine('[' + type + ' - ' + currentTime + '] ' + message);
public report(message: string | unknown, option?: ReportOption) {
option = option || { level: ReportType.Info, notify: false } as ReportOption;
const level = option.level || ReportType.Info;
const notify = option.notify || false;
if (reportInWindows) {
this.showInWindows('' + message, type);
if (!this.skipMessage(level) && message) {
const currentTime = this.getCurrentTime();
this._output.appendLine('[' + level + ' - ' + currentTime + '] ' + message);
if (notify) {
this.showInWindows('' + message, level);
}
}
}

View File

@ -233,6 +233,7 @@ class PrjInfo implements PrjInfoMeta {
const psname = this.prjName.PS;
// TODO : packaging the replacer
// TODO : 支持路径的正则表达式
return path.replace(/\$\{workspace\}/g, workspacePath)
.replace(/\$\{plname\}/g, plname)
.replace(/\$\{psname\}/g, psname);
@ -593,6 +594,11 @@ class PrjInfo implements PrjInfoMeta {
return libPath;
}
/**
* @description arch.hardware.sim
* user/sim
* workspace path
*/
public get hardwareSimPath(): AbsPath {
const simPath = this._arch.hardware.sim;
const workspace = this._workspacePath;
@ -604,6 +610,11 @@ class PrjInfo implements PrjInfoMeta {
return hdlPath.join(workspace, simPath);
}
/**
* @description arch.hardware.src
* user/src
* workspace path
*/
public get hardwareSrcPath(): AbsPath {
const srcPath = this._arch.hardware.src;
const workspace = this._workspacePath;
@ -617,6 +628,30 @@ class PrjInfo implements PrjInfoMeta {
return hdlPath.join(workspace, srcPath);
}
/**
* @description user/ip
*/
public get ipPath(): AbsPath {
const workspace = this._workspacePath;
return hdlPath.join(workspace, 'user', 'ip');
}
/**
* @description user/src/lib
*/
public get localLibPath(): AbsPath {
const workspace = this._workspacePath;
return hdlPath.join(workspace, 'user', 'src', 'lib');
}
/**
* @description ${extensionPath}/library
*/
public get remoteLibPath(): AbsPath {
const extensionPath = this._extensionPath;
return hdlPath.join(extensionPath, 'library');
}
public json(): RawPrjInfo {
return {
toolChain: this._toolChain,

View File

@ -5,7 +5,7 @@ import { AbsPath, RelPath } from '../global';
import { HdlLangID } from '../global/enum';
import { verilogExts, vhdlExts, systemVerilogExts, hdlExts } from '../global/lang';
import * as hdlPath from './path';
import { HdlFileType } from '../hdlParser/common';
import { HdlFileProjectType } from '../hdlParser/common';
import { opeParam } from '../global';
/**
@ -139,24 +139,6 @@ function getLanguageId(path: AbsPath | RelPath): HdlLangID {
}
function getHdlFileType(path: AbsPath) : HdlFileType {
const uniformPath = hdlPath.toSlash(path);
const arch = opeParam.prjInfo.arch;
const srcPath: AbsPath = arch.hardware.src;
const simPath: AbsPath = arch.hardware.sim;
const wsPath: AbsPath = opeParam.workspacePath;
if (uniformPath.includes(srcPath)) {
return HdlFileType.Src;
} else if (uniformPath.includes(simPath)) {
return HdlFileType.Sim;
} else if (uniformPath.includes(wsPath)) {
return HdlFileType.LocalLib;
} else {
return HdlFileType.RemoteLib;
}
}
function readFile(path: AbsPath): string | undefined {
try {
const content = fs.readFileSync(path, 'utf-8');
@ -376,7 +358,6 @@ export {
readJSON,
writeJSON,
rmSync,
getHdlFileType,
pickFileRecursive,
isHasAttr,
isHasValue,

View File

@ -32,11 +32,23 @@ enum HdlModulePortType {
enum HdlModuleParamType {LocalParam, Parameter, Unknown};
enum HdlFileType {
/**
* @description HDL
* - Src: src
* - Sim: sim
* - LocalLib: 局部库文件
* - RemoteLib: 全局库文件
* - IP: IP
* - Primitive: 原语
*/
enum HdlFileProjectType {
Src = 'src',
Sim = 'sim',
LocalLib = 'local_lib',
RemoteLib = 'remote_lib'
RemoteLib = 'remote_lib',
IP = 'ip',
Primitive = 'primitive',
Unknown = 'unknown'
};
enum InstModPathStatus {Current, Include, Others, Unknown};
@ -214,7 +226,7 @@ export {
InstRange,
HdlModulePortType,
HdlModuleParamType,
HdlFileType,
HdlFileProjectType,
InstModPathStatus,
Error,
Define,

View File

@ -58,7 +58,9 @@ class HdlParam {
await this.doHdlFast(path, 'common');
const hdlFile = this.getHdlFile(path);
if (!hdlFile) {
MainOutput.report('error happen when we attempt to add file by path: ' + path, ReportType.Error);
MainOutput.report('error happen when we attempt to add file by path: ' + path, {
level: ReportType.Error
});
} else {
hdlFile.makeInstance();
// when a new file is added, retry the solution of dependency
@ -134,11 +136,11 @@ class HdlParam {
}
public selectTopModuleSourceByFileType(hdlModule: HdlModule): Set<HdlModule> {
switch (hdlModule.file.type) {
case common.HdlFileType.Src: return this.srcTopModules;
case common.HdlFileType.Sim: return this.simTopModules;
case common.HdlFileType.LocalLib: return this.srcTopModules;
case common.HdlFileType.RemoteLib: return this.srcTopModules;
switch (hdlModule.file.projectType) {
case common.HdlFileProjectType.Src: return this.srcTopModules;
case common.HdlFileProjectType.Sim: return this.simTopModules;
case common.HdlFileProjectType.LocalLib: return this.srcTopModules;
case common.HdlFileProjectType.RemoteLib: return this.srcTopModules;
default: return this.srcTopModules;
}
}
@ -152,6 +154,10 @@ class HdlParam {
topModuleSource.add(hdlModule);
}
/**
* @description module src sim topmodules
* @param hdlModule
*/
public deleteTopModuleToSource(hdlModule: HdlModule) {
const topModuleSource = this.selectTopModuleSourceByFileType(hdlModule);
topModuleSource.delete(hdlModule);
@ -238,15 +244,21 @@ class HdlParam {
const fast = await HdlSymbol.fast(path, fileType);
if (fast) {
const languageId = this.getRealLanguageId(path, fast.fileType);
const fileProjectType = this.getHdlFileProjectType(path, fast.fileType);
new HdlFile(path,
languageId,
fast.macro,
fast.content,
fileProjectType,
fast.fileType);
}
} catch (error) {
MainOutput.report('Error happen when parse ' + path, ReportType.Error);
MainOutput.report('Reason: ' + error, ReportType.Error);
MainOutput.report('Error happen when parse ' + path, {
level: ReportType.Error
});
MainOutput.report('Reason: ' + error, {
level: ReportType.Error
});
}
}
@ -257,6 +269,32 @@ class HdlParam {
return hdlFile.getLanguageId(path);
}
public getHdlFileProjectType(path: string, fileType: DoFastFileType): common.HdlFileProjectType {
switch (fileType) {
case 'common':
// 根据前缀来判断对应的类型
path = hdlPath.toSlash(path);
const prjInfo = opeParam.prjInfo;
if (path.startsWith(prjInfo.hardwareSrcPath)) {
return common.HdlFileProjectType.Src;
} else if (path.startsWith(prjInfo.hardwareSimPath)) {
return common.HdlFileProjectType.Sim;
} else if (path.startsWith(prjInfo.ipPath)) {
return common.HdlFileProjectType.IP;
} else if (path.startsWith(prjInfo.localLibPath)) {
return common.HdlFileProjectType.LocalLib;
} else if (path.startsWith(prjInfo.remoteLibPath)) {
return common.HdlFileProjectType.RemoteLib;
} else {
return common.HdlFileProjectType.Unknown;
}
case 'ip':
return common.HdlFileProjectType.IP;
case 'primitives':
return common.HdlFileProjectType.Primitive;
}
}
public async initializeHdlFiles(hdlFiles: AbsPath[], progress: vscode.Progress<IProgress>) {
let count: number = 0;
@ -343,8 +381,8 @@ class HdlParam {
}
switch (type) {
case common.HdlFileType.Src: return this.getSrcTopModules();
case common.HdlFileType.Sim: return this.getSimTopModules();
case common.HdlFileProjectType.Src: return this.getSrcTopModules();
case common.HdlFileProjectType.Sim: return this.getSimTopModules();
default: return [];
}
}
@ -399,7 +437,9 @@ class HdlParam {
// 初始化
const moduleFile = this.getHdlFile(path);
if (!moduleFile) {
MainOutput.report('error happen when create moduleFile ' + path, ReportType.Warn);
MainOutput.report('error happen when create moduleFile ' + path, {
level: ReportType.Warn
});
} else {
moduleFile.makeInstance();
for (const module of moduleFile.getAllHdlModules()) {
@ -481,19 +521,25 @@ class HdlInstance {
this.locateHdlModule();
}
/**
* @description instance HdlModule HDLIP this.module
* HdlModule HDL & IP HdlModule ref
*/
public locateHdlModule() {
const instModPath = this.instModPath;
const instModName = this.type;
if (instModPath) {
this.module = hdlParam.getHdlModule(instModPath, instModName);
// add refer for module
this.module?.addGlobalReferedInstance(this);
// if module and parent module share the same source (e.g both in src folder)
if (this.isSameSourceInstantiation()) {
// 增加当前 instance 的引用,并从对应类型的顶层模块中剔除
this.module?.addLocalReferedInstance(this);
const module = hdlParam.getHdlModule(instModPath, instModName);
if (module) {
this.module = module;
// 增加当前模块的 global ref
this.module.addGlobalReferedInstance(this);
// 如果当前 instance 对应的例化是同源例化,则
// 增加当前 instance 的 local ref并从对应类型的顶层模块中剔除
if (this.isSameSourceInstantiation()) {
this.module?.addLocalReferedInstance(this);
}
}
} else {
doPrimitivesJudgeApi(instModName).then(isPrimitive => {
@ -503,6 +549,9 @@ class HdlInstance {
const fakeModule = new HdlModule(
XilinxPrimitivesHdlFile, instModName, defaultRange, [], [], []);
this.module = fakeModule;
// 原语在任何情况下都不是顶层模块
hdlParam.deleteTopModule(fakeModule);
hdlParam.deleteTopModuleToSource(fakeModule);
}
}
});
@ -513,24 +562,37 @@ class HdlInstance {
/**
* @description `instance` (SSI, same source instantiation)
*
* src + sim moduleA moduleB moduleA moduleB src
* - src + sim moduleA moduleB moduleA moduleB src
* moduleB sim moduleA src
*
* local ref + global ref src local ref module
* - library IP module
* - local ref + global ref src local ref module
*
* @returns
*/
public isSameSourceInstantiation(): boolean {
const parentMod = this.parentMod;
const instMod = this.module;
if (instMod) {
return parentMod.file.type === instMod.file.type;
const parentModule = this.parentMod;
const belongModule = this.module;
// 当前 instance 仍然是 unsolved 状态,返回 false 不参与后续的 ref 计算
if (!belongModule) {
return false;
}
return false;
// instance 模块本身是 library / IP / 原语,一律视为 SSI
if (belongModule.file.projectType === common.HdlFileProjectType.IP ||
belongModule.file.projectType === common.HdlFileProjectType.Primitive ||
belongModule.file.projectType === common.HdlFileProjectType.LocalLib ||
belongModule.file.projectType === common.HdlFileProjectType.RemoteLib
) {
return true;
}
// 剩余情况下,一律根据 type 判断
return parentModule.file.projectType === belongModule.file.projectType;
}
/**
* @description update Instance of each time
* @description instance
* @param newInstance
*/
public update(newInstance: common.RawHdlInstance) {
@ -685,8 +747,9 @@ class HdlModule {
}
// this.rawInstances = undefined;
} else {
MainOutput.report('call makeNameToInstances but this.rawInstances is undefined',
ReportType.Warn);
MainOutput.report('call makeNameToInstances but this.rawInstances is undefined', {
level: ReportType.Warn
});
}
}
@ -885,23 +948,30 @@ class HdlModule {
};
export class HdlFile {
// 标准化的文件绝对路径
public path: string;
// 对应的 HDL 语言 ID
public languageId: HdlLangID;
public type: common.HdlFileType;
// 文件的项目类型
public projectType: common.HdlFileProjectType;
// 文件的解析模式
public doFastType: DoFastFileType;
// 当前文件的宏
public macro: common.Macro;
// 维护当前文件内部 module 的 map
private readonly nameToModule: Map<string, HdlModule>;
constructor(path: string,
languageId: HdlLangID,
macro: common.Macro,
modules: common.RawHdlModule[],
projectType: common.HdlFileProjectType,
doFastType: DoFastFileType) {
this.path = path;
this.languageId = languageId;
this.macro = macro;
this.type = hdlFile.getHdlFileType(path);
this.projectType = projectType;
this.doFastType = doFastType;
// add to global hdlParam
@ -987,8 +1057,13 @@ export class HdlFile {
}
}
export const XilinxPrimitivesHdlFile = new HdlFile('xilinx-primitives', HdlLangID.Verilog, defaultMacro, [], 'primitives');
export const XilinxPrimitivesHdlFile = new HdlFile(
'xilinx-primitives',
HdlLangID.Verilog,
defaultMacro,
[],
common.HdlFileProjectType.Primitive,
'primitives');
export {

View File

@ -10,7 +10,7 @@ import { opeParam } from '../../global';
import { ToolChainType } from '../../global/enum';
import { hdlFile, hdlPath } from '../../hdlFs';
import { moduleTreeProvider, ModuleDataItem } from '../../function/treeView/tree';
import { HdlFileType } from '../../hdlParser/common';
import { HdlFileProjectType } from '../../hdlParser/common';
import { PropertySchema } from '../../global/propertySchema';
import { HardwareOutput, ReportType } from '../../global/outputChannel';
import { t } from '../../i18n';
@ -31,15 +31,7 @@ class PlManage extends BaseManage {
const curToolChain = this.context.tool;
if (curToolChain === ToolChainType.Xilinx) {
const vivadoPath = vscode.workspace.getConfiguration('digital-ide.prj.vivado.install').get('path', '');
if (hdlFile.isDir(vivadoPath)) {
this.context.path = hdlPath.join(hdlPath.toSlash(vivadoPath), 'vivado');
if (opeParam.os === 'win32') {
this.context.path += '.bat';
}
} else {
this.context.path = 'vivado';
}
this.context.path = this.context.ope.updateVivadoPath();
}
}
@ -104,7 +96,7 @@ class PlManage extends BaseManage {
HardwareOutput.show();
this.context.process.stdin.write('exit\n');
HardwareOutput.report(t('info.pl.exit.title'), ReportType.Info);
HardwareOutput.report(t('info.pl.exit.title'));
this.context.process = undefined;
}
@ -112,8 +104,8 @@ class PlManage extends BaseManage {
public setSrcTop(item: ModuleDataItem) {
this.context.ope.setSrcTop(item.name, this.context);
const type = moduleTreeProvider.getItemType(item);
if (type === HdlFileType.Src) {
moduleTreeProvider.setFirstTop(HdlFileType.Src, item.name, item.path);
if (type === HdlFileProjectType.Src) {
moduleTreeProvider.setFirstTop(HdlFileProjectType.Src, item.name, item.path);
moduleTreeProvider.refreshSrc();
}
}
@ -121,8 +113,8 @@ class PlManage extends BaseManage {
public setSimTop(item: ModuleDataItem) {
this.context.ope.setSimTop(item.name, this.context);
const type = moduleTreeProvider.getItemType(item);
if (type === HdlFileType.Sim) {
moduleTreeProvider.setFirstTop(HdlFileType.Sim, item.name, item.path);
if (type === HdlFileProjectType.Sim) {
moduleTreeProvider.setFirstTop(HdlFileProjectType.Sim, item.name, item.path);
moduleTreeProvider.refreshSim();
}
}

View File

@ -13,6 +13,7 @@ import { XilinxIP } from '../../global/enum';
import { HardwareOutput, MainOutput, ReportType } from '../../global/outputChannel';
import { debounce } from '../../global/util';
import { t } from '../../i18n';
import { HdlFileProjectType } from '../../hdlParser/common';
interface XilinxCustom {
ipRepo: AbsPath,
@ -172,15 +173,15 @@ class XilinxOperation {
}
const tclPath = hdlPath.join(this.xilinxPath, 'launch.tcl');
scripts.push(this.getRefreshCmd());
scripts.push(this.getRefreshXprDesignSourceCommand());
scripts.push(`file delete ${tclPath} -force`);
const tclCommands = scripts.join('\n') + '\n';
hdlFile.writeFile(tclPath, tclCommands);
const argu = `-notrace -nolog -nojournal`;
context.path = this.updateVivadoPath();
const cmd = `${context.path} -mode tcl -s ${tclPath} ${argu}`;
const _this = this;
const onVivadoClose = debounce(() => {
@ -193,6 +194,7 @@ class XilinxOperation {
}
// 执行 cmd 启动
const vivadoProcess = spawn(cmd, [], { shell: true, stdio: 'pipe', cwd: opeParam.workspacePath });
let status: 'pending' | 'fulfilled' = 'pending';
vivadoProcess.on('close', () => {
onVivadoClose();
@ -204,13 +206,6 @@ class XilinxOperation {
onVivadoClose();
});
vivadoProcess.stderr.on('data', data => {
HardwareOutput.report(data.toString(), ReportType.Error);
HardwareOutput.show();
});
let status: 'pending' | 'fulfilled' = 'pending';
return new Promise(resolve => {
vivadoProcess.stdout.on('data', data => {
const message: string = _this.handleMessage(data.toString(), status);
@ -219,15 +214,42 @@ class XilinxOperation {
HardwareOutput.show();
resolve(vivadoProcess);
}
HardwareOutput.report(message, ReportType.Info);
HardwareOutput.report(message, {
level: ReportType.Info
});
status = 'fulfilled';
});
vivadoProcess.stderr.on('data', async data => {
HardwareOutput.report(data.toString(), {
level: ReportType.Error
});
HardwareOutput.show();
if (status === 'pending') {
// pending 阶段就出现 stderr 说明启动失败
resolve(undefined);
const vivadoInstallPath = vscode.workspace.getConfiguration('digital-ide').get<string>('prj.vivado.install.path') || '';
const res = await vscode.window.showErrorMessage(
t('error.pl.launch.not-valid-vivado-path', data.toString(), vivadoInstallPath.toString()),
{
title: t('info.pl.launch.set-vivado-path'),
value: true
}
);
if (res?.value) {
await vscode.commands.executeCommand('workbench.action.openSettings', 'digital-ide.prj.vivado.install.path');
}
}
});
});
}
const process = await vscode.window.withProgress({
title: t('info.pl.launch.progress.launch-tcl.title'),
location: vscode.ProgressLocation.Notification
location: vscode.ProgressLocation.Notification,
cancellable: true
}, async () => {
return await launchScript();
});
@ -280,7 +302,11 @@ class XilinxOperation {
scripts.push(`open_project ${path} -quiet`);
}
private getRefreshCmd(): string {
/**
* @description xpr
* @returns
*/
private getRefreshXprDesignSourceCommand(): string {
const scripts: string[] = [];
// 清除所有源文件
scripts.push(`remove_files -quiet [get_files]`);
@ -358,13 +384,25 @@ class XilinxOperation {
});
// 导入非本地的设计源文件
const HDLFiles = hdlParam.getAllHdlFiles();
for (const file of HDLFiles) {
// TODO: 新增library的add_files
if (file.type === "src") {
scripts.push(`add_files ${file.path} -quiet`);
for (const hdlFile of hdlParam.getAllHdlFiles()) {
switch (hdlFile.projectType) {
case HdlFileProjectType.Src:
case HdlFileProjectType.LocalLib:
case HdlFileProjectType.RemoteLib:
// src 和 library 加入 source_1 设计源
scripts.push(`add_file ${hdlFile.path} -quiet`);
break;
case HdlFileProjectType.Sim:
// sim 加入 sim_1 设计源
scripts.push(`add_file -fileset sim_1 ${hdlFile.path} -quiet`);
break;
case HdlFileProjectType.IP:
case HdlFileProjectType.Primitive:
// IP 和 原语不用管
break;
default:
break;
}
scripts.push(`add_files -fileset sim_1 ${file.path} -quiet`);
}
scripts.push(`add_files -fileset constrs_1 ${this.datPath} -quiet`);
@ -389,8 +427,12 @@ class XilinxOperation {
return cmd;
}
/**
* @description Xilinx Vivado xpr
* @param context
*/
public refresh(context: PLContext) {
const cmd = this.getRefreshCmd();
const cmd = this.getRefreshXprDesignSourceCommand();
context.process?.stdin.write(cmd + '\n');
}
@ -590,7 +632,9 @@ file delete ${scriptPath} -force\n`;
if (context.process) {
context.process.stdin.write('start_gui -quiet\n');
HardwareOutput.report(t('info.pl.gui.report-title'), ReportType.Info);
HardwareOutput.report(t('info.pl.gui.report-title'), {
level: ReportType.Info
});
HardwareOutput.show();
this.guiLaunched = true;
}
@ -600,7 +644,7 @@ file delete ${scriptPath} -force\n`;
if (!this.guiLaunched && files.length > 0) {
const filesString = files.join("\n");
HardwareOutput.report(t('info.pl.add-files.title') + '\n' + filesString);
this.processFileInPrj(files, context, "add_file");
this.execCommandToFilesInTclInterpreter(files, context, "add_file");
}
}
@ -608,7 +652,7 @@ file delete ${scriptPath} -force\n`;
if (!this.guiLaunched && files.length > 0) {
const filesString = files.join("\n");
HardwareOutput.report(t('info.pl.del-files.title') + '\n' + filesString);
this.processFileInPrj(files, context, "remove_files");
this.execCommandToFilesInTclInterpreter(files, context, "remove_files");
}
}
@ -638,7 +682,7 @@ file delete ${scriptPath} -force\n`;
* @param context
* @param command
*/
public processFileInPrj(files: string[], context: PLContext, command: string) {
public execCommandToFilesInTclInterpreter(files: string[], context: PLContext, command: string) {
if (context.process === undefined) {
return;
}
@ -681,6 +725,20 @@ file delete ${scriptPath} -force\n`;
MainOutput.report(log);
}
public updateVivadoPath(): string {
const vivadoBinFolder = vscode.workspace.getConfiguration('digital-ide.prj.vivado.install').get<string>('path') || '';
if (hdlFile.isDir(vivadoBinFolder)) {
let vivadoPath = hdlPath.join(hdlPath.toSlash(vivadoBinFolder), 'vivado');
if (opeParam.os === 'win32') {
vivadoPath += '.bat';
}
return vivadoPath;
} else {
// 没有设置 vivado bin 文件夹,就认为用户已经把对应的路径加入环境变量了
return 'vivado';
}
}
}
class XilinxBd {

View File

@ -13,7 +13,9 @@ function registerManagerCommands(context: vscode.ExtensionContext) {
// const psManage = prjManage.ps;
vscode.commands.registerCommand('digital-ide.property-json.generate', prjManage.generatePropertyJson);
vscode.commands.registerCommand('digital-ide.property-json.overwrite', prjManage.overwritePropertyJson);
// 丢弃原因:插件更新后,用户修改的部分会被覆盖,没有存在必要了
// vscode.commands.registerCommand('digital-ide.property-json.overwrite', prjManage.overwritePropertyJson);
// libpick
vscode.commands.registerCommand('digital-ide.pickLibrary', pickLibrary);

View File

@ -33,7 +33,9 @@ abstract class BaseAction {
public listenChange(m: HdlMonitor) {
const fSWatcher = this.selectFSWatcher(m);
if (!fSWatcher) {
MainOutput.report("FSWatcher hasn't been made!", ReportType.Error);
MainOutput.report("FSWatcher hasn't been made!", {
level: ReportType.Error
});
return;
}
fSWatcher.on(Event.Change, path => this.change(path, m));
@ -42,7 +44,9 @@ abstract class BaseAction {
public listenAdd(m: HdlMonitor) {
const fSWatcher = this.selectFSWatcher(m);
if (!fSWatcher) {
MainOutput.report("FSWatcher hasn't been made!", ReportType.Error);
MainOutput.report("FSWatcher hasn't been made!", {
level: ReportType.Error
});
return;
}
fSWatcher.on(Event.Add, path => this.add(path, m));
@ -51,7 +55,9 @@ abstract class BaseAction {
public listenUnlink(m: HdlMonitor) {
const fSWatcher = this.selectFSWatcher(m);
if (!fSWatcher) {
MainOutput.report("FSWatcher hasn't been made!", ReportType.Error);
MainOutput.report("FSWatcher hasn't been made!", {
level: ReportType.Error
});
return;
}
fSWatcher.on(Event.Unlink, path => this.unlink(path, m));
@ -75,7 +81,9 @@ class HdlAction extends BaseAction {
// check if it has been created
if (hdlParam.hasHdlFile(path)) {
MainOutput.report('<HdlAction Add Event> HdlFile ' + path + ' has been created', ReportType.Warn);
MainOutput.report('<HdlAction Add Event> HdlFile ' + path + ' has been created', {
level: ReportType.Warn
});
return;
}
@ -247,7 +255,9 @@ class PpyAction extends BaseAction {
// skip hdl remake
if (originalLibState !== currentLibState) {
const fileChange = await libManage.processLibFiles(opeParam.prjInfo.library);
MainOutput.report(`libManage finish process, add ${fileChange.add.length} files, del ${fileChange.del.length} files`, ReportType.Info);
MainOutput.report(`libManage finish process, add ${fileChange.add.length} files, del ${fileChange.del.length} files`, {
level: ReportType.Info
});
}
} else {
// update hdl monitor
@ -308,8 +318,6 @@ class PpyAction extends BaseAction {
for (const path of delFiles) {
hdlParam.deleteHdlFile(path);
}
// 判断新加入的 module 是否还是顶层模块
}
@ -320,7 +328,9 @@ class PpyAction extends BaseAction {
const delfileActionTag = '(del files) ';
if (addFiles.length > 0) {
const reportMsg = ['', ...addFiles].join('\n\t');
MainOutput.report(addfileActionTag + t('info.pl.xilinx.update-addfiles') + reportMsg, ReportType.Run);
MainOutput.report(addfileActionTag + t('info.pl.xilinx.update-addfiles') + reportMsg, {
level: ReportType.Run
});
await prjManage.pl.addFiles(addFiles);
} else {
MainOutput.report(addfileActionTag + t('info.pl.xilinx.no-need-add-files'));
@ -328,14 +338,18 @@ class PpyAction extends BaseAction {
if (delFiles.length > 0) {
const reportMsg = ['', ...delFiles].join('\n\t');
MainOutput.report(delfileActionTag + t('info.pl.xilinx.update-delfiles') + reportMsg, ReportType.Run);
MainOutput.report(delfileActionTag + t('info.pl.xilinx.update-delfiles') + reportMsg, {
level: ReportType.Run
});
await prjManage.pl.delFiles(delFiles);
} else {
MainOutput.report(delfileActionTag + t('info.pl.xilinx.no-need-del-files'));
}
} else {
MainOutput.report('PL is not registered', ReportType.Warn);
MainOutput.report('PL is not registered', {
level: ReportType.Warn
});
}
}
}