From 6f88e8477f76c422267cdbee990e395a923d8ee9 Mon Sep 17 00:00:00 2001 From: jjsuperpower Date: Sat, 4 Feb 2023 00:45:35 -0600 Subject: allowing for control signals with differnet width --- hdl/core/control.py | 112 ++++++++++++++++++++++++++++++++++++---------- hdl/core/machine_code.csv | 96 ++++++++++++++++++++------------------- 2 files changed, 138 insertions(+), 70 deletions(-) diff --git a/hdl/core/control.py b/hdl/core/control.py index 855cd3b..d858812 100644 --- a/hdl/core/control.py +++ b/hdl/core/control.py @@ -11,7 +11,7 @@ from hdl.config import MACHINE_CODE_CSV import csv MAX_INSTR = 2**8 # do not change this, this is not configurable -CL_NAMES = ['mode'] +CL_NAMES = ['mode', 'valid_op', 'wb_en', 'alu_op', 'is_imm', 'jump_en', 'mem_wr_en', 'mem_rd_en', 'mem_rw_word'] class Control_LUT(Elaboratable): def __init__(self, csv_file, cl_names, **kargs): # cl_names is a list of control line in order of msb to lsb @@ -19,27 +19,79 @@ class Control_LUT(Elaboratable): self.cl_names = cl_names self.sim = kargs.get("sim", False) + def elaborate(self, platform=None): + pass + #TODO: implment this to create signals with the same names as the control lines specified + def create_lut(self): - self.csv_raw = self._read_csv(self.csv_file) - self.csv_parsed = self._parse_csv(self.csv_raw) - self.mem_init = self._create_mem_init(self.csv_parsed) + csv_raw = self._read_csv(self.csv_file) + control_list = self._parse_csv(csv_raw) + mem_width, slice_mapping = self._get_slice_mapping(control_list) + + print('debug') + print(CL_NAMES) + print(mem_width, slice_mapping) + print(control_list[10]) + print(self._create_entry(control_list[10]['data'], mem_width, slice_mapping)) - self.mem = Memory(width=len(self.cl_names) + 1, depth=MAX_INSTR, init=self.mem_init, simulate=self.sim) # one extra bit for valid opcode + # self.mem_init = self._create_mem_init(self.csv_parsed) + # self.mem = Memory(width=len(self.cl_names) + 1, depth=MAX_INSTR, init=self.mem_init, simulate=self.sim) # one extra bit for valid opcode # read csv file and return a list of dictionaries def _read_csv(self, csv_file): - csv_raw = [] with open(csv_file, 'r') as f: reader = csv.DictReader(f) return list(reader) - + + def _get_slice_mapping(self, control_list): - def _list_to_one_hot(self, lst): - tmp = 0 - for i in range(len(lst)): - tmp |= (lst[i] << i) + # helper function to count the number of bits in a number + def count_bits(num:int): + return len(bin(num)[2:]) # remove the '0b' prefix + + # find the max bit length of the control lines per entry + max_width_list = [count_bits(cl) for cl in control_list[0]['data']] + for entry in control_list: + for i, cl in enumerate(entry['data']): + max_width_list[i] = max(max_width_list[i], count_bits(cl)) + + # calculate how many bits for each entry + mem_width = sum(max_width_list) + slice_mapping = [] + accum = 0 + + # generate the slice mapping + for i, cl in enumerate(max_width_list): + slice_mapping.append(slice(accum, accum + max_width_list[i])) + accum += max_width_list[i] + + return mem_width, slice_mapping + - return tmp + def _create_entry(self, control, mem_width, slice_mapping): + + # check that the slices map to the correct number of bits + assert(slice_mapping[-1].stop == mem_width), 'slice mapping is not continuous, this is an internal error' + + def bin_stripped(num): + return bin(num)[2:] + + def pad_zero(num_str, width): + return '0' * (width - len(num_str)) + num_str + + # create the entry with all zeros + entry_str_list = ['0'] * mem_width + + # fill in the control lines, lsb left, msb right + for (cl, s) in zip(control, slice_mapping): + entry_str_list[s.start:s.stop] = list(reversed(list(pad_zero(bin_stripped(cl), s.stop - s.start)))) # signals read from left to right, so reverse the string + + # conversion to int requires lsb right, msb left + entry_str = ''.join(reversed(entry_str_list)) + + # convert to int + entry = int('0b' + entry_str, 2) + return entry def _parse_csv(self, csv_raw): csv_parsed = [] @@ -50,12 +102,19 @@ class Control_LUT(Elaboratable): tmp['data'] = [] for cl in self.cl_names: - tmp['data'].append(bool(int(row[cl]))) # needs to be converted to int first because boolof a string is true + try: + tmp['data'].append(int(row[cl])) + except KeyError: + print(f'control line "{cl}" not found in csv file') + raise csv_parsed.append(tmp) return csv_parsed + + def _alloc_mem(self, csv_parsed): + pass - def _create_mem_init(self, csv_parsed): + def _create_init(self, csv_parsed): mem_init = [] for i in range(MAX_INSTR): @@ -67,7 +126,6 @@ class Control_LUT(Elaboratable): for cl in row['data']: mem_init[row['opcode']] = cl - mem_init[row['opcode']] = (mem_init[row['opcode']] << 1) | 0x1 # set the valid opcode bit return mem_init @@ -80,13 +138,22 @@ class Control(Elaboratable): self.alu_op = Signal(e2s(AluOpCodes)) self.jump_ctl_op = Signal(e2s(JumpOpCodes)) - # register control out - self.wr_en = Signal(1) - self.stall = Signal(1) - self.int_sig = Signal(1) - self.iret = Signal(1) - self.call = Signal(1) - self.jump = Signal(1) + # syncronous control signals + self.valid_op = Signal() + self.wb_en = Signal() + self.alu_op = Signal(e2s(AluOpCodes)) + self.is_imm = Signal() + self.jump_en = Signal() + self.mem_wr_en = Signal() + self.mem_rd_en = Signal() + self.mem_rw_word = Signal() + + + self.stall = Signal() + self.int_sig = Signal() + self.iret = Signal() + self.call = Signal() + self.jump = Signal() # register control in self.int_en = Signal(1) @@ -123,7 +190,6 @@ class Control(Elaboratable): def test_control_mem_init(): lut = Control_LUT(MACHINE_CODE_CSV, CL_NAMES, sim=True) lut.create_lut() - print(lut.mem_init) if __name__ == '__main__': test_control_mem_init() diff --git a/hdl/core/machine_code.csv b/hdl/core/machine_code.csv index 96e73d5..d1799aa 100644 --- a/hdl/core/machine_code.csv +++ b/hdl/core/machine_code.csv @@ -1,47 +1,49 @@ -name,type,opcode,mode,description,notes -ADD,R,1,1,RD = RS1 + RS2, -ADDC,R,2,1,RD = RS1 + RS2 + FLG[0], -SUB,R,3,1,RD = RS1 - RS2, -SUBC,R,4,1,RD = RS1 - RS2 - FLG[0], -XOR,R,5,1,RD = RS1 ^ RS2, -OR,R,6,1,RD = RS1 | RS2, -AND,R,7,1,RD = RS1 & RS2, -LSL,R,8,1,RD = RS1 << RS2 (logical), -LSR,R,9,1,RD = RS1 >> RS2 (logical), -ASR,R,10,1,RD = RS1 >> RS2, -MULL,R,11,1,RD = (RS1 * RS2) & 0xFFFFFFFF, -MULH,R,12,1,RD = (RS1 * RS2) >> 32, -MULLU,R,13,1,RD = RS1 * RS2 & 0xFFFFFFFF (unsigned), -MULHU,R,14,1,RD = (RS1 * RS2) >> 32 (unsigned), -DIV,R,15,1,RD = RS1 / RS2,not implemented yet -DIVU,R,16,1,RD = RS1 / RS2 (unsigned),not implemented yet -LDW,R,17,1,RD = MEM[RS1 + offset], -LDWR,R,18,1,RD = MEM[RS1 + RS2], -STW,R,19,1,MEM[RS1 + offset] = RS2, -LDB,R,20,1,RD = MEM[RS1 + offset] & 0xFF, -LDBR,R,21,1,RD = MEM[RS1 + RS2] & 0xFF, -STB,R,22,1,MEM[RS1 + offset] = RS2 & 0xFF, -ADDI,I,64,1,RD = RS + IMM, -ADDIC,I,65,1,RD = RS + IMM + FLG[0], -SUBI,I,66,1,RD = RS - IMM, -SUBIC,I,67,1,RD = RS - IMM - FLG[0], -XORI,I,68,1,RD = RS ^ IMM, -ORI,I,69,1,RD = RS | IMM, -ANDI,I,70,1,RD = RS & IMM, -LSLI,I,71,1,RD = RS << IMM (logical), -LSRI,I,72,1,RD = RS >> IMM (logical), -ASRI,I,73,1,RD = RS >> IMM, -MULIL,I,74,1,RD = (RS * IMM) & 0xFFFFFFFF, -MULIH,I,75,1,RD = (RS * IMM) >> 32, -MULIU,I,76,1,RD = (RS * IMM) & 0xFFFFFFFF (unsigned), -MULIUH,I,77,1,RD = (RS * IMM) >> 32 (unsigned), -DIVI,I,78,1,RD = RS / IMM,not implemented yet -DIVUI,I,79,1,RD = RS / IMM (unsigned),not implemented yet -JMP,J,128,1,op depends on machine code, -JMPI,J,129,1,op depends on machine code, -NOP,C,0,1,Do nothing -> opcode = ZERO , -CALL,C,160,1,CS0=IP; IP=CS0, -RET,C,161,1,"IP = CS0, this is implemented using jmp or call instruction", -SCALL,C,162,1,CS0=IP; CS1=SP; CS2=FLG; IP=IDT[6]; SP=CS1; FLG[16]=0; FLG[17]=0;, -INT,C,192,0,CS0=IP; CS1=SP; CS2=FLG; IP=IDT[IMM]; SP=CS1; FLG[16]=0; FLG[17]=0;, -IRET,C,193,0,IP=CS0; SP=CS1; FLG=CS2;, \ No newline at end of file +name,type,opcode,mode,description,notes,valid_op,wb_en,alu_op,is_imm,jump_en,mem_wr_en,mem_rd_en,mem_rw_word +ADD,R,1,1,RD = RS1 + RS2,,1,1,0,0,0,0,0,0 +ADDC,R,2,1,RD = RS1 + RS2 + FLG[0],,1,1,1,0,0,0,0,0 +SUB,R,3,1,RD = RS1 - RS2,,1,1,2,0,0,0,0,0 +SUBC,R,4,1,RD = RS1 - RS2 - FLG[0],,1,1,3,0,0,0,0,0 +XOR,R,5,1,RD = RS1 ^ RS2,,1,1,6,0,0,0,0,0 +OR,R,6,1,RD = RS1 | RS2,,1,1,5,0,0,0,0,0 +AND,R,7,1,RD = RS1 & RS2,,1,1,4,0,0,0,0,0 +NOR,R,8,1,RD = ~(RS1 | RS2),,1,1,7,0,0,0,0,0 +LSL,R,9,1,RD = RS1 << RS2 (logical),,1,1,8,0,0,0,0,0 +LSR,R,10,1,RD = RS1 >> RS2 (logical),,1,1,9,0,0,0,0,0 +ASR,R,11,1,RD = RS1 >> RS2,,1,1,10,0,0,0,0,0 +MULL,R,12,1,RD = (RS1 * RS2) & 0xFFFFFFFF,,1,1,13,0,0,0,0,0 +MULH,R,13,1,RD = (RS1 * RS2) >> 32,,1,1,14,0,0,0,0,0 +MULLU,R,14,1,RD = RS1 * RS2 & 0xFFFFFFFF (unsigned),,1,1,11,0,0,0,0,0 +MULHU,R,15,1,RD = (RS1 * RS2) >> 32 (unsigned),,1,1,12,0,0,0,0,0 +DIV,R,16,1,RD = RS1 / RS2,not implemented yet,0,0,0,0,0,0,0,0 +DIVU,R,17,1,RD = RS1 / RS2 (unsigned),not implemented yet,0,0,0,0,0,0,0,0 +LDW,R,18,1,RD = MEM[RS1 + offset],,1,1,0,0,0,0,1,1 +LDWR,R,19,1,RD = MEM[RS1 + RS2],,1,1,0,0,0,0,1,1 +STW,R,20,1,MEM[RS1 + offset] = RS2,,1,0,0,0,0,1,0,1 +LDB,R,21,1,RD = MEM[RS1 + offset] & 0xFF,,1,1,0,0,0,0,1,0 +LDBR,R,22,1,RD = MEM[RS1 + RS2] & 0xFF,,1,1,0,0,0,0,1,0 +STB,R,23,1,MEM[RS1 + offset] = RS2 & 0xFF,,1,0,0,0,0,1,0,0 +ADDI,I,64,1,RD = RS + IMM,,1,1,0,1,0,0,0,0 +ADDIC,I,65,1,RD = RS + IMM + FLG[0],,1,1,1,1,0,0,0,0 +SUBI,I,66,1,RD = RS - IMM,,1,1,2,1,0,0,0,0 +SUBIC,I,67,1,RD = RS - IMM - FLG[0],,1,1,3,1,0,0,0,0 +XORI,I,68,1,RD = RS ^ IMM,,1,1,6,1,0,0,0,0 +ORI,I,69,1,RD = RS | IMM,,1,1,5,1,0,0,0,0 +ANDI,I,70,1,RD = RS & IMM,,1,1,4,1,0,0,0,0 +NORI,I,71,1,RD = ~(RS1 | IMM),,1,1,7,1,0,0,0,0 +LSLI,I,72,1,RD = RS << IMM (logical),,1,1,8,1,0,0,0,0 +LSRI,I,73,1,RD = RS >> IMM (logical),,1,1,9,1,0,0,0,0 +ASRI,I,74,1,RD = RS >> IMM,,1,1,10,1,0,0,0,0 +MULIL,I,75,1,RD = (RS * IMM) & 0xFFFFFFFF,,1,1,13,1,0,0,0,0 +MULIH,I,76,1,RD = (RS * IMM) >> 32,,1,1,14,1,0,0,0,0 +MULIUL,I,77,1,RD = (RS * IMM) & 0xFFFFFFFF (unsigned),,1,1,11,1,0,0,0,0 +MULIUH,I,78,1,RD = (RS * IMM) >> 32 (unsigned),,1,1,12,1,0,0,0,0 +DIVI,I,79,1,RD = RS / IMM,not implemented yet,0,0,0,1,0,0,0,0 +DIVUI,I,80,1,RD = RS / IMM (unsigned),not implemented yet,0,0,0,1,0,0,0,0 +JMP,J,128,1,op depends on machine code,,1,0,0,0,1,0,0,0 +JMPI,J,129,1,op depends on machine code,,1,0,0,1,1,0,0,0 +NOP,C,0,1,Do nothing -> opcode = ZERO ,,1,0,0,0,0,0,0,0 +CALL,C,160,1,CS0=IP; IP=CS0,,1,0,0,0,0,0,0,0 +RET,C,161,1,"IP = CS0, this is implemented using jmp or call instruction",,1,0,0,0,0,0,0,0 +SCALL,C,162,1,CS0=IP; CS1=SP; CS2=FLG; IP=IDT[6]; SP=CS1; FLG[16]=0; FLG[17]=0;,,1,0,0,0,0,0,0,0 +INT,C,192,0,CS0=IP; CS1=SP; CS2=FLG; IP=IDT[IMM]; SP=CS1; FLG[16]=0; FLG[17]=0;,,1,0,0,0,0,0,0,0 +IRET,C,193,0,IP=CS0; SP=CS1; FLG=CS2;,,1,0,0,0,0,0,0,0 -- cgit v1.2.3