def generate_decoder_file(MODULENAME, INPUTS, OUTPUTS, format_dicts):
    # Get ISA information
    isa_info = format_dicts["ISA"]
    # Get register names
    registers = format_dicts["REGISTERS"]
    # Get memory fields needed for modification
    memory = format_dicts["MEMORY"]
    # Get constraints for qed module setup
    qed_constraints = format_dicts["QEDCONSTRAINTS"]
    # Get the instruction types
    ins_types = format_dicts["INSTYPES"]
    # Get the instruction fields for each type
    ins_fields = format_dicts["INSFIELDS"]
    # Get instruction types requirements
    ins_reqs = format_dicts["INSREQS"]
    # Get the bit fields
    bit_fields = format_dicts["BITFIELDS"]
    # Get all instruction types
    instructions = {}
    for ins in format_dicts["INSTYPES"].keys():
        if ins != "CONSTRAINT":
            instructions[ins] = format_dicts[ins]

    # Verilog file
    verilog = ""

    # Fill out the OUTPUTS dict
    for bit_field in bit_fields:
        if bit_field != "CONSTRAINT":
            msb, lsb = bit_fields[bit_field].split()
            bits = int(msb) - int(lsb) + 1
            OUTPUTS[bit_field] = bits

    for ins_type in instructions:
        if ins_type in ins_reqs:
            OUTPUTS["IS_" + ins_type] = 1

    # Header for module
    verilog += I.module_header(MODULENAME, INPUTS, OUTPUTS)
    verilog += I.newline(2)

    # Instantiate inputs
    for inp in INPUTS:
        verilog += I.signal_def(INPUTS[inp], "input", inp, num_spaces=2)
        verilog += I.newline(1)

    # Instantiate outputs
    verilog += I.newline(1)
    for out in OUTPUTS:
        verilog += I.signal_def(OUTPUTS[out], "output", out, num_spaces=2)
        verilog += I.newline(1)

    # Assign the bit fields to the correct bits in instruction
    verilog += I.newline(1)
    for bit_field in bit_fields:
        if bit_field != "CONSTRAINT":
            msb, lsb = bit_fields[bit_field].split()
            verilog += I.assign_def(bit_field,
                                    I.signal_index(INPUTS.keys()[0], msb, lsb),
                                    num_spaces=2)
            verilog += I.newline(1)

    # Assign instruction types requirements
    verilog += I.newline(1)
    for ins_type in instructions:
        if not ins_type in ins_reqs:
            continue
        ins_req = ins_reqs[ins_type]
        reqs = ins_req["CONSTRAINT"]
        for field in ins_req:
            if field != "CONSTRAINT":
                if type(ins_req[field]) == type([]):
                    first = ins_req[field][0]
                    req_expression = I._equals(field,
                                               I._constant(len(first), first),
                                               parens=True)
                    for req in ins_req[field][1:]:
                        equality = I._equals(field,
                                             I._constant(len(req), req),
                                             parens=True)
                        req_expression = I._or(req_expression,
                                               equality,
                                               parens=False)
                    req_expression = "(" + req_expression + ")"
                    reqs.append(req_expression)
                else:
                    equality = I._equals(field,
                                         I._constant(len(ins_req[field]),
                                                     ins_req[field]),
                                         parens=True)
                    reqs.append(equality)

        reqs_expression = reqs[0]
        for i in range(1, len(reqs)):
            reqs_expression = I._and(reqs_expression, reqs[i], parens=False)

        verilog += I.assign_def("IS_" + ins_type,
                                reqs_expression,
                                num_spaces=2)
        verilog += I.newline(1)

    # Module footer
    verilog += I.newline(1)
    verilog += I.module_footer()

    return verilog
