code: def step(self, provided_inputs):
          
          # validate_inputs
          for wire, value in provided_inputs.items():
              wire = self.block.get_wirevector_by_name(wire) if isinstance(wire, str) else wire
              if value > wire.bitmask or value < 0:
                  raise PyrtlError("Wire {} has value {} which cannot be represented"
                                   " using its bitwidth".format(wire, value))
  
          # building the simulation data
          ins = {self._to_name(wire): value for wire, value in provided_inputs.items()}
          ins.update(self.regs)
          ins.update(self.mems)
  
          # propagate through logic
          self.regs, self.outs, mem_writes = self.sim_func(ins)
  
          for mem, addr, value in mem_writes:
              self.mems[mem][addr] = value
  
          # for tracer compatibility
          self.context = self.outs.copy()
          self.context.update(ins)  # also gets old register values
          if self.tracer is not None:
              self.tracer.add_fast_step(self)
  
          # check the rtl assertions
          check_rtl_assertions(self)
docs: Run the simulation for a cycle
  
          :param provided_inputs: a dictionary mapping WireVectors (or their names)
            to their values for this step
            eg: {wire: 3, "wire_name": 17}