精华内容
下载资源
问答
  • 在没有FTP工具情况下,我们如何让电脑自动下载和上传文件到FTP服务器呢?这里给出一个例子,以方便大家紧急情况下使用。由于Windows下FTP命令包含了执行脚本的功能,我们可以事先将要进行的工作,以FTP命令子...

    在没有FTP工具的情况下,我们如何让电脑自动下载和上传文件到FTP服务器呢?这里给出一个例子,以方便大家紧急情况下使用。

    由于Windows下的FTP命令包含了执行脚本的功能,我们可以事先将要进行的工作,以FTP命令的子命令方式写入一个脚本文件中。然后让使用FTP自动执行该脚本即可达到预期效果。当然前提是你要会用FTP的子命令。下面我就举个例子。大家套用即可。

    首先,我们要将需要准备一个任务清单。包括从登陆FTP服务器,完成各项工作,到最后退出FTP服务器的全部命令。并将其保存为一个文本文件。例如:

    TaskList.txt
    -----------------------------------------------------------------------------------------
    user    loginname    password
    cd    /
    get    file1.dat    d:/download/file1.dat
    get    file2.dat   d:/download/file2.dat
    ......
    send   d:/newfile1.dat
    send   d:/newfile2.dat
    ......
    quit

    然后,我们在dos命令窗口下输入如下命令即可。也可以将这个命令保存在一个自动批处理文件中。使用Windows计划任务让电脑在指定的时间自动完成该任务。例如:

    Auto.bat
    -----------------------------------------------------------------------------------------
    ftp    -n    -v    -s:c:/TaskList.txt    ftpServerAddress

    展开全文
  • 简介能让电脑完成的就不要手写了,自动生成寄存器模块verilog代码的脚本设计过程不知道大家是否向我一样,需要快速的实现模块。我大部分写的都是算法模块,而且算法每次修改都特别大,除了控制部分可以复用以外其他...

    简介

    能让电脑完成的就不要手写了,自动生成寄存器模块verilog代码的脚本设计过程

    不知道大家是否向我一样,需要快速的实现模块。

    我大部分写的都是算法模块,而且算法每次修改都特别大,除了控制部分可以复用以外其他都需要重新设计。

    但是有些模块还是有写规律可循的,比如寄存器部分。

    不管算法如何改变寄存器的配置方式可以说都是差不多的,那就可以让电脑代替我来完成这部分工作了。

    脚本功能

    直接生成寄存器模块的verilog文件

    配置接口采用apb接口,32bit数据和16bit地址

    支持 RW、RO 类型的寄存器

    支持地址自动分配

    支持地址和bit位粘连检查

    基础知识

    python

    verilog

    python现在主要有两个大版本2.x 和 3.x ,linux 现在大部分默认还是python2,所以下面所有的都以python2为基础

    python 2.x 和 3.x 有些许不同,请大家注意

    建议使用2.7和3.4及其以上版本

    代码格式

    先定义下最后生成的代码风格(我就以我平时喜欢的风格来设计了)

    代码中有下面两类寄存器

    1.可读可写的寄存器:base,test

    2.只读寄存器:dbg

    module Mbase_reg_cfg

    (

    // clk / rst_n

    input i_clk

    ,input i_rst_n

    // apb port

    ,input i_psel

    ,input [15:0] i_paddr

    ,input i_penable

    ,input i_pwrite

    ,input [31:0] i_pwdata

    ,output [31:0] o_prdata

    // output port

    ,output o_sw_base_0

    ,output [3:0] o_sw_base_1

    ,output [3:0] o_sw_tt_dbg_1

    ,output o_sw_tt_dbg_0

    // input port

    ,input [3:0] i_ro_dbg_1

    ,input [6:0] i_ro_dbg_0

    );

    //==========================================================

    // apb bus ctrl start/*{{{*/

    //==========================================================

    wire wr ;

    wire rd ;

    wire [15:0] addr ;

    wire [31:0] wdata ;

    reg [31:0] rdata ;

    assign wr = i_psel & i_penable & i_pwrite ;

    assign rd = i_psel & ~i_penable & ~i_pwrite ;

    assign addr = i_paddr ;

    assign wdata = i_pwdata ;

    assign o_prdata = rdata ;

    //==========================================================

    // apb bus ctrl end/*}}}*/

    //==========================================================

    //==========================================================

    // localparam start/*{{{*/

    //==========================================================

    localparam BASE_ADDR = 16'h0000 ;

    localparam DBG_ADDR = 16'h0004 ;

    localparam TEST_ADDR = 16'h0008 ;

    //==========================================================

    // localparam end/*}}}*/

    //==========================================================

    //==========================================================

    // reg and wire start/*{{{*/

    //==========================================================

    // write signal

    wire wr_base_w ;

    wire wr_test_w ;

    // reg

    reg [31:0] reg_base_r ;

    reg [31:0] reg_test_r ;

    // read data

    wire [31:0] rdata_base_w ;

    wire [31:0] rdata_dbg_w ;

    wire [31:0] rdata_test_w ;

    //==========================================================

    // reg and wire end/*}}}*/

    //==========================================================

    //==========================================================

    // write signal gen start/*{{{*/

    //==========================================================

    assign wr_base_w = wr & (addr == BASE_ADDR );

    assign wr_test_w = wr & (addr == TEST_ADDR );

    //==========================================================

    // write signal gen end/*}}}*/

    //==========================================================

    //==========================================================

    // base start/*{{{*/

    //==========================================================

    localparam BASE_VALID_BIT = 32'h00_00_00_f1;

    localparam BASE_DEFAULT = 32'h00_00_00_f1;

    always@(posedge i_clk) begin

    if(i_rst_n == 1'd0) begin

    reg_base_r <= BASE_DEFAULT;

    end

    else if(wr_base_w) begin

    reg_base_r <= wdata & BASE_VALID_BIT;

    end

    end

    assign o_sw_base_0 = reg_base_r[0];

    assign o_sw_base_1 = reg_base_r[7:4];

    assign rdata_base_w = {

    24'd0

    ,o_sw_base_1

    ,3'd0

    ,o_sw_base_0

    };

    //==========================================================

    // base end/*}}}*/

    //==========================================================

    //==========================================================

    // dbg start/*{{{*/

    //==========================================================

    assign rdata_dbg_w = {

    14'd0

    ,i_ro_dbg_0

    ,3'd0

    ,i_ro_dbg_1

    ,4'd0

    };

    //==========================================================

    // dbg end/*}}}*/

    //==========================================================

    //==========================================================

    // test start/*{{{*/

    //==========================================================

    localparam TEST_VALID_BIT = 32'h80_00_00_f0;

    localparam TEST_DEFAULT = 32'h00_00_00_00;

    always@(posedge i_clk) begin

    if(i_rst_n == 1'd0) begin

    reg_test_r <= TEST_DEFAULT;

    end

    else if(wr_test_w) begin

    reg_test_r <= wdata & TEST_VALID_BIT;

    end

    end

    assign o_sw_tt_dbg_1 = reg_test_r[7:4];

    assign o_sw_tt_dbg_0 = reg_test_r[31];

    assign rdata_test_w = {

    o_sw_tt_dbg_0

    ,23'd0

    ,o_sw_tt_dbg_1

    ,4'd0

    };

    //==========================================================

    // test end/*}}}*/

    //==========================================================

    //==========================================================

    // rdata start/*{{{*/

    //==========================================================

    always@(posedge i_clk) begin

    if(i_rst_n == 1'd0) begin

    rdata <= 32'd0;

    end

    else if(rd) begin

    case(addr)

    BASE_ADDR : rdata <= rdata_base_w ;

    DBG_ADDR : rdata <= rdata_dbg_w ;

    TEST_ADDR : rdata <= rdata_test_w ;

    default : rdata <= 32'd0 ;

    endcase

    end

    else begin

    rdata <= rdata;

    end

    end

    //==========================================================

    // rdata end/*}}}*/

    //==========================================================

    endmodule

    生成用列表文件内容

    产生寄存器文件需要知道有那些寄存器和如何拼接

    下面为产生上面寄存器文件所使用的列表文件格式

    生成模块名M_reg_cfg

    列表文件名_reg_list

    列表列表名_reg_list

    如果列表文件和列表名不一致或是不匹配会出现问题

    base_reg_list = [

    {

    "name" : "base",

    "addr" : 0x0000,

    "type" : "RW", # "RW" or "RO"

    "bit" : [

    ["base_0", [0], 0x1], # [寄存器名称, 使用bit位, 默认值]

    ["base_1", [7,4], 0xf], # [寄存器名称, 使用bit位, 默认值]

    ]

    },

    {

    "name" : "dbg",

    # "addr" : 0x0004, # 地址可以不显示指定,默认自增

    "type" : "RO",

    "bit" : [

    ["dbg_1", [7,4]],

    ["dbg_0", [17,11], 0x0], # 只读寄存器默认值不起作用

    ]

    },

    {

    "name" : "test",

    "addr" : 0x0008,

    # "type" : "RW", # 类型可以不显示指定,默认 "RW"

    "bit" : [

    ["tt_dbg_1", [7,4]], # 默认值可以不显示指定,默认 "0"

    ["tt_dbg_0", [31], 0x0],

    ]

    },

    ]

    脚本处理步骤

    1.读取寄存器列表

    2.对没有制定默认值的地方进行添加,没有地址的使用前面进行累加

    3.检查地址、bit位有无粘连

    4.产生输入输出端口

    5.产生localparam 地址内容

    6.产生后续会使用到的信号定义

    7.产生寄存器写使能逻辑

    8.产生每个寄存器的写过程和输出信号拆分和读取信号合并内容

    9.产生寄存器读逻辑

    10.合并上述内容进行输出

    脚本设计过程问题与关键点

    1.读取寄存器列表

    主要读取配置文件并生成脚本识别格式

    为了省事,就不对寄存器列表进行语法解析,而是使用python的exec函数

    exec : 执行字符串中的python语句

    def get_reg_list(file_name):

    with open(file_name, "r") as f:

    data_str = f.readlines()

    data_str = "".join(data_str)

    _locals = locals()

    exec(data_str, globals(), _locals)

    data = _locals[file_name]

    return data

    上面主要步骤

    打开文件并读取全部内容,将文件列表拼接为一个大的字符串

    执行字符串中内容,将字符串中的寄存器列表返回

    2.对没有制定默认值的地方进行添加,没有地址的使用前面进行累加

    为了后面代码不会每次还判读时候有指定,没有指定用默认值。

    所以在给到后面处理时将没有显示指定的地方添加上默认值,简化后面代码处理

    前面定义了地址默认自增,类型默认只读,默认值为0.

    下面代码有相应的操作

    def add_default(data):

    def_addr = 0x0000

    def_type = "RW"

    def_value = 0x0

    for reg in data:

    # add default addr

    try:

    def_addr = reg["addr"] + 4

    except:

    reg["addr"] = def_addr

    def_addr = reg["addr"] + 4

    # add default type

    try:

    reg["type"]

    except:

    reg["type"] = def_type

    for bit in reg["bit"]:

    # add default range

    if len(bit[1]) == 1:

    bit[1] = [bit[1][0],bit[1][0]]

    # add default value

    try:

    bit[2]

    except:

    bit.append(def_value)

    上面代码中这两行不知道你有没有想到为什么这么做。

    if len(bit[1]) == 1:

    bit[1] = [bit[1][0],bit[1][0]]

    因为在寄存器只有一个bit的情况下,我们列表中只有一个值

    为了将多bit和单bit统一,所以将单bit转为和多bit相同的方式

    3.检查地址、bit位有无粘连

    在设计过程中我一直有一个观点:人是最不靠谱的

    在上面我们手动需要写的就是list文件

    因为是手写,没有办法保证100%正确,所以需要添加适当的检查机制,确保正确性

    常见的问题有几点:地址重叠、bit重叠、bit超出范围

    下面代码就是针对这几点进行的检查

    def check_overlap(data):

    err = 0

    # addr overlap check

    addr_list = []

    for reg in data:

    addr_list.append(reg["addr"])

    set_addr_list = list(set(addr_list))

    if len(addr_list) != len(set_addr_list):

    overlap_addr = [ addr for addr in set_addr_list if addr_list.count(addr) > 1]

    for addr in overlap_addr:

    print("Err : 0x%08x addr overlap !!!" % addr)

    err = 1

    # bit overlap check

    for reg in data:

    bit_list = []

    for bit in reg["bit"]:

    bit_start = bit[1][1]

    bit_end = bit[1][0]

    bit_list += range(bit_start,bit_end+1)

    set_bit_list = list(set(bit_list))

    if len([bit for bit in set_bit_list if bit >= 32]) > 0:

    print("Err : reg %s addr 0x%08x bit out range !!!" % (reg['name'], reg['addr']))

    err = 1

    if len(bit_list) != len(set_bit_list):

    overlap_bit = [ bit for bit in set_bit_list if bit_list.count(bit) > 1]

    print("Err : 0x%08x bit %s overlap !!!" % (reg['addr'], str(overlap_bit)))

    err = 1

    if err:

    sys.exit(1)

    4.产生输入输出端口

    接下来就该进入正式的verilog代码部分了

    首先我们先确定需要产生的部分(下面内容为上面代码格式部分)

    // output port

    ,output o_sw_base_0

    ,output [3:0] o_sw_base_1

    ,output [3:0] o_sw_tt_dbg_1

    ,output o_sw_tt_dbg_0

    // input port

    ,input [3:0] i_ro_dbg_1

    ,input [6:0] i_ro_dbg_0

    这部分是我们使用过程中需要的输入输出端口

    所有的模块我们都需要配置相应的寄存器来确定工作模式或是开关

    上面输出口就是通过总线配置后的值

    输入一般为运行后的输出,或是debug用的

    下面为详细的产生代码

    def gen_io_port(data):

    io_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    ro_list = [ reg for reg in data if reg['type'] == 'RO']

    # output port

    io_str.append(" // output port\n")

    for reg in rw_list:

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_len = bit_range[0] - bit_range[1]

    if bit_len != 0:

    range_str = "[%d:0]" % bit_len

    else:

    range_str = ""

    bit_name_str = "o_sw_%s" % bit[0]

    io_str.append(" ,output %-17s %s\n" % (range_str, bit_name_str,))

    io_str.append("\n");

    # input port

    io_str.append(" // input port\n")

    for reg in ro_list:

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_len = bit_range[0] - bit_range[1]

    if bit_len != 0:

    range_str = "[%d:0]" % bit_len

    else:

    range_str = ""

    bit_name_str = "i_ro_%s" % bit[0]

    io_str.append(" ,input %-17s %s\n" % (range_str, bit_name_str,))

    io_str.append("\n");

    return io_str

    5.产生localparam 地址内容

    接下来就改产生地址信息了,这里使用lcalparam定义地址,然后使用

    所以这里就只产生定义,具体使用在后面的写逻辑生成

    下面为需要产生的部分(下面内容为上面代码格式部分)

    localparam BASE_ADDR = 16'h0000 ;

    localparam DBG_ADDR = 16'h0004 ;

    localparam TEST_ADDR = 16'h0008 ;

    下面为产生代码。

    这里没有什么难点

    def gen_localparam(data):

    localparam_str = []

    for reg in data:

    addr_name = "%s_ADDR" % reg['name'].upper()

    addr_str = "16'h%04x" % reg['addr']

    localparam_str.append("localparam %-36s = %s ;\n" % (addr_name, addr_str,))

    return localparam_str

    6.产生后续会使用到的信号定义

    下面就是信号的定义部分

    这里主要定义了:写使能信号、寄存器信号、读数据信号

    // write signal

    wire wr_base_w ;

    wire wr_test_w ;

    // reg

    reg [31:0] reg_base_r ;

    reg [31:0] reg_test_r ;

    // read data

    wire [31:0] rdata_base_w ;

    wire [31:0] rdata_dbg_w ;

    wire [31:0] rdata_test_w ;

    写使能和寄存器信号都是"RW"的才有,而读数据信号是所有类型的都有

    主要是因为"RO"的不需要写,数据直接通过输入进来,只需要总线能读取即可

    下面为相应产生部分

    def gen_reg_wire(data):

    reg_wire_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    reg_wire_str.append("\n")

    # write signal

    reg_wire_str.append("// write signal\n")

    for reg in rw_list:

    wire_name = "wr_%s_w" % reg['name']

    reg_wire_str.append("wire %-47s;\n" % wire_name)

    reg_wire_str.append("\n")

    # reg

    reg_wire_str.append("// reg\n")

    for reg in rw_list:

    reg_name = "reg_%s_r" % reg['name']

    reg_wire_str.append("reg [31:0] %-47s;\n" % reg_name)

    reg_wire_str.append("\n")

    # read data

    reg_wire_str.append("// read data\n")

    for reg in data:

    wire_name = "rdata_%s_w" % reg['name']

    reg_wire_str.append("wire [31:0] %-47s;\n" % wire_name)

    reg_wire_str.append("\n")

    return reg_wire_str

    7.产生寄存器写使能逻辑

    接下来就是产生写使能逻辑

    assign wr_base_w = wr & (addr == BASE_ADDR );

    assign wr_test_w = wr & (addr == TEST_ADDR );

    这里只需要产生RW类型的写使能即可,RO不需要

    def gen_write_signal(data):

    write_signal_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    for reg in rw_list:

    wire_name = "wr_%s_w" % reg['name']

    addr_name = "%s_ADDR" % reg['name'].upper()

    write_signal_str.append("assign %-20s = wr & (addr == %-14s);\n" % (wire_name, addr_name,))

    return write_signal_str

    8.产生每个寄存器的写过程和输出信号拆分和读取信号合并内容

    接下来就是最主要的部分了

    寄存器的读写、输出连接、读拼接都是在这里做的

    下面为两类寄存器生成的最终生成内容(生成的注释中有vim识别的折叠,这是个人习惯)

    //==========================================================

    // base start/*{{{*/

    //==========================================================

    localparam BASE_VALID_BIT = 32'h00_00_00_f1;

    localparam BASE_DEFAULT = 32'h00_00_00_f1;

    always@(posedge i_clk) begin

    if(i_rst_n == 1'd0) begin

    reg_base_r <= BASE_DEFAULT;

    end

    else if(wr_base_w) begin

    reg_base_r <= wdata & BASE_VALID_BIT;

    end

    end

    assign o_sw_base_0 = reg_base_r[0];

    assign o_sw_base_1 = reg_base_r[7:4];

    assign rdata_base_w = {

    24'd0

    ,o_sw_base_1

    ,3'd0

    ,o_sw_base_0

    };

    //==========================================================

    // base end/*}}}*/

    //==========================================================

    //==========================================================

    // dbg start/*{{{*/

    //==========================================================

    assign rdata_dbg_w = {

    14'd0

    ,i_ro_dbg_0

    ,3'd0

    ,i_ro_dbg_1

    ,4'd0

    };

    //==========================================================

    // dbg end/*}}}*/

    //==========================================================

    下面代码内容较多,对照上面生成内容看会更好

    def gen_reg(data):

    reg_str = []

    for reg in data:

    reg_str.append("//==========================================================\n")

    reg_str.append("// %-44s start/*{{{*/\n" % reg['name'])

    reg_str.append("//==========================================================\n")

    reg_name = "reg_%s_r" % reg['name']

    value_bit_name = "%s_VALID_BIT" % reg['name'].upper()

    default_name = "%s_DEFAULT" % reg['name'].upper()

    write_name = "wr_%s_w" % reg['name']

    rdata_name = "rdata_%s_w" % reg['name']

    if reg['type'] == 'RW':

    # localparam

    value_bit = 0

    default = 0

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_def = bit[2]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    bit_len = bit_end - bit_start + 1

    value_bit |= (((2**bit_len) - 1) << bit_start)

    default |= bit_def << bit_start

    value_bit_str = "%08x" % value_bit

    default_str = "%08x" % default

    value_bit_str = "_".join([ value_bit_str[i*2:i*2+2] for i in range(4)])

    default_str = "_".join([ default_str[i*2:i*2+2] for i in range(4)])

    reg_str.append("localparam %-30s = 32'h%s;\n" % (value_bit_name, value_bit_str))

    reg_str.append("localparam %-30s = 32'h%s;\n" % (default_name, default_str))

    reg_str.append("\n")

    # reg function

    reg_str.append("always@(posedge i_clk) begin\n" )

    reg_str.append(" if(i_rst_n == 1'd0) begin\n" )

    reg_str.append(" %s <= %s;\n" % (reg_name, default_name,))

    reg_str.append(" end\n" )

    reg_str.append(" else if(%s) begin\n" % write_name)

    reg_str.append(" %s <= wdata & %s;\n" % (reg_name, value_bit_name,))

    reg_str.append(" end\n" )

    reg_str.append("end\n" )

    reg_str.append("\n" )

    # output

    for bit in reg['bit']:

    output_name = "o_sw_%s" % bit[0]

    bit_range = bit[1]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    bit_len = bit_end - bit_start + 1

    if bit_len > 1:

    bit_range_str = "[%d:%d]" % (bit_end, bit_start)

    else:

    bit_range_str = "[%d]" % bit_start

    reg_str.append("assign %-16s = %s%s;\n" % (output_name, reg_name, bit_range_str,))

    reg_str.append("\n")

    # rdata

    bit_index = 0

    rdata_list = []

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    if bit_index != bit_start:

    rdata_list.append("%d'd0" % (bit_start - bit_index))

    if reg['type'] == "RW":

    rdata_list.append("o_sw_%s" % bit[0])

    else:

    rdata_list.append("i_ro_%s" % bit[0])

    bit_index = bit_end + 1

    if bit_index != 32:

    rdata_list.append("%d'd0" % (32 - bit_index))

    reg_str.append("assign %s = {\n" % rdata_name)

    reg_str.append(" " + "\n ,".join(rdata_list[::-1]) + "\n")

    reg_str.append("};\n")

    reg_str.append("//==========================================================\n")

    reg_str.append("// %-44s end/*}}}*/\n" % reg['name'])

    reg_str.append("//==========================================================\n")

    reg_str.append("\n")

    return reg_str

    首先产生需要一些名称

    产生默认值、可写bit 这两个localparam

    产生寄存器写的always

    产生输出信号的连接

    产生输出信号的拼接,这里RW拼接的是o_sw_* 而RO拼接的是i_ro_*

    9.产生寄存器读逻辑

    这可以说已经是最后了

    前面大部分逻辑都生成了,就差能让总线读取到的逻辑了

    always@(posedge i_clk) begin

    if(i_rst_n == 1'd0) begin

    rdata <= 32'd0;

    end

    else if(rd) begin

    case(addr)

    BASE_ADDR : rdata <= rdata_base_w ;

    DBG_ADDR : rdata <= rdata_dbg_w ;

    TEST_ADDR : rdata <= rdata_test_w ;

    default : rdata <= 32'd0 ;

    endcase

    end

    else begin

    rdata <= rdata;

    end

    end

    这里恒简单,因为前面已经将信号拼接好了,这里直接使用即可

    def gen_rdata(data):

    rdata_str = []

    for reg in data:

    addr_name = "%s_ADDR" % reg['name'].upper()

    rdata_name = "rdata_%s_w" % reg['name']

    rdata_str.append(" %-22s : rdata <= %-21s;\n" % (addr_name, rdata_name,))

    return rdata_str

    10.合并上述内容进行输出

    上面产生完所有逻辑内容,这里就只需要将所有内容拼接起来

    下面代码虽然长,但其实没有什么内容。

    def gen_reg_file(

    mode_name,

    io_str,

    localparam_str,

    reg_wire_str,

    write_signal_str,

    reg_str,

    rdata_str,

    ):

    with open("../reg_file/%s_reg_cfg.v" % mode_name, "w") as f:

    f.write("module M%s_reg_cfg\n" % mode_name )

    f.write("(\n" )

    f.write(" // clk / rst_n\n" )

    f.write(" input i_clk\n" )

    f.write(" ,input i_rst_n\n" )

    f.write("\n" )

    f.write(" // apb port\n" )

    f.write(" ,input i_psel\n" )

    f.write(" ,input [15:0] i_paddr\n" )

    f.write(" ,input i_penable\n" )

    f.write(" ,input i_pwrite\n" )

    f.write(" ,input [31:0] i_pwdata\n" )

    f.write(" ,output [31:0] o_prdata\n" )

    f.write("\n" )

    f.write("".join(io_str))

    f.write(");\n" )

    f.write("//==========================================================\n")

    f.write("// apb bus ctrl start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("wire wr ;\n")

    f.write("wire rd ;\n")

    f.write("wire [15:0] addr ;\n")

    f.write("wire [31:0] wdata ;\n")

    f.write("reg [31:0] rdata ;\n")

    f.write("\n" )

    f.write("assign wr = i_psel & i_penable & i_pwrite ;\n")

    f.write("assign rd = i_psel & ~i_penable & ~i_pwrite ;\n")

    f.write("assign addr = i_paddr ;\n")

    f.write("assign wdata = i_pwdata ;\n")

    f.write("assign o_prdata = rdata ;\n")

    f.write("//==========================================================\n")

    f.write("// apb bus ctrl end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// localparam start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(localparam_str))

    f.write("//==========================================================\n")

    f.write("// localparam end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// reg and wire start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(reg_wire_str))

    f.write("//==========================================================\n")

    f.write("// reg and wire end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// write signal gen start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(write_signal_str))

    f.write("//==========================================================\n")

    f.write("// write signal gen end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("".join(reg_str))

    f.write("//==========================================================\n")

    f.write("// rdata start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("always@(posedge i_clk) begin\n" )

    f.write(" if(i_rst_n == 1'd0) begin\n" )

    f.write(" rdata <= 32'd0;\n" )

    f.write(" end\n" )

    f.write(" else if(rd) begin\n" )

    f.write(" case(addr)\n" )

    f.write("".join(rdata_str))

    f.write(" default : rdata <= 32'd0 ;\n")

    f.write(" endcase\n" )

    f.write(" end\n" )

    f.write(" else begin\n" )

    f.write(" rdata <= rdata;\n" )

    f.write(" end\n" )

    f.write("end\n" )

    f.write("//==========================================================\n")

    f.write("// rdata end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("endmodule\n" )

    f.close()

    结尾

    在工作过程中有许多的事,而且IC这一行容错率非常低,稍微一个bug就可以是流片失败(FPGA的除外)

    而我一直奉行观点。而工作后会发现有很多的工具就是专门为了帮助人们找错误的,仿真就是其一。

    然而工具使用的在熟练,也是需要花费不少时间的。

    所以提高效率和准确性就是流程化,并且自动化

    下面为完整的脚本

    #!/bin/env python

    import os

    import sys

    # ==========================================================

    # get reg list start#{{{

    # ==========================================================

    def get_reg_list(file_name):

    try:

    with open(file_name, "r") as f:

    data_str = f.readlines()

    data_str = "".join(data_str)

    _locals = locals()

    exec(data_str, globals(), _locals)

    data = _locals[file_name]

    return data

    except:

    print("open file %s err" % file_name)

    sys.exit(1)

    # ==========================================================

    # get reg list end#}}}

    # ==========================================================

    # ==========================================================

    # add default start#{{{

    # ==========================================================

    def add_default(data):

    def_addr = 0x0000

    def_type = "RW"

    def_value = 0x0

    for reg in data:

    # add default addr

    try:

    def_addr = reg["addr"] + 4

    except:

    reg["addr"] = def_addr

    def_addr = reg["addr"] + 4

    # add default type

    try:

    reg["type"]

    except:

    reg["type"] = def_type

    for bit in reg["bit"]:

    # add default range

    if len(bit[1]) == 1:

    bit[1] = [bit[1][0],bit[1][0]]

    # add default value

    try:

    bit[2]

    except:

    bit.append(def_value)

    # ==========================================================

    # add default end#}}}

    # ==========================================================

    # ==========================================================

    # check overlap start#{{{

    # ==========================================================

    def check_overlap(data):

    err = 0

    # addr overlap check

    addr_list = []

    for reg in data:

    addr_list.append(reg["addr"])

    set_addr_list = list(set(addr_list))

    if len(addr_list) != len(set_addr_list):

    overlap_addr = [ addr for addr in set_addr_list if addr_list.count(addr) > 1]

    for addr in overlap_addr:

    print("Err : 0x%08x addr overlap !!!" % addr)

    err = 1

    # bit overlap check

    for reg in data:

    bit_list = []

    for bit in reg["bit"]:

    bit_start = bit[1][1]

    bit_end = bit[1][0]

    bit_list += range(bit_start,bit_end+1)

    set_bit_list = list(set(bit_list))

    if len([bit for bit in set_bit_list if bit >= 32]) > 0:

    print("Err : reg %s addr 0x%08x bit out range !!!" % (reg['name'], reg['addr']))

    err = 1

    if len(bit_list) != len(set_bit_list):

    overlap_bit = [ bit for bit in set_bit_list if bit_list.count(bit) > 1]

    print("Err : 0x%08x bit %s overlap !!!" % (reg['addr'], str(overlap_bit)))

    err = 1

    if err:

    sys.exit(1)

    # ==========================================================

    # check overlap end#}}}

    # ==========================================================

    # ==========================================================

    # gen io port start#{{{

    # ==========================================================

    def gen_io_port(data):

    io_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    ro_list = [ reg for reg in data if reg['type'] == 'RO']

    # output port

    io_str.append(" // output port\n")

    for reg in rw_list:

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_len = bit_range[0] - bit_range[1]

    if bit_len != 0:

    range_str = "[%d:0]" % bit_len

    else:

    range_str = ""

    bit_name_str = "o_sw_%s" % bit[0]

    io_str.append(" ,output %-17s %s\n" % (range_str, bit_name_str,))

    io_str.append("\n");

    # input port

    io_str.append(" // input port\n")

    for reg in ro_list:

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_len = bit_range[0] - bit_range[1]

    if bit_len != 0:

    range_str = "[%d:0]" % bit_len

    else:

    range_str = ""

    bit_name_str = "i_ro_%s" % bit[0]

    io_str.append(" ,input %-17s %s\n" % (range_str, bit_name_str,))

    io_str.append("\n");

    return io_str

    # ==========================================================

    # gen io port end#}}}

    # ==========================================================

    # ==========================================================

    # gen localparam start#{{{

    # ==========================================================

    def gen_localparam(data):

    localparam_str = []

    for reg in data:

    addr_name = "%s_ADDR" % reg['name'].upper()

    addr_str = "16'h%04x" % reg['addr']

    localparam_str.append("localparam %-36s = %s ;\n" % (addr_name, addr_str,))

    return localparam_str

    # ==========================================================

    # gen localparam end#}}}

    # ==========================================================

    # ==========================================================

    # gen reg wire start#{{{

    # ==========================================================

    def gen_reg_wire(data):

    reg_wire_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    reg_wire_str.append("\n")

    # write signal

    reg_wire_str.append("// write signal\n")

    for reg in rw_list:

    wire_name = "wr_%s_w" % reg['name']

    reg_wire_str.append("wire %-47s;\n" % wire_name)

    reg_wire_str.append("\n")

    # reg

    reg_wire_str.append("// reg\n")

    for reg in rw_list:

    reg_name = "reg_%s_r" % reg['name']

    reg_wire_str.append("reg [31:0] %-47s;\n" % reg_name)

    reg_wire_str.append("\n")

    # read data

    reg_wire_str.append("// read data\n")

    for reg in data:

    wire_name = "rdata_%s_w" % reg['name']

    reg_wire_str.append("wire [31:0] %-47s;\n" % wire_name)

    reg_wire_str.append("\n")

    return reg_wire_str

    # ==========================================================

    # gen reg wire end#}}}

    # ==========================================================

    # ==========================================================

    # gen write signal start#{{{

    # ==========================================================

    def gen_write_signal(data):

    write_signal_str = []

    rw_list = [ reg for reg in data if reg['type'] == 'RW']

    for reg in rw_list:

    wire_name = "wr_%s_w" % reg['name']

    addr_name = "%s_ADDR" % reg['name'].upper()

    write_signal_str.append("assign %-20s = wr & (addr == %-14s);\n" % (wire_name, addr_name,))

    return write_signal_str

    # ==========================================================

    # gen write signal end#}}}

    # ==========================================================

    # ==========================================================

    # gen reg start#{{{

    # ==========================================================

    def gen_reg(data):

    reg_str = []

    for reg in data:

    reg_str.append("//==========================================================\n")

    reg_str.append("// %-44s start/*{{{*/\n" % reg['name'])

    reg_str.append("//==========================================================\n")

    reg_name = "reg_%s_r" % reg['name']

    value_bit_name = "%s_VALID_BIT" % reg['name'].upper()

    default_name = "%s_DEFAULT" % reg['name'].upper()

    write_name = "wr_%s_w" % reg['name']

    rdata_name = "rdata_%s_w" % reg['name']

    if reg['type'] == 'RW':

    # localparam

    value_bit = 0

    default = 0

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_def = bit[2]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    bit_len = bit_end - bit_start + 1

    value_bit |= (((2**bit_len) - 1) << bit_start)

    default |= bit_def << bit_start

    value_bit_str = "%08x" % value_bit

    default_str = "%08x" % default

    value_bit_str = "_".join([ value_bit_str[i*2:i*2+2] for i in range(4)])

    default_str = "_".join([ default_str[i*2:i*2+2] for i in range(4)])

    reg_str.append("localparam %-30s = 32'h%s;\n" % (value_bit_name, value_bit_str))

    reg_str.append("localparam %-30s = 32'h%s;\n" % (default_name, default_str))

    reg_str.append("\n")

    # reg function

    reg_str.append("always@(posedge i_clk) begin\n" )

    reg_str.append(" if(i_rst_n == 1'd0) begin\n" )

    reg_str.append(" %s <= %s;\n" % (reg_name, default_name,))

    reg_str.append(" end\n" )

    reg_str.append(" else if(%s) begin\n" % write_name)

    reg_str.append(" %s <= wdata & %s;\n" % (reg_name, value_bit_name,))

    reg_str.append(" end\n" )

    reg_str.append("end\n" )

    reg_str.append("\n" )

    # output

    for bit in reg['bit']:

    output_name = "o_sw_%s" % bit[0]

    bit_range = bit[1]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    bit_len = bit_end - bit_start + 1

    if bit_len > 1:

    bit_range_str = "[%d:%d]" % (bit_end, bit_start)

    else:

    bit_range_str = "[%d]" % bit_start

    reg_str.append("assign %-16s = %s%s;\n" % (output_name, reg_name, bit_range_str,))

    reg_str.append("\n")

    # rdata

    bit_index = 0

    rdata_list = []

    for bit in reg['bit']:

    bit_range = bit[1]

    bit_start = bit_range[1]

    bit_end = bit_range[0]

    if bit_index != bit_start:

    rdata_list.append("%d'd0" % (bit_start - bit_index))

    if reg['type'] == "RW":

    rdata_list.append("o_sw_%s" % bit[0])

    else:

    rdata_list.append("i_ro_%s" % bit[0])

    bit_index = bit_end + 1

    if bit_index != 32:

    rdata_list.append("%d'd0" % (32 - bit_index))

    reg_str.append("assign %s = {\n" % rdata_name)

    reg_str.append(" " + "\n ,".join(rdata_list[::-1]) + "\n")

    reg_str.append("};\n")

    reg_str.append("//==========================================================\n")

    reg_str.append("// %-44s end/*}}}*/\n" % reg['name'])

    reg_str.append("//==========================================================\n")

    reg_str.append("\n")

    return reg_str

    # ==========================================================

    # gen reg end#}}}

    # ==========================================================

    # ==========================================================

    # gen rdata start#{{{

    # ==========================================================

    def gen_rdata(data):

    rdata_str = []

    for reg in data:

    addr_name = "%s_ADDR" % reg['name'].upper()

    rdata_name = "rdata_%s_w" % reg['name']

    rdata_str.append(" %-22s : rdata <= %-21s;\n" % (addr_name, rdata_name,))

    return rdata_str

    # ==========================================================

    # gen rdata end#}}}

    # ==========================================================

    # ==========================================================

    # gen reg file start#{{{

    # ==========================================================

    def gen_reg_file(

    mode_name,

    io_str,

    localparam_str,

    reg_wire_str,

    write_signal_str,

    reg_str,

    rdata_str,

    ):

    with open("../reg_file/%s_reg_cfg.v" % mode_name, "w") as f:

    f.write("module M%s_reg_cfg\n" % mode_name )

    f.write("(\n" )

    f.write(" // clk / rst_n\n" )

    f.write(" input i_clk\n" )

    f.write(" ,input i_rst_n\n" )

    f.write("\n" )

    f.write(" // apb port\n" )

    f.write(" ,input i_psel\n" )

    f.write(" ,input [15:0] i_paddr\n" )

    f.write(" ,input i_penable\n" )

    f.write(" ,input i_pwrite\n" )

    f.write(" ,input [31:0] i_pwdata\n" )

    f.write(" ,output [31:0] o_prdata\n" )

    f.write("\n" )

    f.write("".join(io_str))

    f.write(");\n" )

    f.write("//==========================================================\n")

    f.write("// apb bus ctrl start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("wire wr ;\n")

    f.write("wire rd ;\n")

    f.write("wire [15:0] addr ;\n")

    f.write("wire [31:0] wdata ;\n")

    f.write("reg [31:0] rdata ;\n")

    f.write("\n" )

    f.write("assign wr = i_psel & i_penable & i_pwrite ;\n")

    f.write("assign rd = i_psel & ~i_penable & ~i_pwrite ;\n")

    f.write("assign addr = i_paddr ;\n")

    f.write("assign wdata = i_pwdata ;\n")

    f.write("assign o_prdata = rdata ;\n")

    f.write("//==========================================================\n")

    f.write("// apb bus ctrl end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// localparam start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(localparam_str))

    f.write("//==========================================================\n")

    f.write("// localparam end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// reg and wire start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(reg_wire_str))

    f.write("//==========================================================\n")

    f.write("// reg and wire end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("//==========================================================\n")

    f.write("// write signal gen start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("".join(write_signal_str))

    f.write("//==========================================================\n")

    f.write("// write signal gen end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("".join(reg_str))

    f.write("//==========================================================\n")

    f.write("// rdata start/*{{{*/\n")

    f.write("//==========================================================\n")

    f.write("always@(posedge i_clk) begin\n" )

    f.write(" if(i_rst_n == 1'd0) begin\n" )

    f.write(" rdata <= 32'd0;\n" )

    f.write(" end\n" )

    f.write(" else if(rd) begin\n" )

    f.write(" case(addr)\n" )

    f.write("".join(rdata_str))

    f.write(" default : rdata <= 32'd0 ;\n")

    f.write(" endcase\n" )

    f.write(" end\n" )

    f.write(" else begin\n" )

    f.write(" rdata <= rdata;\n" )

    f.write(" end\n" )

    f.write("end\n" )

    f.write("//==========================================================\n")

    f.write("// rdata end/*}}}*/\n")

    f.write("//==========================================================\n")

    f.write("\n" )

    f.write("endmodule\n" )

    f.close()

    # ==========================================================

    # gen reg file end#}}}

    # ==========================================================

    if __name__ == '__main__':

    if(len(sys.argv) < 2):

    print("not have input file")

    print(" %s reg_list" % sys.argv[0])

    sys.exit(0)

    file_name = sys.argv[1]

    mode_name = file_name.split("_")[0]

    data = get_reg_list(file_name)

    add_default(data)

    check_overlap(data)

    io_str = gen_io_port(data)

    localparam_str = gen_localparam(data)

    reg_wire_str = gen_reg_wire(data)

    write_signal_str = gen_write_signal(data)

    reg_str = gen_reg(data)

    rdata_str = gen_rdata(data)

    gen_reg_file(

    mode_name,

    io_str,

    localparam_str,

    reg_wire_str,

    write_signal_str,

    reg_str,

    rdata_str,

    )

    如果生成不了或是错误可能是下面几点

    1.列表文件名不是_reg_list

    2.列表文件中列表名和文件不一致

    3.代码中生成目录为 "../reg_file/_reg_cfg.v",需要有相应的目录才能生成

    4.是不是python版本问题

    如果有问题或是有想探讨的可以加我微信:anyuexiu

    展开全文
  • 没有什么比Bash自动化完成数小时繁琐工作的Bash优雅系列更令我满意的了。 作为最近使用Bash脚本自动重新创建笔记本电脑的探索的一部分,我想找到一种方法,可以轻松地将GitHub托管的存储库克隆到新计算机上。 经过...

    没有什么比让Bash自动化完成数小时繁琐工作的Bash优雅系列更令我满意的了。 作为最近使用Bash脚本自动重新创建笔记本电脑的探索的一部分,我想找到一种方法,可以轻松地将GitHub托管的存储库克隆到新计算机上。 经过一番挖掘之后,我写了一篇这样的单线纸。 然后,本着不把所有鸡蛋都放在同一篮子的精神,我写了另一种单行代码来自动创建并推送到GitLab托管的备份。 他们来了。

    一个Bash单一代码来克隆您所有的GitHub存储库

    警告:您将需要要克隆的GitHub存储库的列表。 这样做的好处是,它为您提供了全面的代理权,使您可以只选择要在计算机上存储的存储库,而不必花很多精力。

    您可以轻松地克隆GitHub存储库,而无需每次都输入HTTPS并使用15分钟的缓存凭据,或者,我首选的方法是使用SSH连接到GitHub,而无需每次输入密码。 为简便起见,我假设我们要使用后者,并且我们已经设置了SSH密钥。

    gh-repos.txt文件中给出GitHub URL列表,如下所示:

    git@github.com:username/first-repository.git
    git@github.com:username/second-repository.git
    git@github.com:username/third-repository.git

    我们跑:

    xargs -n1 git clone < gh-repos.txt

    这会将列表上的所有存储库克隆到当前文件夹中。 如果替换适当的URL,则同一行也适用于GitLab存储库。

    这里发生了什么?

    单行代码有两半:违反直觉的输入在右侧,而使事情发生的部分在左侧。 通过编写如下相同的命令,我们可以使这些部分的顺序更直观(也许?):

    <gh-repos.txt xargs -n1 git clone 

    要对输入的每一行gh-repos.txt运行命令,我们使用xargs -n1 xargs工具从输入中读取项目并执行找到的所有命令(如果找不到则echo )。 默认情况下,它假定项目之间用空格隔开; 新行也可以使我们的列表更易于阅读。 标志-n1告诉xargs每个命令使用1参数,在本例中为1行。 我们使用git clone构建命令,然后xargs将针对每一行执行。 -

    Bash一线式工具,可在GitLab上创建并推送许多存储库

    与GitHub不同,GitLab让我们可以做这件漂亮的事情,而不必先使用网站创建新的存储库。 我们可以从终端创建一个新的GitLab存储库 新创建的存储库默认设置为“私有”,因此,如果要在GitLab上将其设置为“公开”,则稍后必须手动进行。

    GitLab文档告诉我们使用git push --set-upstream来推动创建一个新项目,但是我觉得使用GitLab作为备份不是很方便。 将来在使用存储库时,我想运行一个命令同时推送到GitHub GitLab,而无需我付出额外的努力。

    为了使此Bash单线工作,我们还需要GitLab的存储库URL列表(尚不存在的URL)。 我们可以轻松地做到这一点,方法是复制我们的GitHub存储库列表,使用Vim打开它,然后进行搜索和替换

    cp gh-repos.txt gl-repos.txt
    vim gl-repos.txt
    :%s/\<github\>/gitlab/g
    :wq

    这将产生gl-repos.txt ,看起来像:

    git@gitlab.com:username/first-repository.git
    git@gitlab.com:username/second-repository.git
    git@gitlab.com:username/third-repository.git

    我们可以在GitLab上创建这些存储库,将URL添加为远程存储,并通过运行以下命令将代码推送到新的存储库:

    awk -F '\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

    请稍等,我会解释。 现在,请注意~/FULL/PATH/应该是包含我们的GitHub存储库的目录的完整路径。

    我们必须注意以下两个假设:

    1. 包含资源库的本地计算机上目录的名称与URL中资源库的名称相同(如果是使用上述一种方法克隆的,则为这种情况);
    2. 当前,每个存储库都检出到要推送的分支,即。 master

    单行代码可以扩展以处理这些假设,但是作者的愚见是,在那时,我们确实应该编写Bash脚本。

    这里发生了什么?

    我们的Bash单行使用gl-repos.txt文件中的每一行(或URL)作为输入。 使用awk ,它拆分出包含本地计算机上存储库的目录名称,并使用这些信息来构建更大的命令。 如果我们要print的输出awk ,我们会看到:

    cd ~/FULL/PATH/first-repository && git remote set -url origin --add git@gitlab.com:username/first-repository.git && git push
    cd ~/FULL/PATH/second-repository && git remote set -url origin --add git@gitlab.com:username/second-repository.git && git push
    cd ~/FULL/PATH/third-repository && git remote set -url origin --add git@gitlab.com:username/third-repository.git && git push

    让我们看看如何构建此命令。

    awk分割字符串

    工具awk可以基于字段分隔符拆分输入。 默认的分隔符是空格字符,但是我们可以通过传递-F标志来更改它。 除了单个字符,我们还可以使用正则表达式字段分隔符 由于我们的存储库URL具有固定的格式,因此我们可以通过请求斜杠/和URL末尾.git之间的子字符串来获取存储库名称。

    实现此目的的一种方法是使用我们的正则表达式\/|(\.git)

    • \/是转义的/字符;
    • | 表示“或”,告诉awk匹配任一表达式;
    • (\.git)是URL末尾的捕获组,与“ .git”匹配,带有转义符. 字符。 这有点作弊,因为“ .git”并没有严格分割任何内容(另一面没有任何内容),但这是我们轻松实现这一点的简便方法。

    告诉awk在哪里分割后,我们可以使用field运算符来获取正确的子字符串。 我们用$字符引用字段,然后用字段的列号引用。 在我们的示例中,我们需要第二个字段$2 这是所有子字符串的样子:

    1: git@gitlab.com:username
    2: first-repository

    要使用整个字符串或本示例中的整个URL,我们使用字段运算符$0 要编写该命令,我们只需将字段运算符替换为存储库名称和URL。 在我们构建时使用print运行它可以帮助确保所有空间都正确。

    awk -F '\/|(\.git)' '{print "cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push"}' gl-repos.txt

    运行命令

    我们在system()括号内构建命令。 通过将其用作awk的输出,每条命令在生成并输出后将立即运行。 system()函数创建一个执行我们命令的子进程 ,然后在命令完成后返回。 用简单的英语来说,这使我们可以在每个存储库上一个接一个地执行Git命令,而不会破坏awk使用输入文件执行操作的主要过程。 这是我们的最终命令,所有命令都放在一起了。

    awk -F '\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

    使用我们的备份

    通过将GitLab URL添加为远程站点,我们简化了推送到两个外部托管存储库的过程。 如果在其中一个存储库目录中运行git remote -v ,我们将看到:

    origin  git@github.com:username/first-repository.git (fetch)
    origin  git@github.com:username/first-repository.git (push)
    origin  git@gitlab.com:username/first-repository.git (push)

    现在,简单地运行不带参数的git push会将当前分支推送到两个远程存储库。

    我们还应该注意, git pull通常只会尝试从最初克隆的远程存储库中(fetch)在上面的示例中标记为(fetch)的URL)。 可以同时从多个Git存储库中拉出,但很复杂,超出了本文的范围。 如果您有好奇心,这是推和拉到多个遥控器以帮助您入门的说明。 遥控器上Git文档也可能会有所帮助。

    详细阐述Bash单行代码的简洁性

    当了解Bash一线时,它可能是有趣且方便的快捷方式。 至少,了解xargsawk类的工具可以帮助自动化和减轻工作中的繁琐工作。 但是,还有一些缺点。

    就易于理解,易于维护和易于使用的工具而言,Bash一线难熬。 与使用ifwhile循环的Bash脚本相比,编写它们通常更复杂,并且读取起来当然更复杂。 当我们编写它们时,可能会在某处遗漏单引号或右括号。 正如我希望这篇文章所演示的那样,他们也可以做很多解释。 那为什么要使用它们呢?

    想象一下,逐步阅读烘焙蛋糕的食谱。 您了解方法和成分,并收集物品。 然后,当您考虑它时,您开始意识到,如果只是以正确的顺序将所有配料扔进烤箱,蛋糕就会立即变质。 您尝试一下,就可以了!

    那会很令人满意,不是吗?

    From: https://hackernoon.com/how-to-write-bash-one-liners-for-cloning-and-managing-github-and-gitlab-repositories-2d2di30h5

    展开全文
  • gitlab bash 没有什么比Bash自动化完成数小时繁琐工作的Bash优雅系列更令我满意的了。 作为最近使用Bash脚本自动重新创建笔记本电脑的探索的一部分,我想找到一种轻松地将GitHub托管的存储库克隆到新计算机上的...

    gitlab bash

    没有什么比让Bash自动化完成数小时繁琐工作的Bash优雅系列更令我满意的了。 作为最近使用Bash脚本自动重新创建笔记本电脑的探索的一部分,我想找到一种轻松地将GitHub托管的存储库克隆到新计算机上的方法。 经过一番挖掘之后,我写了一篇这样的单线纸。 然后,本着不把所有鸡蛋都放在同一篮子的精神,我写了另一种单行代码来自动创建并推送到GitLab托管的备份。 他们来了。

    一个Bash单一代码来克隆您所有的GitHub存储库

    警告:您将需要要克隆的GitHub存储库的列表。 这样做的好处是,它使您可以完全选择仅要在计算机上存储的存储库,而不必花很多精力。

    您可以轻松地克隆GitHub存储库,而无需每次都输入HTTPS并使用15分钟的缓存凭证,或者,我首选的方法是使用SSH连接到GitHub,而无需每次输入密码。 为简便起见,我假设我们要使用后者,并且我们已经设置了SSH密钥。

    gh-repos.txt文件中给出GitHub URL列表,如下所示:

    git@github.com:username/first-repository.git
    git@github.com:username/second-repository.git
    git@github.com:username/third-repository.git

    我们跑:

    xargs -n1 gitclone < gh-repos.txt

    这会将列表上的所有存储库克隆到当前文件夹中。 如果替换适当的URL,则同一行也适用于GitLab存储库。

    这里发生了什么?

    单行代码有两半:输入(在直觉上相反)在右侧,而使事情发生的部分在左侧。 通过编写如下相同的命令,我们可以使这些部分的顺序更直观(也许?):

    <gh-repos.txt xargs -n1 gitclone 

    要对输入的每一行gh-repos.txt运行命令,我们使用xargs -n1 xargs工具从输入中读取项目并执行找到的任何命令(如果找不到则echo )。 默认情况下,它假定项目之间用空格隔开; 新行也可以使我们的列表更易于阅读。 标志-n1告诉xargs每个命令使用1参数,在本例中为1行。 我们使用git clone构建命令,然后xargs将针对每一行执行。 -

    Bash一线式工具,可在GitLab上创建并推送许多存储库

    与GitHub不同,GitLab让我们可以做这件漂亮的事情,而不必先使用网站创建新的存储库。 我们可以从终端创建一个新的GitLab存储库 新创建的存储库默认设置为“私有”,因此,如果要在GitLab上将其设置为“公开”,则稍后必须手动进行。

    GitLab文档告诉我们使用git push --set-upstream来创建一个新项目,但是我发现使用GitLab作为备份不是很方便。 将来在使用我的存储库时,我想运行一个可以同时推送到GitHub GitLab的命令。

    为了使此Bash单线工作,我们还需要GitLab的存储库URL列表(尚不存在的URL)。 我们可以轻松地做到这一点,方法是复制我们的GitHub存储库列表,使用Vim打开它,然后进行搜索和替换

    cp gh-repos.txt gl-repos.txt
    vim gl-repos.txt
    :%s/\<github\>/gitlab/g
    :wq

    这将产生gl-repos.txt ,看起来像:

    git@gitlab.com:username/first-repository.git
    git@gitlab.com:username/second-repository.git
    git@gitlab.com:username/third-repository.git

    我们可以在GitLab上创建这些存储库,将URL添加为远程存储,并通过运行以下命令将代码推送到新的存储库:

    awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

    请稍等,我会解释。 现在,请注意~/FULL/PATH/应该是包含我们的GitHub存储库的目录的完整路径。

    我们必须注意以下两个假设:

    1. 包含资源库的本地计算机上目录的名称与URL中资源库的名称相同(如果是使用上述一种方法克隆的,则为这种情况);
    2. 当前,每个存储库都检出到要推送的分支,即。 master

    单行代码可以扩展以处理这些假设,但是作者的拙见认为,在那时,我们确实应该编写Bash脚本。

    这里发生了什么?

    我们的Bash单行使用gl-repos.txt文件中的每一行(或URL)作为输入。 使用awk ,它拆分出包含本地计算机上存储库的目录名称,并使用这些信息来构建更大的命令。 如果我们要print的输出awk ,我们会看到:

    cd ~/FULL/PATH/first-repository && git remote set -url origin --add git@gitlab.com:username/first-repository.git && git push
    cd ~/FULL/PATH/second-repository && git remote set -url origin --add git@gitlab.com:username/second-repository.git && git push
    cd ~/FULL/PATH/third-repository && git remote set -url origin --add git@gitlab.com:username/third-repository.git && git push

    让我们看看如何构建此命令。

    awk分割字符串

    工具awk可以基于字段分隔符拆分输入。 默认的分隔符是空格字符,但是我们可以通过传递-F标志来更改它。 除了单个字符,我们还可以使用正则表达式字段分隔符 由于我们的存储库URL具有固定格式,因此我们可以通过请求斜杠/和URL末尾.git之间的子字符串来获取存储库名称。

    实现此目的的一种方法是使用我们的正则表达式\/|(\.git)

    • \/是转义的/字符;
    • | 表示“或”,告诉awk匹配任一表达式;
    • (\.git)是URL末尾的捕获组,与“ .git”匹配,带有转义符. 字符。 这有点作弊,因为“ .git”并没有严格分割任何内容(另一面没有任何内容),但这是我们轻松实现这一点的简便方法。

    告诉awk拆分位置后,我们可以使用field运算符来获取正确的子字符串。 我们用$字符引用字段,然后用字段的列号引用。 在我们的示例中,我们需要第二个字段$2 这是所有子字符串的样子:

    1: git@gitlab.com:username
    2: first-repository

    要使用整个字符串或本示例中的整个URL,我们使用字段运算符$0 要编写命令,我们只需将字段运算符替换为存储库名称和URL。 在构建它时使用print运行它可以帮助确保所有空间都正确。

    awk -F'\/|(\.git)' '{print "cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push"}' gl-repos.txt

    运行命令

    我们在system()括号内构建命令。 通过将此作为awk的输出,每条命令在生成并输出后都会立即运行。 system()函数创建一个执行我们命令的子进程 ,然后在命令完成后返回。 用简单的英语来说,这使我们可以在每个存储库上一对一地执行Git命令,而不会中断awk使用输入文件执行操作的主要过程。 这是我们的最终命令,所有命令都放在一起了。

    awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

    使用我们的备份

    通过将GitLab URL添加为远程站点,我们简化了推送到两个外部托管存储库的过程。 如果在我们的存储库目录之一中运行git remote -v ,我们将看到:

    origin  git@github.com:username/first-repository.git (fetch)
    origin  git@github.com:username/first-repository.git (push)
    origin  git@gitlab.com:username/first-repository.git (push)

    现在,简单地运行不带参数的git push会将当前分支推送到两个远程存储库。

    我们还应注意, git pull通常只会尝试从最初克隆的远程存储库中(fetch)在上面的示例中标记为(fetch)的URL)。 同时从多个Git存储库中提取是可能的,但很复杂,超出了本文的范围。 如果您有好奇心,这是推和拉到多个遥控器以帮助您入门的说明。 遥控器上Git文档也可能会有所帮助。

    详细阐述Bash单行代码的简洁性

    如果了解Bash一线,可以说是有趣而便捷的捷径。 至少,了解xargsawk类的工具可以帮助自动化和减轻我们工作中的繁琐工作。 但是,还有一些缺点。

    就易于理解,可维护和易用的工具而言,Bash一线难熬。 与使用ifwhile循环的Bash脚本相比,编写它们通常更复杂,并且读取起来当然更复杂。 当我们编写它们时,可能会在某处遗漏单引号或右括号。 正如我希望这篇文章所演示的那样,他们也可以做很多解释。 那为什么要使用它们呢?

    想象一下,逐步阅读烘焙蛋糕的食谱。 您了解方法和成分,并收集物品。 然后,当您考虑它时,您开始意识到,如果只是以正确的顺序将所有配料扔进烤箱,蛋糕就会立即变质。 您尝试一下,就可以了!

    那会很令人满意,不是吗?

    翻译自: https://hackernoon.com/how-to-write-bash-one-liners-for-cloning-and-managing-github-and-gitlab-repositories-2d2di30h5

    gitlab bash

    展开全文
  • 而前端使用流程自动化工具更是没有测试参与了)。对于像基础组件、基础模型之类不常变更且复用较多部分,可以考虑去写测试用例来保证质量。个人比较倾向于先写少量测试用例覆盖到80%+场景...
  • 本书在向个人电脑用户,系统而详细地讲解了电脑的常见故障,同时读者更直接、更深刻地了解电脑故障产生原因和排除方法,从而达到能够自己解决电脑故障目的。 本书分10章,共有1000多个实例,编写时从产生电脑...
  • 在本工作坊中,您首先将OpenFaaS部署到笔记本电脑或使用Docker for Mac或Windows远程集群。 然后,您将使用OpenFaaS UI,CLI和Function Store来解决问题。 构建,使用Python部署调用自己无服务器功能之后,您将...
  • 与我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示了谢意。 研究生签名: 日期: 东南大学学位论文使用 授权声明 东南大学、中国科学技术信息研究所、国家图书馆有权保留本人...
  • asp.net知识库

    2015-06-18 08:45:45
    生成表中的数据的脚本 最详细的SQL注入相关的命令整理 Oracle Oracle中PL/SQL单行函数和组函数详解 mssql+oracle Oracle编程的编码规范及命名规则 Oracle数据库字典介绍 0RACLE的字段类型 事务 CMT DEMO(容器管理...
  • 上面我们已经简要的讲述了一些XML的基本原理,我们来看看它们之间的关联以及它们是如何工作的,先看这里一张图: 1.XML描述数据类型。例如:"King lear"是一个标题元素; 2.CSS储存并控制元素的显示样式。例如...
  •  本书还提供了dba完成本职工作必备基本uniix、sql、pl/sql和数据建模知识,也给出了许多富有趣味性例子,通过这些实例详细、循序渐进地说明了oracle database 11g数据库各个概念和特性。 作译者  Sam...
  • 就会自动添加一些附加头信息,有时还会多出一次附加请求,但用户不会有感觉。 因此,实现 CORS 通信关键是服务器。只要服务器实现了 CORS 接口,就可以跨域通信。 前端逻辑很简单&#...
  • 073《Chrome Better History》如何让Chrome查找历史记录更方便? 072《OneNote Web Clipper》微软免费跨平台笔记OneNote扩展程序 071《Color Tab》色彩猎人优质配色提升你审美 070《网盘助手》网盘万能钥匙,...
  • 如果你的电脑满足要求但仍然显示检查失败,这时候直接忽略,勾选全部忽略 7. 步骤6/8:概要信息 核对将要安装数据详细信息,并保存响应文件,以备以后查看。然后点击完成数据库安装 8. 步骤7/8:安装产品 ...
  • docker中mysql启动时自动执行sql》 《Docker搭建disconf环境,三部曲之一:极速搭建disconf》 《Docker搭建disconf环境,三部曲之二:本地快速构建disconf镜像》 《Docker搭建disconf环境,三部曲之三:细说...
  • The GNU C Library :本手册目的是告诉你如何使用GNU C库。 框架 C++通用框架和库 abseil-cpp :Abseil C ++ 通用库。 Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件集合。 ...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    实现:事物是如何工作的特殊细节(如何做) 扩展机制 约 束:允许对模型元素添加新的规则 构造型:基于已有的建模元素引入新的建模元素 标记值:允许为模型元素添加新的特性,是带有相关值得关键字 JAVA开发平台体系...
  • *如果你无论如何都需要一个在mac下工作的摄像头,吐血推荐罗技c270,我天天用 mx250独显(这个是废话) 指纹不能用(这个也是废话) 个人设备版本信息等 oc version:0.6.4 macos: BigSur 11.0.1 Public ...
  • ASD:Microsoft Word的自动保存文件;Microsoft高级流媒体格式(microsoft advanced streaming format,ASF)描述文件;可用NSREX打开 Velvet Studio例子文件 ASF:Microsoft高级流媒体格式文件 ASM:汇编语言...
  • (鉴于我的工作电脑是加了域,因为并不能使用这个方式,如果有和我一样情况童鞋,可以考虑使用另外两种调试方式) <p><img alt="clipboard.png" src=...
  • 1215 网吧维护\资料\PNP无盘工作站启动后不能提示找到新硬件解决.TXT 1716 网吧维护\资料\PNP无盘快速安装方法.TXT 5723 网吧维护\资料\RAID简介.TXT 583 网吧维护\资料\REALONE 解码器.TXT 9734 网吧维护\资料\...
  • 它使物理网络拓朴和协议透明化,这样网络上用户可以访问任何资源,而不需要知道资源在什么地方,或物理上它是如何连接到网络上。% t! G+ S" E# e9 q 2 \% m) N4 I- I* v4 f. t(2)集中式管理: * [. Y& e' Q6 @,...
  • 经典SQL语句大全

    热门讨论 2014-12-20 12:00:30
    14.如何修改数据库名称: sp_renamedb 'old_name', 'new_name' 二、提升 1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用) 法一:select * into b from a where 1<>1(仅用于SQlServer) 法二:...
  • 14.如何修改数据库名称: sp_renamedb 'old_name', 'new_name' 二、提升 1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用) 法一:select * into b from a where 1<>1(仅用于SQlServer) 法二...
  • 系统会根据该名字自动匹配对应菜单功能,来实现快捷键设置。具体可参考设置 <a href="http://osxdaily.com/2012/05/13/set-system-preferences-keyboard-shortcut-mac-os-x/">System Preference</a> ...

空空如也

空空如也

1 2
收藏数 25
精华内容 10
关键字:

如何让电脑自动工作的脚本