Exemple #2
0
def generate_constraints_file(MODULENAME, INPUTS, OUTPUTS, format_dicts):
    # Get ISA information
    isa_info = format_dicts["ISA"]
    # Get register names
    registers = format_dicts["REGISTERS"]
    # Get memory fields needed for modification
    memory = format_dicts["MEMORY"]
    # Get constraints for qed module setup
    qed_constraints = format_dicts["QEDCONSTRAINTS"]
    # Get the instruction types
    ins_types = format_dicts["INSTYPES"]
    # Get the instruction fields for each type
    ins_fields = format_dicts["INSFIELDS"]
    # Get instruction types requirements
    ins_reqs = format_dicts["INSREQS"]
    # Get the bit fields
    bit_fields = format_dicts["BITFIELDS"]
    # Get all instruction types
    instructions = {}
    for ins in format_dicts["INSTYPES"].keys():
        if ins != "CONSTRAINT":
            instructions[ins] = format_dicts[ins]
    
    # Verilog file
    verilog = ""

    # Adds module header definition
    verilog += I.module_header(MODULENAME, INPUTS, OUTPUTS)
    verilog += I.newline(2)

    # Instantiate inputs
    for inp in INPUTS:
        verilog += I.signal_def(INPUTS[inp], "input", inp, num_spaces=2)
        verilog += I.newline(1)

    # Instantiate outputs
    for out in OUTPUTS:
        verilog += I.signal_def(OUTPUTS[out], "output", out, num_spaces=2)
        verilog += I.newline(1)

    # Instantiate bit fields
    verilog += I.newline(1)
    for bit_field in bit_fields:
        if bit_field != "CONSTRAINT":
            msb, lsb = bit_fields[bit_field].split()
            bits = int(msb) - int(lsb) + 1
            verilog += I.signal_def(bits, "wire", bit_field, num_spaces=2)
            verilog += I.newline(1)

    # Instantiate instructions
    verilog += I.newline(1)
    for ins_type in instructions:
        if ins_type != "NOP":
            verilog += I.signal_def(1, "wire", "FORMAT_"+ins_type, num_spaces=2)
            verilog += I.newline(1)
        verilog += I.signal_def(1, "wire", "ALLOWED_"+ins_type, num_spaces=2)
        verilog += I.newline(1)
        for ins in instructions[ins_type]:
            if ins != "CONSTRAINT":
                verilog += I.signal_def(1, "wire", ins, num_spaces=2)
                verilog += I.newline(1)
        verilog += I.newline(1)

    # Assign bit fields
    for bit_field in bit_fields:
        if bit_field != "CONSTRAINT":
            msb, lsb = bit_fields[bit_field].split()
            verilog += I.assign_def(bit_field, I.signal_index("instruction", msb, lsb), num_spaces=2)
            verilog += I.newline(1)

    # Assign instruction types
    verilog += I.newline(1)
    for ins_type in instructions:
        type_constraints = instructions[ins_type]["CONSTRAINT"]
        constraints = type_constraints

        if qed_constraints["half_registers"] == "1":
            fields = ins_fields[ins_type].split()
            for field in fields:
                if field in registers:
                    constraints.append(I._lt(field, str(int(isa_info["num_registers"])/2), parens=True))

        if ins_type != "NOP" and len(constraints) > 0:
            expression = constraints[0]
            for i in range(1, len(constraints)):
                expression = I._and(expression, constraints[i], parens=False)

            verilog += I.assign_def("FORMAT_"+ins_type, expression, num_spaces=2)
            verilog += I.newline(1)

        allowed_expression = ""
        for ins in instructions[ins_type]:
            if ins != "CONSTRAINT":
                fields = instructions[ins_type][ins]
                reqs = fields["CONSTRAINT"]
                for field in fields:
                    if field != "CONSTRAINT":
                        if type(fields[field]) == type([]):
                            first = fields[field][0]
                            req_expression = I._equals(field, I._constant(len(first), first), parens=True)
                            for req in fields[field][1:]:
                                equality = I._equals(field, I._constant(len(req), req), parens=True)
                                req_expression = I._or(req_expression, equality, parens=False)
                            req_expression = "(" + req_expression + ")"
                            reqs.append(req_expression)
                        else:
                            equality = I._equals(field, I._constant(len(fields[field]), fields[field]), parens=True)
                            reqs.append(equality)

                if ins != "NOP":
                    reqs_expression = "FORMAT_" + ins_type
                    for i in range(len(reqs)):
                        reqs_expression = I._and(reqs_expression, reqs[i], parens=False)
                else:
                    reqs_expression = reqs[0]
                    for i in range(1, len(reqs)):
                        reqs_expression = I._and(reqs_expression, reqs[i], parens=False)

                verilog += I.assign_def(ins, reqs_expression, num_spaces=2)
                verilog += I.newline(1)

                if allowed_expression == "":
                    allowed_expression = ins
                else:
                    allowed_expression = I._or(allowed_expression, ins, parens=False)

        verilog += I.assign_def("ALLOWED_"+ins_type, allowed_expression, num_spaces=2)
        verilog += I.newline(2)

    # Property assertion
    assertions = instructions.keys()
    property_expression = ""
    for ins_type in assertions:
        if property_expression == "":
            property_expression = "ALLOWED_" + ins_type
        else:
            property_expression = I._or(property_expression, "ALLOWED_"+ins_type, parens=False)

    verilog += I.always_def("clk", num_spaces=2) + I.begin(num_spaces=1)
    verilog += I.newline(1)
    verilog += I.property_def(property_expression, num_spaces=4)
    verilog += I.newline(1)
    verilog += I.end(num_spaces=2)
    verilog += I.newline(1)

    # End module with footer
    verilog += I.newline(1)
    verilog += I.module_footer()

    return verilog 
