def make_file_read(self, i, action): assert file_mode_allows_reading(action.file.mode), \ f'File mode {action.file.mode} is not compatible with reading.' idx = 'i' fd = self.fd_var(action.file) in_ = self.in_var(action.file) err_msg = f'Reached end of file {action.file.name_without_ext}' return self.generate_action_code(i, [ Loop(loop_var=idx, n_iter=action.file.chunk_size, count='down' if action.file.endianness == 'big' else 'up', actions=[ f'int result = fgetc({fd});', If(f'result == EOF', [f'std::cout << "{err_msg}" << std::endl;', 'break;']), f'{in_}[{idx}] = result;' ]) ])
def make_file_write(self, i, action): assert file_mode_allows_writing(action.file.mode), \ f'File mode {action.file.mode} is not compatible with writing.' idx = 'i' fd = self.fd_var(action.file) value = f'top->{verilator_name(action.value.name)}' byte_expr = f'({value} >> ({idx} * 8)) & 0xFF' err_msg = f'Error writing to {action.file.name_without_ext}' return self.generate_action_code(i, [ Loop(loop_var=idx, n_iter=action.file.chunk_size, count='down' if action.file.endianness == 'big' else 'up', actions=[ 'int result = ' + self.write_byte(fd, byte_expr) + ';', If(f'result == EOF', [f'std::cout << "{err_msg}" << std::endl;', 'break;']), ]) ])
def make_file_open(self, i, action): # make sure the file mode is supported if not is_valid_file_mode(action.file.mode): raise NotImplementedError(action.file.mode) # declare the file read variable if the file mode allows reading if file_mode_allows_reading(action.file.mode): in_ = self.in_var(action.file) decl_rd_var = [f'char {in_}[{action.file.chunk_size}] = {{0}};'] else: decl_rd_var = [] fd = self.fd_var(action.file) err_msg = f'Could not open file {action.file.name}' return self.generate_action_code( i, decl_rd_var + [ f'FILE *{fd} = fopen("{action.file.name}", "{action.file.mode}");', If(f'{fd} == NULL', [f'std::cout << "{err_msg}" << std::endl;', f'return 1;']) ])
def _if(self, cond): if_tester = IfTester(self._circuit, self.clock) self.actions.append(If(cond, if_tester.actions, if_tester.else_actions)) return if_tester
def make_expect(self, i, action): # don't do anything if any value is OK if value_utils.is_any(action.value): return [] # determine the exact name of the signal name = self.make_name(action.port) # TODO: add something like "make_read_name" and "make_write_name" # so that reading inout signals has more uniform behavior across # expect, peek, etc. if actions.is_inout(action.port): name = self.input_wire(name) # determine the name of the signal for debugging purposes if isinstance(action.port, SelectPath): debug_name = action.port[-1].name elif isinstance(action.port, fault.WrappedVerilogInternalPort): debug_name = name else: debug_name = action.port.name # determine the value to be checked value = self.process_value(action.port, action.value) # determine the condition and error body err_hdr = '' err_hdr += f'Failed on action={i} checking port {debug_name}' if action.traceback is not None: err_hdr += f' with traceback {action.traceback}' if action.above is not None: if action.below is not None: # must be in range cond = f'(({action.above} <= {name}) && ({name} <= {action.below}))' # noqa err_msg = 'Expected %0f to %0f, got %0f' err_args = [action.above, action.below, name] else: # must be above cond = f'({action.above} <= {name})' err_msg = 'Expected above %0f, got %0f' err_args = [action.above, name] else: if action.below is not None: # must be below cond = f'({name} <= {action.below})' err_msg = 'Expected below %0f, got %0f' err_args = [action.below, name] else: # equality comparison if action.strict: cond = f'({name} === {value})' else: cond = f'({name} == {value})' err_msg = 'Expected %x, got %x' err_args = [value, name] if action.msg is not None: if isinstance(action.msg, str): err_msg += "\\n" + action.msg else: assert isinstance(action.msg, tuple) err_msg += "\\n" + action.msg[0] err_args += self._make_print_args(action.msg[1:]) # construct the body of the $error call err_fmt_str = f'"{err_hdr}. {err_msg}."' err_body = [err_fmt_str] + err_args err_body = ', '.join([str(elem) for elem in err_body]) if self.use_sva: return [f'assert ({cond}) else $error({err_body});'] else: # return a snippet of verilog implementing the assertion return self.make_if(i, If(f'!{cond}', [f'$error({err_body});']))