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
def generate_qed_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 verilog += I.newline(1) for out in OUTPUTS: verilog += I.signal_def(OUTPUTS[out], "output", out, num_spaces=2) verilog += I.newline(1) # Instantiate bit fields as wires 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 new instruction types wires verilog += I.newline(1) for ins_type in ins_reqs: if ins_type != "CONSTRAINT": verilog += I.signal_def(1, "wire", "IS_" + ins_type, num_spaces=2) verilog += I.newline(1) # Instantiate internal instruction versions verilog += I.newline(1) verilog += I.signal_def(int(isa_info["instruction_length"]), "wire", "qed_instruction", num_spaces=2) verilog += I.newline(1) verilog += I.signal_def(int(isa_info["instruction_length"]), "wire", "qic_qimux_instruction", num_spaces=2) verilog += I.newline(2) # Decoder module decoder_args = ["qic_qimux_instruction"] decoder_args = decoder_args + list(bit_fields.keys()) decoder_args.remove("CONSTRAINT") decoder_args = decoder_args + [("IS_" + key) for key in ins_reqs] decoder_args.remove("IS_CONSTRAINT") signals = decoder_args names = copy.deepcopy(signals) names[0] = "ifu_qed_instruction" verilog += I.module_def("qed_decoder", "dec", names, signals, num_spaces=2) verilog += I.newline(2) # Modify module modify_args = ["qed_instruction", "qic_qimux_instruction"] modify_args = modify_args + list(bit_fields.keys()) modify_args.remove("CONSTRAINT") modify_args = modify_args + [("IS_" + key) for key in ins_reqs] modify_args.remove("IS_CONSTRAINT") signals = modify_args names = modify_args verilog += I.module_def("modify_instruction", "minst", names, signals, num_spaces=2) verilog += I.newline(2) # Mux module mux_args = [ "qed_ifu_instruction", "ifu_qed_instruction", "qed_instruction", "exec_dup", "ena" ] signals = mux_args names = mux_args verilog += I.module_def("qed_instruction_mux", "imux", names, signals, num_spaces=2) verilog += I.newline(2) # Cache module cache_args = [ "qic_qimux_instruction", "vld_out", "clk", "rst", "exec_dup", "stall_IF", "ifu_qed_instruction" ] signals = cache_args names = copy.deepcopy(signals) names[-2] = "IF_stall" verilog += I.module_def("qed_i_cache", "qic", names, signals, num_spaces=2) verilog += I.newline(2) verilog += I.module_footer() return verilog
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
MODULENAME = "qed" INPUTS = { "clk": 1, "ifu_qed_instruction": int(isa_info["instruction_length"]), "rst": 1, "ena": 1, "exec_dup": 1, "stall_IF": 1 } OUTPUTS = { "qed_ifu_instruction": int(isa_info["instruction_length"]), "vld_out": 1 } # 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 verilog += I.newline(1) for out in OUTPUTS: verilog += I.signal_def(OUTPUTS[out], "output", out, num_spaces=2) verilog += I.newline(1) # Instantiate bit fields as wires for bit_field in bit_fields:
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