def generate_modify_file(MODULENAME, INPUTS, OUTPUTS, format_dicts):
    # Get ISA information
    isa_info = format_dicts["ISA"]
    # Get register names
    registers = format_dicts["REGISTERS"]
    # Get memory fields needed for modification
    memory = format_dicts["MEMORY"]
    # Get constraints for qed module setup
    qed_constraints = format_dicts["QEDCONSTRAINTS"]
    # Get the instruction types
    ins_types = format_dicts["INSTYPES"]
    # Get the instruction fields for each type
    ins_fields = format_dicts["INSFIELDS"]
    # Get instruction types requirements
    ins_reqs = format_dicts["INSREQS"]
    # Get the bit fields
    bit_fields = format_dicts["BITFIELDS"]
    # Get all instruction types
    instructions = {}
    for ins in format_dicts["INSTYPES"].keys():
        if ins != "CONSTRAINT":
            instructions[ins] = format_dicts[ins]

    # Verilog file
    verilog = ""

    # Fill out the INPUTS dict
    for bit_field in bit_fields:
        if bit_field != "CONSTRAINT":
            msb, lsb = bit_fields[bit_field].split()
            bits = int(msb) - int(lsb) + 1
            INPUTS[bit_field] = bits

    for ins_type in instructions:
        if ins_type in ins_reqs:
            INPUTS["IS_" + ins_type] = 1

    verilog += I.module_header(MODULENAME, INPUTS, OUTPUTS)
    verilog += I.newline(2)

    # Instantiate inputs
    for inp in INPUTS:
        verilog += I.signal_def(INPUTS[inp], "input", inp, num_spaces=2)
        verilog += I.newline(1)

    # Instantiate outputs
    verilog += I.newline(1)
    for out in OUTPUTS:
        verilog += I.signal_def(OUTPUTS[out], "output reg", out, num_spaces=2)
        verilog += I.newline(1)

    # Instantiate new instruction types wires
    verilog += I.newline(1)
    for ins_type in ins_reqs:
        verilog += I.signal_def(int(isa_info["instruction_length"]),
                                "wire",
                                "INS_" + ins_type,
                                num_spaces=2)
        verilog += I.newline(1)

    # Instantiate the new registers and immediate values
    verilog += I.newline(1)
    if qed_constraints["half_registers"] == "1":
        for reg in registers:
            if reg != "CONSTRAINT":
                msb, lsb = bit_fields[reg].split()
                bits = int(msb) - int(lsb) + 1
                verilog += I.signal_def(bits,
                                        "wire",
                                        "NEW_" + reg,
                                        num_spaces=2)
                verilog += I.newline(1)

    if qed_constraints["half_memory"] == "1":
        for mem in memory:
            if mem != "CONSTRAINT":
                msb, lsb = bit_fields[mem].split()
                bits = int(msb) - int(lsb) + 1
                verilog += I.signal_def(bits,
                                        "wire",
                                        "NEW_" + mem,
                                        num_spaces=2)
                verilog += I.newline(1)

    # Keeps track of modified fields
    modified_fields = []

    # Assign the new values for the registers
    verilog += I.newline(1)
    if qed_constraints["half_registers"] == "1":
        for reg in registers:
            if reg != "CONSTRAINT":
                msb, lsb = bit_fields[reg].split()
                bits = int(msb) - int(lsb) + 1
                equals_zero = I._equals(reg, I._constant(bits, "0" * bits),
                                        True)
                new_reg = I.bit_vector([
                    I._constant(1, "1"),
                    I.signal_index(reg, str(bits - 2), "0")
                ])
                cond = I.inline_conditional(equals_zero, reg, new_reg, False)
                verilog += I.assign_def("NEW_" + reg, cond, num_spaces=2)
                verilog += I.newline(1)
                modified_fields.append(reg)

    if qed_constraints["half_memory"] == "1":
        for mem in memory:
            if mem != "CONSTRAINT":
                msb, lsb = bit_fields[mem].split()
                bits = int(msb) - int(lsb) + 1
                new_mem = I.bit_vector([
                    I._constant(2, "01"),
                    I.signal_index(mem, str(bits - 3), "0")
                ])
                verilog += I.assign_def("NEW_" + mem, new_mem)
                verilog += I.newline(1)
                modified_fields.append(mem)

    # Assign the new instruction types with the modified fields
    verilog += I.newline(1)
    if len(ins_types["CONSTRAINT"]) > 0:
        ins_types_defs = {}
        for c in ins_types["CONSTRAINT"]:
            parts = c.split(",")
            ins_types_defs[parts[0]] = parts[1:]

        mem_types = ins_types_defs["MEMORYTYPE"]
    else:
        mem_types = []

    for ins_type in ins_reqs:
        if ins_type != "CONSTRAINT":
            fields = ins_fields[ins_type].split()
            new_fields = []
            for field in fields:
                if ((field in modified_fields and field in registers)
                        or (field in modified_fields and field in memory
                            and ins_type in mem_types)):
                    new_fields.append("NEW_" + field)
                else:
                    new_fields.append(field)
            verilog += I.assign_def("INS_" + ins_type,
                                    I.bit_vector(new_fields),
                                    num_spaces=2)
            verilog += I.newline(1)

    # Assign the final qed instruction output after modification
    verilog += I.newline(1)
    output_instruction = OUTPUTS.keys()[0]
    types = ins_reqs.keys()
    types.remove("CONSTRAINT")
    conditional = ""
    for i in range(len(types)):
        ins_type = types[i]
        if i < len(types) - 1:
            false = "("
        else:
            false = "qic_qimux_instruction"
        conditional += I.inline_conditional("IS_" + ins_type,
                                            "INS_" + ins_type, false, False)
    conditional += (len(types) - 1) * ")"
    verilog += I.assign_def(output_instruction, conditional, num_spaces=2)
    verilog += I.newline(1)

    # This code does the same thing as above,
    # but utilizes the always_comb logic
    # to make it more readable. However
    # this will cause certain verilog compilers
    # to complain.
    """
    verilog += I.always_comb_def(num_spaces=2)
    verilog += I.newline(1)
    output_instruction = OUTPUTS.keys()[0]
    types = ins_reqs.keys()
    types.remove("CONSTRAINT")
    for i in range(len(types)+1):
        if i == 0:
            ins_type = types[i]
            verilog += I.if_header("IS_"+ins_type, num_spaces=4)
        elif i < len(types):
            ins_type = types[i]
            verilog += I.else_if_header("IS_"+ins_type, num_spaces=4)
        else:
            verilog += I.else_header(num_spaces=4)
            verilog += I.newline(1)
            verilog += I.direct_assignment_def(output_instruction, "qic_qimux_instruction", num_spaces=6)
            verilog += I.newline(1)
            verilog += I.end(num_spaces=4)
            verilog += I.newline(1)
            continue

        verilog += I.newline(1)
        verilog += I.direct_assignment_def(output_instruction, "INS_"+ins_type, num_spaces=6)
        verilog += I.newline(1)
        verilog += I.end(num_spaces=4)
        verilog += I.newline(1)
    verilog += I.end(num_spaces=2)
    verilog += I.newline(1)
    """

    # Module footer
    verilog += I.newline(1)
    verilog += I.module_footer()

    return verilog
            expression = I._and(expression, constraints[i], parens=False)

        verilog += I.assign_def("FORMAT_" + ins_type, expression, num_spaces=2)
        verilog += I.newline(1)

    allowed_expression = ""
    for ins in instructions[ins_type]:
        if ins != "CONSTRAINT":
            fields = instructions[ins_type][ins]
            reqs = []
            for field in fields:
                if field != "CONSTRAINT":
                    req = fields[field]
                    reqs.append(
                        I._equals(field,
                                  I._constant(len(req), req),
                                  parens=True))

            #if len(instructions[ins_type]["CONSTRAINT"]) > 0:
            if ins != "NOP":
                reqs_expression = "FORMAT_" + ins_type
                for i in range(len(reqs)):
                    reqs_expression = I._and(reqs_expression,
                                             reqs[i],
                                             parens=False)
            else:
                reqs_expression = reqs[0]
                for i in range(1, len(reqs)):
                    reqs_expression = I._and(reqs_expression,
                                             reqs[i],
                                             parens=False)
verilog += I.signal_def(12, "wire", "NEW_imm12", num_spaces=2)
verilog += I.newline(1)
verilog += I.signal_def(7, "wire", "NEW_imm7", num_spaces=2)
verilog += I.newline(1)

# Keeps track of modified fields
modified_fields = []

# Assign the new values for the registers
verilog += I.newline(1)
if qed_constraints["half_registers"] == "1":
    for reg in registers:
        if reg != "CONSTRAINT":
            msb, lsb = bit_fields[reg].split()
            bits = int(msb) - int(lsb) + 1
            equals_zero = I._equals(reg, I._constant(bits, "0" * bits), True)
            new_reg = I.bit_vector(
                ["1'b1", I.signal_index(reg, str(bits - 2), "0")])
            cond = I.inline_conditional(equals_zero, reg, new_reg, False)
            verilog += I.assign_def("NEW_" + reg, cond, num_spaces=2)
            verilog += I.newline(1)
            modified_fields.append(reg)

# Temporary fix
verilog += I.assign_def("NEW_imm12",
                        I.bit_vector(
                            ["2'b01",
                             I.signal_index("imm12", "9", "0")]),
                        num_spaces=2)
verilog += I.newline(1)
modified_fields.append("imm12")
                                I.signal_index(INPUTS.keys()[0], msb, lsb),
                                num_spaces=2)
        verilog += I.newline(1)

# Assign instruction types requirements
verilog += I.newline(1)
for ins_type in instructions:
    if not ins_type in ins_reqs:
        continue
    ins_req = ins_reqs[ins_type]
    reqs = []
    for req in ins_req:
        if req != "CONSTRAINT":
            reqs.append(
                I._equals(req,
                          I._constant(len(ins_req[req]), ins_req[req]),
                          parens=True))

    reqs_expression = reqs[0]
    for i in range(1, len(reqs)):
        reqs_expression = I._and(reqs_expression, reqs[i], parens=False)

    verilog += I.assign_def("IS_" + ins_type, reqs_expression, num_spaces=2)
    verilog += I.newline(1)

# Module footer
verilog += I.newline(1)
verilog += I.module_footer()

f = open("../QEDFiles/qed_decoder.v", 'w')
f.write(verilog)